Index: machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v retrieving revision 1.209.2.13 retrieving revision 1.209.2.17 diff -c -r1.209.2.13 -r1.209.2.17 *** machdep.c 1997/09/25 15:50:53 1.209.2.13 --- machdep.c 1997/12/05 07:26:37 1.209.2.17 *************** *** 35,49 **** * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 ! * $Id: machdep.c,v 1.209.2.13 1997/09/25 15:50:53 davidg Exp $ */ #include "npx.h" - #include "opt_sysvipc.h" - #include "opt_ddb.h" #include "opt_bounce.h" #include "opt_machdep.h" #include "opt_perfmon.h" #include "opt_userconfig.h" #include --- 35,50 ---- * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 ! * $Id: machdep.c,v 1.209.2.17 1997/12/05 07:26:37 jmg Exp $ */ #include "npx.h" #include "opt_bounce.h" + #include "opt_cpu.h" + #include "opt_ddb.h" #include "opt_machdep.h" #include "opt_perfmon.h" + #include "opt_sysvipc.h" #include "opt_userconfig.h" #include *************** *** 743,748 **** --- 744,754 ---- struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */ union descriptor ldt[NLDT]; /* local descriptor table */ + #if defined(I586_CPU) && !defined(NO_F00F_HACK) + struct gate_descriptor *t_idt; + extern int has_f00f_bug; + #endif + static struct i386tss dblfault_tss; static char dblfault_stack[PAGE_SIZE]; *************** *** 1360,1365 **** --- 1366,1404 ---- proc0.p_addr->u_pcb.pcb_flags = 0; proc0.p_addr->u_pcb.pcb_cr3 = IdlePTD; } + + #if defined(I586_CPU) && !defined(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; + + 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); + if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE, + VM_PROT_READ, FALSE) != KERN_SUCCESS) + panic("vm_map_protect failed"); + return; + } + #endif /* defined(I586_CPU) && !NO_F00F_HACK */ /* * The registers are in the frame; the frame is in the user area of Index: trap.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/trap.c,v retrieving revision 1.83.2.2 retrieving revision 1.83.2.5 diff -c -r1.83.2.2 -r1.83.2.5 *** trap.c 1997/02/13 07:51:53 1.83.2.2 --- trap.c 1997/12/05 07:26:39 1.83.2.5 *************** *** 35,49 **** * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 ! * $Id: trap.c,v 1.83.2.2 1997/02/13 07:51:53 bde Exp $ */ /* * 386 Trap and System call handling */ ! #include "opt_ktrace.h" #include "opt_ddb.h" #include #include --- 35,50 ---- * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 ! * $Id: trap.c,v 1.83.2.5 1997/12/05 07:26:39 jmg Exp $ */ /* * 386 Trap and System call handling */ ! #include "opt_cpu.h" #include "opt_ddb.h" + #include "opt_ktrace.h" #include #include *************** *** 133,138 **** --- 134,144 ---- static void userret __P((struct proc *p, struct trapframe *frame, u_quad_t oticks)); + #if defined(I586_CPU) && !defined(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; *************** *** 189,194 **** --- 195,203 ---- u_long eva; #endif + #if defined(I586_CPU) && !defined(NO_F00F_HACK) + restart: + #endif type = frame.tf_trapno; code = frame.tf_err; *************** *** 239,244 **** --- 248,257 ---- i = trap_pfault(&frame, TRUE); if (i == -1) return; + #if defined(I586_CPU) && !defined(NO_F00F_HACK) + if (i == -2) + goto restart; + #endif if (i == 0) goto out; *************** *** 585,591 **** --- 598,615 ---- 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. */ + #if defined(I586_CPU) && !defined(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; Index: identcpu.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/identcpu.c,v retrieving revision 1.7.2.8 retrieving revision 1.7.2.12 diff -c -r1.7.2.8 -r1.7.2.12 *** identcpu.c 1997/10/03 14:29:48 1.7.2.8 --- identcpu.c 1997/12/04 14:36:55 1.7.2.12 *************** *** 36,42 **** * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp ! * $Id: identcpu.c,v 1.7.2.8 1997/10/03 14:29:48 kato Exp $ */ #include "opt_cpu.h" --- 36,42 ---- * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp ! * $Id: identcpu.c,v 1.7.2.12 1997/12/04 14:36:55 jkh Exp $ */ #include "opt_cpu.h" *************** *** 91,96 **** --- 91,100 ---- { "Cyrix 486S/DX", CPUCLASS_486 }, /* CPU_CY486DX */ }; + #if defined(I586_CPU) && !defined(NO_F00F_HACK) + int has_f00f_bug = 0; + #endif + void printcpuinfo(void) { *************** *** 119,124 **** --- 123,136 ---- break; case 0x500: strcat(cpu_model, "Pentium"); /* nb no space */ + #if defined(I586_CPU) && !defined(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"); *************** *** 198,212 **** } } else if (strcmp(cpu_vendor,"CyrixInstead") == 0) { strcpy(cpu_model, "Cyrix "); ! switch (cpu_id & 0xf00) { ! case 0x500: strcat(cpu_model, "6x86"); break; case 0x600: strcat(cpu_model, "6x86MX"); break; default: ! /* cpuid instruction is not supported */ switch (cyrix_did & 0xf0) { case 0x00: switch (cyrix_did & 0x0f) { --- 210,236 ---- } } else if (strcmp(cpu_vendor,"CyrixInstead") == 0) { strcpy(cpu_model, "Cyrix "); ! switch (cpu_id & 0xff0) { ! case 0x440: ! strcat(cpu_model, "MediaGX"); ! break; ! case 0x520: strcat(cpu_model, "6x86"); break; + case 0x540: + cpu_class = CPUCLASS_586; + strcat(cpu_model, "GXm"); + break; case 0x600: strcat(cpu_model, "6x86MX"); break; default: ! /* ! * Even though CPU supports the cpuid ! * instruction, it can be disabled. ! * Therefore, this routine supports all Cyrix ! * CPUs. ! */ switch (cyrix_did & 0xf0) { case 0x00: switch (cyrix_did & 0x0f) { *************** *** 289,296 **** strcat(cpu_model, "6x86"); break; case 0x40: ! /* XXX */ ! strcat(cpu_model, "MediaGX"); break; case 0x50: strcat(cpu_model, "6x86MX"); --- 313,323 ---- strcat(cpu_model, "6x86"); break; case 0x40: ! if ((cyrix_did & 0xf000) == 0x3000) { ! cpu_class = CPUCLASS_586; ! strcat(cpu_model, "GXm"); ! } else ! strcat(cpu_model, "MediaGX"); break; case 0x50: strcat(cpu_model, "6x86MX"); *************** *** 564,569 **** --- 591,601 ---- } switch (cpu_id & 0xf00) { case 0x600: + /* + * Cyrix's datasheet does not describe DIRs. + * Therefor, I assume it does not have them + * and use the result of the cpuid instruction. + */ identifycyrix(); cpu = CPU_M2; break; *************** *** 582,588 **** cpu = CPU_CY486DX; break; case 0x20: ! if ((cyrix_did & 0x00f0) < 8) cpu = CPU_M1; else cpu = CPU_M1SC; --- 614,620 ---- cpu = CPU_CY486DX; break; case 0x20: ! if ((cyrix_did & 0x000f) < 8) cpu = CPU_M1; else cpu = CPU_M1SC; *************** *** 591,596 **** --- 623,629 ---- cpu = CPU_M1; break; case 0x40: + /* MediaGX CPU */ cpu = CPU_M1SC; break; default: