Stopgap patch for F00F bug

ganesh@cse.iitb.ernet.in
Wed, 12 Nov 1997 20:12:59 +0530 (IST)


Hi,
this Horrible Hack(TM) implements Jim Brook's idea to overcome
the Pentium F00F bug - do a dummy illegal instruction and then disable
the cache. Of course it causes a severe performance hit, but in some
cases a slow machine is better than no machine.
Patch against 2.0.30, might work for other versions too ...
After booting run a program like
char main[] = {0xf,0xb};
having an illegal instruction. Your machine is now slow, but protected
against f00f*
-- ganesh
--- linux/arch/i386/kernel/traps.c.ORG Wed Nov 12 17:54:44 1997
+++ linux/arch/i386/kernel/traps.c Wed Nov 12 19:41:13 1997
@@ -10,6 +10,9 @@
* to mainly kill the offending process (probably by giving it a signal,
* but possibly by killing it outright if necessary).
*/
+
+#define F00F_HACK 1
+
#include <linux/config.h>
#include <linux/head.h>
#include <linux/sched.h>
@@ -181,7 +184,9 @@
DO_VM86_ERROR( 3, SIGTRAP, "int3", int3, current)
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow, current)
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds, current)
+#ifndef F00F_HACK
DO_ERROR( 6, SIGILL, "invalid operand", invalid_op, current)
+#endif
DO_VM86_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
@@ -190,6 +195,26 @@
DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current)
DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
+
+#ifdef F00F_HACK
+static int f00f_hack = 0 ;
+asmlinkage void do_invalid_op(struct pt_regs * regs, long error_code)
+{
+#if CPU == 586
+ if (!f00f_hack) {
+ f00f_hack = 1 ;
+ __asm__ __volatile__ ("movl %%cr0, %%eax\n\t"
+ "orl $0xc0000000, %%eax\n\t"
+ "movl %%eax, %%cr0"
+ :::"eax") ;
+ }
+#endif
+ current->tss.error_code = error_code;
+ current->tss.trap_no = 6;
+ force_sig(SIGILL, current); \
+ die_if_kernel("invalid operand",regs,error_code); \
+}
+#endif

asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{