X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=arch%2Fi386%2Fkernel%2Ftraps.c;h=d4fd1c57b09e99536aa5d9fd2d808be76cd52896;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=f7e15360bea6b1197dd1803d508a2b4293aabacf;hpb=e3f6fb6212a7102bdb56ba38fa1e98fe72950475;p=linux-2.6.git diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f7e15360b..d4fd1c57b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -348,8 +348,7 @@ void die(const char * str, struct pt_regs * regs, long err) if (panic_on_oops) { printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(5 * HZ); + ssleep(5); panic("Fatal exception"); } do_exit(SIGSEGV); @@ -455,6 +454,7 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) +DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) fastcall void do_general_protection(struct pt_regs * regs, long error_code) { @@ -646,16 +646,15 @@ void unset_nmi_callback(void) } #ifdef CONFIG_KPROBES -fastcall int do_int3(struct pt_regs *regs, long error_code) +fastcall void do_int3(struct pt_regs *regs, long error_code) { if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) - return 1; + return; /* This is an interrupt gate, because kprobes wants interrupts disabled. Normal trap handlers don't. */ restore_interrupts(regs); do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL); - return 0; } #endif @@ -710,8 +709,6 @@ fastcall void do_debug(struct pt_regs * regs, long error_code) /* * Single-stepping through TF: make sure we ignore any events in * kernel space (but re-enable TF when returning to user mode). - * And if the event was due to a debugger (PT_DTRACE), clear the - * TF flag so that register information is correct. */ if (condition & DR_STEP) { /* @@ -721,11 +718,6 @@ fastcall void do_debug(struct pt_regs * regs, long error_code) */ if ((regs->xcs & 3) == 0) goto clear_TF_reenable; - - if (likely(tsk->ptrace & PT_DTRACE)) { - tsk->ptrace &= ~PT_DTRACE; - regs->eflags &= ~TF_MASK; - } } /* Ok, finally something we can handle */ @@ -817,7 +809,7 @@ fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code) math_error((void __user *)regs->eip); } -void simd_math_error(void __user *eip) +static void simd_math_error(void __user *eip) { struct task_struct * task; siginfo_t info; @@ -898,6 +890,51 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs, #endif } +fastcall void setup_x86_bogus_stack(unsigned char * stk) +{ + unsigned long *switch16_ptr, *switch32_ptr; + struct pt_regs *regs; + unsigned long stack_top, stack_bot; + unsigned short iret_frame16_off; + int cpu = smp_processor_id(); + /* reserve the space on 32bit stack for the magic switch16 pointer */ + memmove(stk, stk + 8, sizeof(struct pt_regs)); + switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs)); + regs = (struct pt_regs *)stk; + /* now the switch32 on 16bit stack */ + stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu); + stack_top = stack_bot + CPU_16BIT_STACK_SIZE; + switch32_ptr = (unsigned long *)(stack_top - 8); + iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20; + /* copy iret frame on 16bit stack */ + memcpy((void *)(stack_bot + iret_frame16_off), ®s->eip, 20); + /* fill in the switch pointers */ + switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off; + switch16_ptr[1] = __ESPFIX_SS; + switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) + + 8 - CPU_16BIT_STACK_SIZE; + switch32_ptr[1] = __KERNEL_DS; +} + +fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp) +{ + unsigned long *switch32_ptr; + unsigned char *stack16, *stack32; + unsigned long stack_top, stack_bot; + int len; + int cpu = smp_processor_id(); + stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu); + stack_top = stack_bot + CPU_16BIT_STACK_SIZE; + switch32_ptr = (unsigned long *)(stack_top - 8); + /* copy the data from 16bit stack to 32bit stack */ + len = CPU_16BIT_STACK_SIZE - 8 - sp; + stack16 = (unsigned char *)(stack_bot + sp); + stack32 = (unsigned char *) + (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len); + memcpy(stack32, stack16, len); + return stack32; +} + /* * 'math_state_restore()' saves the current math information in the * old math state array, and gets the new ones from the current task @@ -1041,3 +1078,10 @@ void __init trap_init(void) trap_init_hook(); } + +static int __init kstack_setup(char *s) +{ + kstack_depth_to_print = simple_strtoul(s, NULL, 0); + return 0; +} +__setup("kstack=", kstack_setup);