diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1997-12-09 03:36:43 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1997-12-09 03:36:43 +0000 |
commit | 900f574e1f49c18be8e2cc07f21abcb10fdc8ec5 (patch) | |
tree | 10179962bf0dbea0df454f816cb3fd7d1c571706 /sys | |
parent | eb5c0c47d0704e39ca34dc1845cb685a142a897d (diff) |
Intel P5 f00f workaround; weingart & who knows who else
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/i386/i386/genassym.cf | 4 | ||||
-rw-r--r-- | sys/arch/i386/i386/locore.s | 15 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 54 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 6 | ||||
-rw-r--r-- | sys/arch/i386/include/segments.h | 3 | ||||
-rw-r--r-- | sys/arch/i386/isa/isa_machdep.c | 3 |
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(®ion, idt, sizeof(idt_region) - 1); + lidt(®ion); + + /* 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(®ion, gdt, sizeof(gdt) - 1); lgdt(®ion); - setregion(®ion, idt, sizeof(idt) - 1); + setregion(®ion, idt, sizeof(idt_region) - 1); lidt(®ion); #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(®ion, idt, sizeof(idt) - 1); + bzero((caddr_t)idt, sizeof(idt_region)); + setregion(®ion, idt, sizeof(idt_region) - 1); lidt(®ion); __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 *)); |