F00F-Patch for 2.0.29

Wolfram Liebchen (liebchen@ffo.fgan.de)
Wed, 19 Nov 1997 10:30:52 +0100


This is a multi-part message in MIME format.

--------------67E360F04C7D
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

Hi,

I extracted the parts necessary for fixing the f00f bug
to patch my 2.0.29 system.
It works on two different systems now (I don't have more
computers :-( ), so perhaps you can check it and may use it.
The patch (6 kByte) is attached to this mail.
Please excuse, if this offends your rules, but I have no
ftp-server to offer the file.

Regards,

-- Wolfram

-- ---------------------------------------------
Forschungsinstitut f=FCr Optik
(Research Institute for Optics)
Wolfram Liebchen
Schlo=DF Kre=DFbach Tel: +49 7071 709-158
D-72072 T=FCbingen Fax: +49 7071 709-270
Germany liebchen@ffo.fgan.de

--------------67E360F04C7D
Content-Type: text/plain; charset=us-ascii; name="pat-f00f-bug-2.0.29"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="pat-f00f-bug-2.0.29"

diff -u -r --exclude=.* kernel-source-2.0.29/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- kernel-source-2.0.29/arch/i386/kernel/head.S Sun May 25 13:50:44 1997
+++ linux/arch/i386/kernel/head.S Sun Nov 16 13:24:20 1997
@@ -260,7 +260,7 @@
movw %dx,%ax /* selector = 0x0010 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */

- lea SYMBOL_NAME(idt),%edi
+ lea SYMBOL_NAME(__idt),%edi
mov $256,%ecx
rp_sidt:
movl %eax,(%edi)
@@ -376,9 +376,9 @@
.word 0
idt_descr:
.word 256*8-1 # idt contains 256 entries
- .long 0xc0000000+SYMBOL_NAME(idt)
+ .long 0xc0000000+SYMBOL_NAME(__idt)

-ENTRY(idt)
+ENTRY(__idt)
.fill 256,8,0 # idt is uninitialized

ALIGN
diff -u -r --exclude=.* kernel-source-2.0.29/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- kernel-source-2.0.29/arch/i386/kernel/setup.c Sun May 25 14:16:20 1997
+++ linux/arch/i386/kernel/setup.c Sun Nov 16 13:24:21 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 */
int has_mca_pentium = 0; /* MCA with bad pentium processor */

@@ -324,6 +325,7 @@
len += sprintf(buffer+len,
"fdiv_bug\t: %s\n"
"hlt_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"
@@ -331,6 +333,7 @@
"flags\t\t:",
CD(fdiv_bug) ? "yes" : "no",
CD(hlt_works_ok) ? "no" : "yes",
+ pentium_f00f_bug ? "yes" : "no",
CD(hard_math) ? "yes" : "no",
(CD(hard_math) && ignore_irq13)
? "yes" : "no",
diff -u -r --exclude=.* kernel-source-2.0.29/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- kernel-source-2.0.29/arch/i386/kernel/traps.c Sun May 25 14:16:21 1997
+++ linux/arch/i386/kernel/traps.c Sun Nov 16 13:24:20 1997
@@ -27,6 +27,7 @@
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/io.h>
+#include <asm/pgtable.h>

asmlinkage int system_call(void);
asmlinkage void lcall7(void);
@@ -340,6 +341,49 @@
}

#endif /* CONFIG_MATH_EMULATION */
+
+struct desc_struct *idt = __idt+0;
+
+void trap_init_f00f_bug(void)
+{
+ pgd_t * pgd;
+ pmd_t * pmd;
+ pte_t * pte;
+ unsigned long twopage;
+ struct desc_struct *new_idt;
+ struct {
+ unsigned short limit;
+ unsigned long addr __attribute__((packed));
+ } idt_descriptor;
+
+ printk("moving IDT ... ");
+
+ twopage = (unsigned long) vmalloc (2*PAGE_SIZE);
+
+ new_idt = (void *)(twopage + 4096-7*8);
+
+ memcpy(new_idt,idt,256*8);
+
+ idt_descriptor.limit = 256*8-1;
+ idt_descriptor.addr = VMALLOC_VMADDR(new_idt);
+
+ __asm__ __volatile__("\tlidt %0": "=m" (idt_descriptor));
+ idt = new_idt;
+
+ /*
+ * Unmap lower page:
+ */
+ twopage = VMALLOC_VMADDR(twopage);
+ 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");
+}
+

void trap_init(void)
{
diff -u -r --exclude=.* kernel-source-2.0.29/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- kernel-source-2.0.29/arch/i386/mm/fault.c Sun May 25 13:50:42 1997
+++ linux/arch/i386/mm/fault.c Sun Nov 16 13:24:21 1997
@@ -21,6 +21,16 @@

extern void die_if_kernel(const char *,struct pt_regs *,long);

+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 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
@@ -117,6 +127,30 @@
force_sig(SIGSEGV, tsk);
return;
}
+
+ /*
+ * Pentium F0 0F C7 C8 bug workaround:
+ */
+ if ( pentium_f00f_bug ) {
+ unsigned long nr;
+
+ nr = (address - TASK_SIZE - (unsigned long) idt) >> 3;
+
+ if (nr < 7) {
+ static void (*handler[])(struct pt_regs *, unsigned long) = {
+ do_divide_error, /* 0 - divide overflow */
+ do_debug, /* 1 - debug trap */
+ do_nmi, /* 2 - NMI */
+ do_int3, /* 3 - int 3 */
+ do_overflow, /* 4 - overflow */
+ do_bounds, /* 5 - bound range */
+ do_invalid_op }; /* 6 - invalid opcode */
+ handler[nr](regs, error_code);
+ return;
+ }
+ }
+
+
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
diff -u -r --exclude=.* kernel-source-2.0.29/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- kernel-source-2.0.29/include/asm-i386/bugs.h Sat Nov 8 21:03:48 1997
+++ linux/include/asm-i386/bugs.h Sun Nov 16 13:24:21 1997
@@ -135,6 +135,27 @@
#endif
}

+/*
+ * 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;
+extern void trap_init_f00f_bug(void);
+
+static void check_pentium_f00f(void)
+{
+ /*
+ * Pentium and Pentium MMX
+ */
+ pentium_f00f_bug = 0;
+ if (x86==5 && !memcmp(x86_vendor_id, "GenuineIntel", 12)) {
+ printk(KERN_INFO "Intel Pentium with F0 0F bug - workaround enabled.\n");
+ pentium_f00f_bug = 1;
+ trap_init_f00f_bug();
+ }
+}
+
+
static void check_bugs(void)
{
check_tlb();
@@ -146,5 +167,6 @@
check_fpu();
#endif
check_hlt();
+ check_pentium_f00f();
system_utsname.machine[1] = '0' + x86;
}
diff -u -r --exclude=.* kernel-source-2.0.29/include/linux/head.h linux/include/linux/head.h
--- kernel-source-2.0.29/include/linux/head.h Sun May 25 13:49:35 1997
+++ linux/include/linux/head.h Sun Nov 16 13:24:20 1997
@@ -5,7 +5,8 @@
unsigned long a,b;
} desc_table[256];

-extern desc_table idt,gdt;
+extern desc_table __idt,gdt;
+extern struct desc_struct *idt;

#define GDT_NUL 0
#define GDT_CODE 1

--------------67E360F04C7D--