diff options
author | kato <kato@FreeBSD.org> | 1997-12-03 09:46:34 +0000 |
---|---|---|
committer | kato <kato@FreeBSD.org> | 1997-12-03 09:46:34 +0000 |
commit | 185fb48052f903a80b31786784cbb82fb059c35c (patch) | |
tree | 9a3831d11382b5d41f52e7ab5cefffb8aee9c325 | |
parent | 82c7f870ed2d82b91f3d99026d2c52e9ebb097d5 (diff) | |
download | FreeBSD-src-185fb48052f903a80b31786784cbb82fb059c35c.zip FreeBSD-src-185fb48052f903a80b31786784cbb82fb059c35c.tar.gz |
Sync with sys/i386/i386/machdep.c and trap.c revisions 1.275 and
1.116, respectively.
-rw-r--r-- | sys/pc98/i386/machdep.c | 44 | ||||
-rw-r--r-- | sys/pc98/i386/trap.c | 25 | ||||
-rw-r--r-- | sys/pc98/pc98/machdep.c | 44 |
3 files changed, 110 insertions, 3 deletions
diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index 7cd722c..cc4e032 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.61 1997/11/07 12:53:48 kato Exp $ + * $Id: machdep.c,v 1.62 1997/11/25 09:54:36 kato Exp $ */ #include "apm.h" @@ -878,6 +878,11 @@ u_int my_tr; /* which task register setting */ #endif /* VM86 */ #endif +#ifndef NO_F00F_HACK +struct gate_descriptor *t_idt; +int has_f00f_bug; +#endif + static struct i386tss dblfault_tss; static char dblfault_stack[PAGE_SIZE]; @@ -1571,6 +1576,43 @@ init386(first) proc0.p_addr->u_pcb.pcb_ext = 0; } +#ifndef NO_F00F_HACK +void f00f_hack(void); +SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL); + +void +f00f_hack(void) { + struct region_descriptor r_idt; + unsigned char *tmp; + int i; + vm_offset_t vp; + unsigned *pte; + + if (!has_f00f_bug) + return; + + printf("Intel Pentium F00F detected, installing workaround\n"); + + r_idt.rd_limit = sizeof(idt) - 1; + + tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2); + if (tmp == 0) + panic("kmem_alloc returned 0"); + if (((unsigned int)tmp & (PAGE_SIZE-1)) != 0) + panic("kmem_alloc returned non-page-aligned memory"); + /* Put the first seven entries in the lower page */ + t_idt = (struct gate_descriptor*)(tmp + PAGE_SIZE - (7*8)); + bcopy(idt, t_idt, sizeof(idt)); + r_idt.rd_base = (int)t_idt; + lidt(&r_idt); + vp = trunc_page(t_idt); + if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE, + VM_PROT_READ, FALSE) != KERN_SUCCESS) + panic("vm_map_protect failed"); + return; +} +#endif /* NO_F00F_HACK */ + int ptrace_set_pc(p, addr) struct proc *p; diff --git a/sys/pc98/i386/trap.c b/sys/pc98/i386/trap.c index 2b06769..fb9431f 100644 --- a/sys/pc98/i386/trap.c +++ b/sys/pc98/i386/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.38 1997/11/07 12:53:49 kato Exp $ + * $Id: trap.c,v 1.39 1997/11/25 09:53:44 kato Exp $ */ /* @@ -146,6 +146,11 @@ static char *trap_msg[] = { static void userret __P((struct proc *p, struct trapframe *frame, u_quad_t oticks)); +#ifndef NO_F00F_HACK +extern struct gate_descriptor *t_idt; +extern int has_f00f_bug; +#endif + static inline void userret(p, frame, oticks) struct proc *p; @@ -218,6 +223,9 @@ trap(frame) vm_offset_t va; #endif +#ifndef NO_F00F_HACK +restart: +#endif type = frame.tf_trapno; code = frame.tf_err; @@ -300,6 +308,10 @@ trap(frame) #endif if (i == -1) return; +#ifndef NO_F00F_HACK + if (i == -2) + goto restart; +#endif if (i == 0) goto out; @@ -692,7 +704,18 @@ trap_pfault(frame, usermode) if (va >= KERNBASE) { /* * Don't allow user-mode faults in kernel address space. + * An exception: if the faulting address is the invalid + * instruction entry in the IDT, then the Intel Pentium + * F00F bug workaround was triggered, and we need to + * treat it is as an illegal instruction, and not a page + * fault. */ +#ifndef NO_F00F_HACK + if ((eva == (unsigned int)&t_idt[6]) && has_f00f_bug) { + frame->tf_trapno = T_PRIVINFLT; + return -2; + } +#endif if (usermode) goto nogo; diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 7cd722c..cc4e032 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.61 1997/11/07 12:53:48 kato Exp $ + * $Id: machdep.c,v 1.62 1997/11/25 09:54:36 kato Exp $ */ #include "apm.h" @@ -878,6 +878,11 @@ u_int my_tr; /* which task register setting */ #endif /* VM86 */ #endif +#ifndef NO_F00F_HACK +struct gate_descriptor *t_idt; +int has_f00f_bug; +#endif + static struct i386tss dblfault_tss; static char dblfault_stack[PAGE_SIZE]; @@ -1571,6 +1576,43 @@ init386(first) proc0.p_addr->u_pcb.pcb_ext = 0; } +#ifndef NO_F00F_HACK +void f00f_hack(void); +SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL); + +void +f00f_hack(void) { + struct region_descriptor r_idt; + unsigned char *tmp; + int i; + vm_offset_t vp; + unsigned *pte; + + if (!has_f00f_bug) + return; + + printf("Intel Pentium F00F detected, installing workaround\n"); + + r_idt.rd_limit = sizeof(idt) - 1; + + tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2); + if (tmp == 0) + panic("kmem_alloc returned 0"); + if (((unsigned int)tmp & (PAGE_SIZE-1)) != 0) + panic("kmem_alloc returned non-page-aligned memory"); + /* Put the first seven entries in the lower page */ + t_idt = (struct gate_descriptor*)(tmp + PAGE_SIZE - (7*8)); + bcopy(idt, t_idt, sizeof(idt)); + r_idt.rd_base = (int)t_idt; + lidt(&r_idt); + vp = trunc_page(t_idt); + if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE, + VM_PROT_READ, FALSE) != KERN_SUCCESS) + panic("vm_map_protect failed"); + return; +} +#endif /* NO_F00F_HACK */ + int ptrace_set_pc(p, addr) struct proc *p; |