diff options
-rw-r--r-- | sys/amd64/amd64/identcpu.c | 14 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 44 | ||||
-rw-r--r-- | sys/amd64/amd64/trap.c | 25 | ||||
-rw-r--r-- | sys/i386/i386/identcpu.c | 14 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 44 | ||||
-rw-r--r-- | sys/i386/i386/trap.c | 25 | ||||
-rw-r--r-- | sys/kern/subr_trap.c | 25 |
7 files changed, 184 insertions, 7 deletions
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c index b1d4ba6..e299241 100644 --- a/sys/amd64/amd64/identcpu.c +++ b/sys/amd64/amd64/identcpu.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id: identcpu.c,v 1.32 1997/11/06 03:10:28 kato Exp $ + * $Id: identcpu.c,v 1.33 1997/11/07 08:52:27 phk Exp $ */ #include "opt_cpu.h" @@ -107,6 +107,10 @@ do_cpuid(u_long ax, u_long *p) ); } +#ifndef NO_F00F_HACK +int has_f00f_bug = 0; +#endif + void printcpuinfo(void) { @@ -136,6 +140,14 @@ printcpuinfo(void) break; case 0x500: strcat(cpu_model, "Pentium"); /* nb no space */ +#ifndef NO_F00F_HACK + /* + * XXX - If/when Intel fixes the bug, this + * should also check the version of the + * CPU, not just that it's a Pentium. + */ + has_f00f_bug = 1; +#endif break; case 0x600: strcat(cpu_model, "Pentium Pro"); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index db3d2f2..82ad9e5 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.273 1997/11/21 18:27:10 bde Exp $ + * $Id: machdep.c,v 1.274 1997/11/24 18:35:11 bde Exp $ */ #include "apm.h" @@ -866,6 +866,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]; @@ -1534,6 +1539,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/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index e53b015..9bebd7e 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.114 1997/11/06 19:28:09 phk Exp $ + * $Id: trap.c,v 1.115 1997/11/24 13:25:37 bde Exp $ */ /* @@ -142,6 +142,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; @@ -211,6 +216,9 @@ trap(frame) u_long eva; #endif +#ifndef NO_F00F_HACK +restart: +#endif type = frame.tf_trapno; code = frame.tf_err; @@ -276,6 +284,10 @@ trap(frame) i = trap_pfault(&frame, TRUE); if (i == -1) return; +#ifndef NO_F00F_HACK + if (i == -2) + goto restart; +#endif if (i == 0) goto out; @@ -642,7 +654,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/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index b1d4ba6..e299241 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id: identcpu.c,v 1.32 1997/11/06 03:10:28 kato Exp $ + * $Id: identcpu.c,v 1.33 1997/11/07 08:52:27 phk Exp $ */ #include "opt_cpu.h" @@ -107,6 +107,10 @@ do_cpuid(u_long ax, u_long *p) ); } +#ifndef NO_F00F_HACK +int has_f00f_bug = 0; +#endif + void printcpuinfo(void) { @@ -136,6 +140,14 @@ printcpuinfo(void) break; case 0x500: strcat(cpu_model, "Pentium"); /* nb no space */ +#ifndef NO_F00F_HACK + /* + * XXX - If/when Intel fixes the bug, this + * should also check the version of the + * CPU, not just that it's a Pentium. + */ + has_f00f_bug = 1; +#endif break; case 0x600: strcat(cpu_model, "Pentium Pro"); diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index db3d2f2..82ad9e5 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.273 1997/11/21 18:27:10 bde Exp $ + * $Id: machdep.c,v 1.274 1997/11/24 18:35:11 bde Exp $ */ #include "apm.h" @@ -866,6 +866,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]; @@ -1534,6 +1539,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/i386/i386/trap.c b/sys/i386/i386/trap.c index e53b015..9bebd7e 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.114 1997/11/06 19:28:09 phk Exp $ + * $Id: trap.c,v 1.115 1997/11/24 13:25:37 bde Exp $ */ /* @@ -142,6 +142,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; @@ -211,6 +216,9 @@ trap(frame) u_long eva; #endif +#ifndef NO_F00F_HACK +restart: +#endif type = frame.tf_trapno; code = frame.tf_err; @@ -276,6 +284,10 @@ trap(frame) i = trap_pfault(&frame, TRUE); if (i == -1) return; +#ifndef NO_F00F_HACK + if (i == -2) + goto restart; +#endif if (i == 0) goto out; @@ -642,7 +654,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/kern/subr_trap.c b/sys/kern/subr_trap.c index e53b015..9bebd7e 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.114 1997/11/06 19:28:09 phk Exp $ + * $Id: trap.c,v 1.115 1997/11/24 13:25:37 bde Exp $ */ /* @@ -142,6 +142,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; @@ -211,6 +216,9 @@ trap(frame) u_long eva; #endif +#ifndef NO_F00F_HACK +restart: +#endif type = frame.tf_trapno; code = frame.tf_err; @@ -276,6 +284,10 @@ trap(frame) i = trap_pfault(&frame, TRUE); if (i == -1) return; +#ifndef NO_F00F_HACK + if (i == -2) + goto restart; +#endif if (i == 0) goto out; @@ -642,7 +654,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; |