patch-1.3.31 linux/arch/i386/kernel/traps.c

Next file: linux/arch/i386/mm/init.c
Previous file: linux/arch/i386/kernel/trampoline32.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
@@ -10,6 +10,7 @@
  * to mainly kill the offending process (probably by giving it a signal,
  * but possibly by killing it outright if necessary).
  */
+#include <linux/config.h>
 #include <linux/head.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -111,6 +112,7 @@
 	}
 	console_verbose();
 	printk("%s: %04lx\n", str, err & 0xffff);
+	printk("CPU:    %d\n", smp_processor_id());
 	printk("EIP:    %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
 	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
@@ -190,11 +192,15 @@
 
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
+#ifdef CONFIG_SMP_NMI_INVAL
+	smp_invalidate_rcv();
+#else
 #ifndef CONFIG_IGNORE_NMI
 	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
 	printk("You probably have a hardware problem with your RAM chips or a\n");
 	printk("power saving mode enabled.\n");
 #endif	
+#endif
 }
 
 asmlinkage void do_debug(struct pt_regs * regs, long error_code)
@@ -236,7 +242,19 @@
 void math_error(void)
 {
 	struct i387_hard_struct * env;
-
+#ifdef CONFIG_SMP
+	env=&current->tss.i387.hard;
+	send_sig(SIGFPE, current, 1);
+	/*
+	 *	Save the info for the exception handler
+	 */
+	__asm__ __volatile__("fnsave %0":"=m" (*env));
+	current->flags&=~PF_USEDFPU;
+	/*
+	 *	Cause a trap if they use the FPU again.
+	 */
+	stts();
+#else
 	clts();
 	if (!last_task_used_math) {
 		__asm__("fnclex");
@@ -253,6 +271,7 @@
 	env->fos = env->twd;
 	env->swd &= 0xffff3800;
 	env->twd = 0xffffffff;
+#endif	
 }
 
 asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
@@ -270,6 +289,30 @@
  */
 asmlinkage void math_state_restore(void)
 {
+#ifdef CONFIG_SMP
+/*
+ *	SMP is actually simpler than uniprocessor for once. Because
+ *	we can't pull the delayed FPU switching trick Linus does
+ *	we simply have to do the restore each context switch and
+ *	set the flag. switch_to() will always save the state in
+ *	case we swap processors. We also don't use the coprocessor
+ *	timer - IRQ 13 mode isnt used with SMP machines (thank god).
+ *
+ *	If this actually works it will be a miracle however
+ */
+	__asm__ __volatile__("clts");		/* Allow maths ops (or we recurse) */
+	if(current->used_math)
+		__asm__("frstor %0": :"m" (current->tss.i387));
+	else
+	{
+		/*
+		 *	Our first FPU usage, clean the chip.
+		 */
+		__asm__("fninit");
+		current->used_math = 1;
+	}
+	current->flags|=PF_USEDFPU;		/* So we fnsave on switch_to() */
+#else
 	__asm__ __volatile__("clts");
 	if (last_task_used_math == current)
 		return;
@@ -287,6 +330,7 @@
 		current->used_math=1;
 	}
 	timer_active &= ~(1<<COPRO_TIMER);
+#endif	
 }
 
 #ifndef CONFIG_MATH_EMULATION
@@ -305,7 +349,15 @@
 {
 	int i;
 	struct desc_struct * p;
-
+	static int smptrap=0;
+	
+	if(smptrap)
+	{
+		__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
+		load_ldt(0);
+		return;
+	}
+	smptrap++;
 	if (strncmp((char*)0x0FFFD9, "EISA", 4) == 0)
 		EISA_bus = 1;
 	set_call_gate(&default_ldt,lcall7);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this