From owner-freebsd-hackers Thu Nov 13 12:11:54 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id MAA15421 for hackers-outgoing; Thu, 13 Nov 1997 12:11:54 -0800 (PST) (envelope-from owner-freebsd-hackers) Received: from super-g.inch.com (super-g.com [207.240.140.161]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id MAA15401 for ; Thu, 13 Nov 1997 12:11:47 -0800 (PST) (envelope-from spork@super-g.com) Received: from localhost (localhost [127.0.0.1]) by super-g.inch.com (8.8.7/8.8.5) with SMTP id PAA19010; Thu, 13 Nov 1997 15:06:53 -0500 (EST) Date: Thu, 13 Nov 1997 15:06:53 -0500 (EST) From: spork X-Sender: spork@super-g.inch.com To: "David E. Cross" cc: freebsd-hackers@FreeBSD.ORG Subject: Re: Pentium Bug Fix... In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-hackers@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk > I would be interested in seeing the alledged Linux 'fix'. Here ya go: Date: Wed, 12 Nov 1997 18:45:15 -0600 From: Aleph One To: BUGTRAQ@NETSPACE.ORG Subject: Linux F00F Patch This are the relevant parts of the linux kernel 2.1.63 patch that fix the Pentium bug that Alan mentioned. Aleph One / aleph1@dfw.net http://underground.org/ KeyID 1024/948FD6B5 Fingerprint EE C9 E8 AA CB AF 09 61 8C 39 EA 47 A8 6A B8 01 diff -u --recursive --new-file v2.1.62/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.1.62/linux/arch/i386/kernel/setup.c Tue Sep 23 16:48:46 1997 +++ linux/arch/i386/kernel/setup.c Wed Nov 12 11:09:56 1997 @@ -42,6 +42,7 @@ char x86_mask = 0; /* set by kernel/head.S */ int x86_capability = 0; /* set by kernel/head.S */ int fdiv_bug = 0; /* set if Pentium(TM) with FP bug */ +int pentium_f00f_bug = 0; /* set if Pentium(TM) with F00F bug */ int have_cpuid = 0; /* set if CPUID instruction works */ char x86_vendor_id[13] = "unknown"; @@ -359,6 +360,7 @@ "fdiv_bug\t: %s\n" "hlt_bug\t\t: %s\n" "sep_bug\t\t: %s\n" + "pentium_f00f_bug\t\t: %s\n" "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid\t\t: %s\n" @@ -367,6 +369,7 @@ CD(fdiv_bug) ? "yes" : "no", CD(hlt_works_ok) ? "no" : "yes", sep_bug ? "yes" : "no", + pentium_f00f_bug ? "yes" : "no", CD(hard_math) ? "yes" : "no", (CD(hard_math) && ignore_irq13) ? "yes" : "no", diff -u --recursive --new-file v2.1.62/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.1.62/linux/arch/i386/kernel/traps.c Sun Sep 7 13:10:42 1997 +++ linux/arch/i386/kernel/traps.c Wed Nov 12 11:09:56 1997 @@ -413,6 +413,51 @@ #endif /* CONFIG_MATH_EMULATION */ +static struct +{ + short limit __attribute__((packed)); + void * addr __attribute__((packed)); + short __pad __attribute__((packed)); +} idt_d; + +void * idt2; + +__initfunc(void trap_init_f00f_bug(void)) +{ + pgd_t * pgd; + pmd_t * pmd; + pte_t * pte; + unsigned long twopage; + + printk("moving IDT ... "); + + twopage = (unsigned long) vmalloc (2*PAGE_SIZE); + + idt2 = (void *)(twopage + 4096-7*8); + + memcpy(idt2,&idt,sizeof(idt)); + + idt_d.limit = 256*8-1; + idt_d.addr = idt2; + idt_d.__pad = 0; + + __asm__ __volatile__("\tlidt %0": "=m" (idt_d)); + + /* + * Unmap lower page: + */ + pgd = pgd_offset(current->mm, twopage); + pmd = pmd_offset(pgd, twopage); + pte = pte_offset(pmd, twopage); + + pte_clear(pte); + flush_tlb_all(); + + printk(" ... done\n"); +} + + + __initfunc(void trap_init(void)) { int i; diff -u --recursive --new-file v2.1.62/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.1.62/linux/arch/i386/mm/fault.c Wed Oct 15 16:04:23 1997 +++ linux/arch/i386/mm/fault.c Wed Nov 12 11:09:55 1997 @@ -74,6 +74,25 @@ return 0; } +asmlinkage void divide_error(void); +asmlinkage void debug(void); +asmlinkage void nmi(void); +asmlinkage void int3(void); +asmlinkage void overflow(void); +asmlinkage void bounds(void); +asmlinkage void invalid_op(void); + +asmlinkage void do_divide_error (struct pt_regs *, unsigned long); +asmlinkage void do_debug (struct pt_regs *, unsigned long); +asmlinkage void do_nmi (struct pt_regs *, unsigned long); +asmlinkage void do_int3 (struct pt_regs *, unsigned long); +asmlinkage void do_overflow (struct pt_regs *, unsigned long); +asmlinkage void do_bounds (struct pt_regs *, unsigned long); +asmlinkage void do_invalid_op (struct pt_regs *, unsigned long); + +extern int * idt2; +extern int pentium_f00f_bug; + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -170,6 +189,46 @@ goto out; } + printk("<%p/%p>\n", idt2, (void *)address); + /* + * Pentium F0 0F C7 C8 bug workaround: + */ + if ( pentium_f00f_bug && (address >= (unsigned long)idt2) && + (address < (unsigned long)idt2+256*8) ) { + + void (*handler) (void); + int nr = (address-(unsigned long)idt2)/8; + unsigned long low, high; + + low = idt[nr].a; + high = idt[nr].b; + + handler = (void (*) (void)) ((low&0x0000ffff) | (high&0xffff0000)); + printk("\n"); + goto out; + } + /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->eip)) != 0) { printk(KERN_DEBUG "%s: Exception at [<%lx>] cr2=%lx (fixup: %lx)\n", @@ -193,6 +252,7 @@ flush_tlb(); goto out; } + if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); else diff -u --recursive --new-file v2.1.62/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h --- v2.1.62/linux/include/asm-i386/bugs.h Thu Sep 11 09:02:24 1997 +++ linux/include/asm-i386/bugs.h Wed Nov 12 11:09:55 1997 @@ -166,6 +166,32 @@ } } +/* + * All current models of Pentium and Pentium with MMX technology CPUs + * have the F0 0F bug, which lets nonpriviledged users lock up the system: + */ + +extern int pentium_f00f_bug; + +__initfunc(static void check_pentium_f00f(void)) +{ + /* + * Pentium and Pentium MMX + */ + printk("checking for F00F bug ..."); + if(x86==5 && !memcmp(x86_vendor_id, "GenuineIntel", 12)) + { + extern void trap_init_f00f_bug(void); + + printk(KERN_INFO "\nIntel Pentium/[MMX] F0 0F bug detected - turning on workaround.\n"); + pentium_f00f_bug = 1; + trap_init_f00f_bug(); + } else { + printk(KERN_INFO " no F0 0F bug in this CPU, great!\n"); + pentium_f00f_bug = 0; + } +} + __initfunc(static void check_bugs(void)) { check_tlb(); @@ -173,5 +199,6 @@ check_hlt(); check_popad(); check_amd_k6(); + check_pentium_f00f(); system_utsname.machine[1] = '0' + x86; }