aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index f0dffa03fbb..53ad954e3ba 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -306,14 +306,17 @@ void die(const char * str, struct pt_regs * regs, long err)
306 .lock_owner_depth = 0 306 .lock_owner_depth = 0
307 }; 307 };
308 static int die_counter; 308 static int die_counter;
309 unsigned long flags;
309 310
310 if (die.lock_owner != raw_smp_processor_id()) { 311 if (die.lock_owner != raw_smp_processor_id()) {
311 console_verbose(); 312 console_verbose();
312 spin_lock_irq(&die.lock); 313 spin_lock_irqsave(&die.lock, flags);
313 die.lock_owner = smp_processor_id(); 314 die.lock_owner = smp_processor_id();
314 die.lock_owner_depth = 0; 315 die.lock_owner_depth = 0;
315 bust_spinlocks(1); 316 bust_spinlocks(1);
316 } 317 }
318 else
319 local_save_flags(flags);
317 320
318 if (++die.lock_owner_depth < 3) { 321 if (++die.lock_owner_depth < 3) {
319 int nl = 0; 322 int nl = 0;
@@ -340,7 +343,7 @@ void die(const char * str, struct pt_regs * regs, long err)
340 343
341 bust_spinlocks(0); 344 bust_spinlocks(0);
342 die.lock_owner = -1; 345 die.lock_owner = -1;
343 spin_unlock_irq(&die.lock); 346 spin_unlock_irqrestore(&die.lock, flags);
344 347
345 if (kexec_should_crash(current)) 348 if (kexec_should_crash(current))
346 crash_kexec(regs); 349 crash_kexec(regs);
@@ -452,7 +455,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
452#endif 455#endif
453DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) 456DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
454DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) 457DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
455DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) 458DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
456DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) 459DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
457DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) 460DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
458DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) 461DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
@@ -1075,9 +1078,9 @@ void __init trap_init(void)
1075 set_trap_gate(0,&divide_error); 1078 set_trap_gate(0,&divide_error);
1076 set_intr_gate(1,&debug); 1079 set_intr_gate(1,&debug);
1077 set_intr_gate(2,&nmi); 1080 set_intr_gate(2,&nmi);
1078 set_system_intr_gate(3, &int3); /* int3-5 can be called from all */ 1081 set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
1079 set_system_gate(4,&overflow); 1082 set_system_gate(4,&overflow);
1080 set_system_gate(5,&bounds); 1083 set_trap_gate(5,&bounds);
1081 set_trap_gate(6,&invalid_op); 1084 set_trap_gate(6,&invalid_op);
1082 set_trap_gate(7,&device_not_available); 1085 set_trap_gate(7,&device_not_available);
1083 set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); 1086 set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
@@ -1095,6 +1098,28 @@ void __init trap_init(void)
1095#endif 1098#endif
1096 set_trap_gate(19,&simd_coprocessor_error); 1099 set_trap_gate(19,&simd_coprocessor_error);
1097 1100
1101 if (cpu_has_fxsr) {
1102 /*
1103 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
1104 * Generates a compile-time "error: zero width for bit-field" if
1105 * the alignment is wrong.
1106 */
1107 struct fxsrAlignAssert {
1108 int _:!(offsetof(struct task_struct,
1109 thread.i387.fxsave) & 15);
1110 };
1111
1112 printk(KERN_INFO "Enabling fast FPU save and restore... ");
1113 set_in_cr4(X86_CR4_OSFXSR);
1114 printk("done.\n");
1115 }
1116 if (cpu_has_xmm) {
1117 printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
1118 "support... ");
1119 set_in_cr4(X86_CR4_OSXMMEXCPT);
1120 printk("done.\n");
1121 }
1122
1098 set_system_gate(SYSCALL_VECTOR,&system_call); 1123 set_system_gate(SYSCALL_VECTOR,&system_call);
1099 1124
1100 /* 1125 /*