Work around for the Intel Pentium F00F bug; this is Intel's recommended
workaround. Note that this currently eats up two pages extra in the system; this could be alleviated by aligning idt correctly, and then only dealing with that (as opposed to the current method of allocated two pages and copying the IDT table to that, and then setting that to be the IDT table).
This commit is contained in:
parent
a587a35bbd
commit
c4fbf2774d
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user