diff options
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index c34d1bfc5161..53ad954e3ba4 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 |
453 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) | 456 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) |
454 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) | 457 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) |
455 | DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) | 458 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) |
456 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | 459 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
457 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | 460 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) |
458 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 461 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
@@ -650,13 +653,6 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code) | |||
650 | 653 | ||
651 | cpu = smp_processor_id(); | 654 | cpu = smp_processor_id(); |
652 | 655 | ||
653 | #ifdef CONFIG_HOTPLUG_CPU | ||
654 | if (!cpu_online(cpu)) { | ||
655 | nmi_exit(); | ||
656 | return; | ||
657 | } | ||
658 | #endif | ||
659 | |||
660 | ++nmi_count(cpu); | 656 | ++nmi_count(cpu); |
661 | 657 | ||
662 | if (!rcu_dereference(nmi_callback)(regs, cpu)) | 658 | if (!rcu_dereference(nmi_callback)(regs, cpu)) |
@@ -1082,9 +1078,9 @@ void __init trap_init(void) | |||
1082 | set_trap_gate(0,÷_error); | 1078 | set_trap_gate(0,÷_error); |
1083 | set_intr_gate(1,&debug); | 1079 | set_intr_gate(1,&debug); |
1084 | set_intr_gate(2,&nmi); | 1080 | set_intr_gate(2,&nmi); |
1085 | 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 */ |
1086 | set_system_gate(4,&overflow); | 1082 | set_system_gate(4,&overflow); |
1087 | set_system_gate(5,&bounds); | 1083 | set_trap_gate(5,&bounds); |
1088 | set_trap_gate(6,&invalid_op); | 1084 | set_trap_gate(6,&invalid_op); |
1089 | set_trap_gate(7,&device_not_available); | 1085 | set_trap_gate(7,&device_not_available); |
1090 | set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); | 1086 | set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); |
@@ -1102,6 +1098,28 @@ void __init trap_init(void) | |||
1102 | #endif | 1098 | #endif |
1103 | set_trap_gate(19,&simd_coprocessor_error); | 1099 | set_trap_gate(19,&simd_coprocessor_error); |
1104 | 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 | |||
1105 | set_system_gate(SYSCALL_VECTOR,&system_call); | 1123 | set_system_gate(SYSCALL_VECTOR,&system_call); |
1106 | 1124 | ||
1107 | /* | 1125 | /* |