summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/identcpu.c14
-rw-r--r--sys/amd64/amd64/machdep.c44
-rw-r--r--sys/amd64/amd64/trap.c25
-rw-r--r--sys/i386/i386/identcpu.c14
-rw-r--r--sys/i386/i386/machdep.c44
-rw-r--r--sys/i386/i386/trap.c25
-rw-r--r--sys/kern/subr_trap.c25
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;
OpenPOWER on IntegriCloud