summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1997-12-09 03:36:43 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1997-12-09 03:36:43 +0000
commit900f574e1f49c18be8e2cc07f21abcb10fdc8ec5 (patch)
tree10179962bf0dbea0df454f816cb3fd7d1c571706 /sys
parenteb5c0c47d0704e39ca34dc1845cb685a142a897d (diff)
Intel P5 f00f workaround; weingart & who knows who else
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/i386/genassym.cf4
-rw-r--r--sys/arch/i386/i386/locore.s15
-rw-r--r--sys/arch/i386/i386/machdep.c54
-rw-r--r--sys/arch/i386/include/cpu.h6
-rw-r--r--sys/arch/i386/include/segments.h3
-rw-r--r--sys/arch/i386/isa/isa_machdep.c3
6 files changed, 74 insertions, 11 deletions
diff --git a/sys/arch/i386/i386/genassym.cf b/sys/arch/i386/i386/genassym.cf
index c7d96c90eff..c811a9dbf20 100644
--- a/sys/arch/i386/i386/genassym.cf
+++ b/sys/arch/i386/i386/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.5 1997/10/19 06:34:23 mickey Exp $
+# $OpenBSD: genassym.cf,v 1.6 1997/12/09 03:36:39 deraadt Exp $
#
# Copyright (c) 1982, 1990 The Regents of the University of California.
# All rights reserved.
@@ -108,6 +108,8 @@ define PCB_ONFAULT offsetof(struct pcb, pcb_onfault)
define TF_CS offsetof(struct trapframe, tf_cs)
define TF_TRAPNO offsetof(struct trapframe, tf_trapno)
define TF_EFLAGS offsetof(struct trapframe, tf_eflags)
+define TF_EIP offsetof(struct trapframe, tf_eip)
+define TF_ERR offsetof(struct trapframe, tf_err)
define FRAMESIZE sizeof(struct trapframe)
diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s
index fda7798ef74..192fffb44f6 100644
--- a/sys/arch/i386/i386/locore.s
+++ b/sys/arch/i386/i386/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.36 1997/10/22 23:37:12 mickey Exp $ */
+/* $OpenBSD: locore.s,v 1.37 1997/12/09 03:36:39 deraadt Exp $ */
/* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */
/*-
@@ -1931,6 +1931,19 @@ IDTVEC(stk)
TRAP(T_STKFLT)
IDTVEC(prot)
TRAP(T_PROTFLT)
+#ifdef I586_CPU
+IDTVEC(f00f_redirect)
+ pushl $T_PAGEFLT
+ INTRENTRY
+ testb $PGEX_U,TF_ERR(%esp)
+ jnz calltrap
+ movl %cr2,%eax
+ subl _idt,%eax
+ cmpl $(6*8),%eax
+ jne calltrap
+ movb $T_PRIVINFLT,TF_TRAPNO(%esp)
+ jmp calltrap
+#endif
IDTVEC(page)
TRAP(T_PAGEFLT)
IDTVEC(rsvd)
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 61b5522816f..5494dc3d24c 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.66 1997/12/02 05:06:41 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.67 1997/12/09 03:36:40 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.202 1996/05/18 15:54:59 christos Exp $ */
/*-
@@ -489,6 +489,10 @@ identifycpu()
calibrate_cyclecounter();
printf(" %d MHz", pentium_mhz);
}
+ if (!strcmp(cpu_model, "Pentium (GenuineIntel 586-class CPU)")) {
+ fix_f00f();
+ printf("\nCPU: F00F bug workaround installed");
+ }
#endif
printf("\n");
@@ -1079,7 +1083,8 @@ setregs(p, pack, stack, retval)
union descriptor gdt[NGDT];
union descriptor ldt[NLDT];
-struct gate_descriptor idt[NIDT];
+struct gate_descriptor idt_region[NIDT];
+struct gate_descriptor *idt = idt_region;
extern struct user *proc0paddr;
@@ -1139,6 +1144,45 @@ extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt),
IDTVEC(fpu), IDTVEC(align),
IDTVEC(syscall), IDTVEC(osyscall);
+#if defined(I586_CPU)
+extern IDTVEC(f00f_redirect);
+pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
+
+int cpu_f00f_bug = 0;
+
+void
+fix_f00f()
+{
+ struct region_descriptor region;
+ vm_offset_t va;
+ pt_entry_t *pte;
+ void *p;
+
+ /* Allocate two new pages */
+ va = kmem_alloc(kernel_map, NBPG*2);
+ p = (void *)(va + NBPG - 7*sizeof(*idt));
+
+ /* Copy over old IDT */
+ bcopy(idt, p, sizeof(idt_region));
+ idt = p;
+
+ /* Fix up paging redirect */
+ setgate(&idt[ 14], &IDTVEC(f00f_redirect), 0, SDT_SYS386TGT,
+ SEL_KPL, GCODE_SEL);
+
+ /* Map first page RO */
+ pte = pmap_pte(pmap_kernel(), va);
+ *pte &= ~PG_RW;
+
+ /* Reload idtr */
+ setregion(&region, idt, sizeof(idt_region) - 1);
+ lidt(&region);
+
+ /* Tell the rest of the world */
+ cpu_f00f_bug = 1;
+}
+#endif
+
void
init386(first_avail)
vm_offset_t first_avail;
@@ -1214,7 +1258,7 @@ init386(first_avail)
setregion(&region, gdt, sizeof(gdt) - 1);
lgdt(&region);
- setregion(&region, idt, sizeof(idt) - 1);
+ setregion(&region, idt, sizeof(idt_region) - 1);
lidt(&region);
#if NISA > 0
@@ -1414,8 +1458,8 @@ cpu_reset()
* Try to cause a triple fault and watchdog reset by setting the
* IDT to point to nothing.
*/
- bzero((caddr_t)idt, sizeof(idt));
- setregion(&region, idt, sizeof(idt) - 1);
+ bzero((caddr_t)idt, sizeof(idt_region));
+ setregion(&region, idt, sizeof(idt_region) - 1);
lidt(&region);
__asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h
index ed1b2880f76..15506252a04 100644
--- a/sys/arch/i386/include/cpu.h
+++ b/sys/arch/i386/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.17 1997/10/25 21:47:27 mickey Exp $ */
+/* $OpenBSD: cpu.h,v 1.18 1997/12/09 03:36:41 deraadt Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
@@ -140,6 +140,10 @@ extern int cpu_class;
extern struct cpu_nameclass i386_cpus[];
#ifdef I586_CPU
extern int pentium_mhz;
+
+/* F00F bug fix stuff for pentium cpu */
+extern int cpu_f00f_bug;
+void fix_f00f __P((void));
#endif
/* autoconf.c */
diff --git a/sys/arch/i386/include/segments.h b/sys/arch/i386/include/segments.h
index 4aa542dc009..f99604bb380 100644
--- a/sys/arch/i386/include/segments.h
+++ b/sys/arch/i386/include/segments.h
@@ -128,7 +128,8 @@ struct region_descriptor {
#ifdef _KERNEL
extern union descriptor gdt[], ldt[];
-extern struct gate_descriptor idt[];
+extern struct gate_descriptor idt_region[];
+extern struct gate_descriptor *idt;
void setgate __P((struct gate_descriptor *, void *, int, int, int, int));
void setregion __P((struct region_descriptor *, void *, size_t));
diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c
index 73cb52256b7..362f0262f71 100644
--- a/sys/arch/i386/isa/isa_machdep.c
+++ b/sys/arch/i386/isa/isa_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa_machdep.c,v 1.22 1997/09/24 22:28:16 niklas Exp $ */
+/* $OpenBSD: isa_machdep.c,v 1.23 1997/12/09 03:36:42 deraadt Exp $ */
/* $NetBSD: isa_machdep.c,v 1.14 1996/05/12 23:06:18 mycroft Exp $ */
/*-
@@ -62,7 +62,6 @@
/* default interrupt vector table entries */
typedef (*vector) __P((void));
extern vector IDTVEC(intr)[], IDTVEC(fast)[];
-extern struct gate_descriptor idt[];
void isa_strayintr __P((int));
void intr_calculatemasks __P((void));
int fakeintr __P((void *));