]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/i386/kernel/traps.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / arch / i386 / kernel / traps.c
index 0efad8aeb41af86849ac3b8e6b667d6603f4f594..90da0575fcff092a0a8cc9a1f561a3347c3c5bbf 100644 (file)
@@ -52,7 +52,7 @@
 #include <asm/unwind.h>
 #include <asm/smp.h>
 #include <asm/arch_hooks.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/stacktrace.h>
 
 #include <linux/module.h>
@@ -94,20 +94,7 @@ asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
 
 int kstack_depth_to_print = 24;
-ATOMIC_NOTIFIER_HEAD(i386die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       vmalloc_sync_all();
-       return atomic_notifier_chain_register(&i386die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&i386die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
+static unsigned int code_bytes = 64;
 
 static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
 {
@@ -291,10 +278,11 @@ void show_registers(struct pt_regs *regs)
        int i;
        int in_kernel = 1;
        unsigned long esp;
-       unsigned short ss;
+       unsigned short ss, gs;
 
        esp = (unsigned long) (&regs->esp);
        savesegment(ss, ss);
+       savesegment(gs, gs);
        if (user_mode_vm(regs)) {
                in_kernel = 0;
                esp = regs->esp;
@@ -313,18 +301,19 @@ void show_registers(struct pt_regs *regs)
                regs->eax, regs->ebx, regs->ecx, regs->edx);
        printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
                regs->esi, regs->edi, regs->ebp, esp);
-       printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
-               regs->xds & 0xffff, regs->xes & 0xffff, ss);
+       printk(KERN_EMERG "ds: %04x   es: %04x   fs: %04x  gs: %04x  ss: %04x\n",
+              regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
        printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
                TASK_COMM_LEN, current->comm, current->pid,
-               current_thread_info(), current, current->thread_info);
+               current_thread_info(), current, task_thread_info(current));
        /*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
         */
        if (in_kernel) {
                u8 *eip;
-               int code_bytes = 64;
+               unsigned int code_prologue = code_bytes * 43 / 64;
+               unsigned int code_len = code_bytes;
                unsigned char c;
 
                printk("\n" KERN_EMERG "Stack: ");
@@ -332,14 +321,14 @@ void show_registers(struct pt_regs *regs)
 
                printk(KERN_EMERG "Code: ");
 
-               eip = (u8 *)regs->eip - 43;
+               eip = (u8 *)regs->eip - code_prologue;
                if (eip < (u8 *)PAGE_OFFSET ||
                        probe_kernel_address(eip, c)) {
                        /* try starting at EIP */
                        eip = (u8 *)regs->eip;
-                       code_bytes = 32;
+                       code_len = code_len - code_prologue + 1;
                }
-               for (i = 0; i < code_bytes; i++, eip++) {
+               for (i = 0; i < code_len; i++, eip++) {
                        if (eip < (u8 *)PAGE_OFFSET ||
                                probe_kernel_address(eip, c)) {
                                printk(" Bad EIP value.");
@@ -473,8 +462,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
                              siginfo_t *info)
 {
        struct task_struct *tsk = current;
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = trapnr;
 
        if (regs->eflags & VM_MASK) {
                if (vm86)
@@ -486,6 +473,18 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
                goto kernel_trap;
 
        trap_signal: {
+               /*
+                * We want error_code and trap_no set for userspace faults and
+                * kernelspace faults which result in die(), but not
+                * kernelspace faults which are fixed up.  die() gives the
+                * process no chance to handle the signal and notice the
+                * kernel fault information, so that won't result in polluting
+                * the information about previously queued, but not yet
+                * delivered, faults.  See also do_general_protection below.
+                */
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
+
                if (info)
                        force_sig_info(signr, info, tsk);
                else
@@ -494,8 +493,11 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
        }
 
        kernel_trap: {
-               if (!fixup_exception(regs))
+               if (!fixup_exception(regs)) {
+                       tsk->thread.error_code = error_code;
+                       tsk->thread.trap_no = trapnr;
                        die(str, regs, error_code);
+               }
                return;
        }
 
@@ -580,7 +582,7 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
         * and we set the offset field correctly. Then we let the CPU to
         * restart the faulting instruction.
         */
-       if (tss->io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
+       if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
            thread->io_bitmap_ptr) {
                memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
                       thread->io_bitmap_max);
@@ -593,16 +595,13 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
                                thread->io_bitmap_max, 0xff,
                                tss->io_bitmap_max - thread->io_bitmap_max);
                tss->io_bitmap_max = thread->io_bitmap_max;
-               tss->io_bitmap_base = IO_BITMAP_OFFSET;
+               tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
                tss->io_bitmap_owner = thread;
                put_cpu();
                return;
        }
        put_cpu();
 
-       current->thread.error_code = error_code;
-       current->thread.trap_no = 13;
-
        if (regs->eflags & VM_MASK)
                goto gp_in_vm86;
 
@@ -621,6 +620,8 @@ gp_in_vm86:
 
 gp_in_kernel:
        if (!fixup_exception(regs)) {
+               current->thread.error_code = error_code;
+               current->thread.trap_no = 13;
                if (notify_die(DIE_GPF, "general protection fault", regs,
                                error_code, 13, SIGSEGV) == NOTIFY_STOP)
                        return;
@@ -1015,9 +1016,7 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
 fastcall unsigned long patch_espfix_desc(unsigned long uesp,
                                          unsigned long kesp)
 {
-       int cpu = smp_processor_id();
-       struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
-       struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address;
+       struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
        unsigned long base = (kesp - uesp) & -THREAD_SIZE;
        unsigned long new_kesp = kesp - base;
        unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
@@ -1191,3 +1190,13 @@ static int __init kstack_setup(char *s)
        return 1;
 }
 __setup("kstack=", kstack_setup);
+
+static int __init code_bytes_setup(char *s)
+{
+       code_bytes = simple_strtoul(s, NULL, 0);
+       if (code_bytes > 8192)
+               code_bytes = 8192;
+
+       return 1;
+}
+__setup("code_bytes=", code_bytes_setup);