Merge branch 'x86/crashdump' into cpus4096
[safe/jmp/linux-2.6] / arch / x86 / kernel / process_64.c
index 4da8514..fbb321d 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/prctl.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
+#include <linux/ftrace.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -51,6 +52,7 @@
 #include <asm/proto.h>
 #include <asm/ia32.h>
 #include <asm/idle.h>
+#include <asm/syscalls.h>
 
 asmlinkage extern void ret_from_fork(void);
 
@@ -62,6 +64,13 @@ void idle_notifier_register(struct notifier_block *n)
 {
        atomic_notifier_chain_register(&idle_notifier, n);
 }
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+       atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
 
 void enter_idle(void)
 {
@@ -85,29 +94,12 @@ void exit_idle(void)
        __exit_idle();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-DECLARE_PER_CPU(int, cpu_state);
-
-#include <linux/nmi.h>
-/* We halt the CPU with physical CPU hotplug */
-static inline void play_dead(void)
-{
-       idle_task_exit();
-       wbinvd();
-       mb();
-       /* Ack it */
-       __get_cpu_var(cpu_state) = CPU_DEAD;
-
-       local_irq_disable();
-       while (1)
-               halt();
-}
-#else
+#ifndef CONFIG_SMP
 static inline void play_dead(void)
 {
        BUG();
 }
-#endif /* CONFIG_HOTPLUG_CPU */
+#endif
 
 /*
  * The idle thread. There's no useful work to be
@@ -152,7 +144,7 @@ void cpu_idle(void)
 }
 
 /* Prints also some state that isn't saved in the pt_regs */
-void __show_regs(struct pt_regs *regs)
+void __show_regs(struct pt_regs *regs, int all)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
        unsigned long d0, d1, d2, d3, d6, d7;
@@ -161,24 +153,24 @@ void __show_regs(struct pt_regs *regs)
 
        printk("\n");
        print_modules();
-       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+       printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n",
                current->pid, current->comm, print_tainted(),
                init_utsname()->release,
                (int)strcspn(init_utsname()->version, " "),
                init_utsname()->version);
-       printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
+       printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
        printk_address(regs->ip, 1);
-       printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->sp,
-               regs->flags);
-       printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+       printk(KERN_INFO "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
+                       regs->sp, regs->flags);
+       printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
               regs->ax, regs->bx, regs->cx);
-       printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+       printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
               regs->dx, regs->si, regs->di);
-       printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+       printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
               regs->bp, regs->r8, regs->r9);
-       printk("R10: %016lx R11: %016lx R12: %016lx\n",
+       printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
               regs->r10, regs->r11, regs->r12);
-       printk("R13: %016lx R14: %016lx R15: %016lx\n",
+       printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
               regs->r13, regs->r14, regs->r15);
 
        asm("movl %%ds,%0" : "=r" (ds));
@@ -191,30 +183,35 @@ void __show_regs(struct pt_regs *regs)
        rdmsrl(MSR_GS_BASE, gs);
        rdmsrl(MSR_KERNEL_GS_BASE, shadowgs);
 
+       if (!all)
+               return;
+
        cr0 = read_cr0();
        cr2 = read_cr2();
        cr3 = read_cr3();
        cr4 = read_cr4();
 
-       printk("FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
+       printk(KERN_INFO "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
               fs, fsindex, gs, gsindex, shadowgs);
-       printk("CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0);
-       printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4);
+       printk(KERN_INFO "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
+                       es, cr0);
+       printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
+                       cr4);
 
        get_debugreg(d0, 0);
        get_debugreg(d1, 1);
        get_debugreg(d2, 2);
-       printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
+       printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
        get_debugreg(d3, 3);
        get_debugreg(d6, 6);
        get_debugreg(d7, 7);
-       printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
+       printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
 }
 
 void show_regs(struct pt_regs *regs)
 {
-       printk("CPU %d:", smp_processor_id());
-       __show_regs(regs);
+       printk(KERN_INFO "CPU %d:", smp_processor_id());
+       __show_regs(regs, 1);
        show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
 }
 
@@ -239,6 +236,14 @@ void exit_thread(void)
                t->io_bitmap_max = 0;
                put_cpu();
        }
+#ifdef CONFIG_X86_DS
+       /* Free any DS contexts that have not been properly released. */
+       if (unlikely(t->ds_ctx)) {
+               /* we clear debugctl to make sure DS is not used. */
+               update_debugctlmsr(0);
+               ds_free(t->ds_ctx);
+       }
+#endif /* CONFIG_X86_DS */
 }
 
 void flush_thread(void)
@@ -472,13 +477,27 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
        next = &next_p->thread;
 
        debugctl = prev->debugctlmsr;
-       if (next->ds_area_msr != prev->ds_area_msr) {
-               /* we clear debugctl to make sure DS
-                * is not in use when we change it */
-               debugctl = 0;
-               update_debugctlmsr(0);
-               wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
+
+#ifdef CONFIG_X86_DS
+       {
+               unsigned long ds_prev = 0, ds_next = 0;
+
+               if (prev->ds_ctx)
+                       ds_prev = (unsigned long)prev->ds_ctx->ds;
+               if (next->ds_ctx)
+                       ds_next = (unsigned long)next->ds_ctx->ds;
+
+               if (ds_next != ds_prev) {
+                       /*
+                        * We clear debugctl to make sure DS
+                        * is not in use when we change it:
+                        */
+                       debugctl = 0;
+                       update_debugctlmsr(0);
+                       wrmsrl(MSR_IA32_DS_AREA, ds_next);
+               }
        }
+#endif /* CONFIG_X86_DS */
 
        if (next->debugctlmsr != debugctl)
                update_debugctlmsr(next->debugctlmsr);
@@ -516,13 +535,13 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
                memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
        }
 
-#ifdef X86_BTS
+#ifdef CONFIG_X86_PTRACE_BTS
        if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
                ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
 
        if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
                ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
-#endif
+#endif /* CONFIG_X86_PTRACE_BTS */
 }
 
 /*
@@ -533,8 +552,9 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
  * - could test fs/gs bitsliced
  *
  * Kprobes not supported here. Set the probe on schedule instead.
+ * Function graph tracer not supported too.
  */
-struct task_struct *
+__notrace_funcgraph struct task_struct *
 __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 {
        struct thread_struct *prev = &prev_p->thread;
@@ -728,12 +748,12 @@ unsigned long get_wchan(struct task_struct *p)
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
        stack = (unsigned long)task_stack_page(p);
-       if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE)
+       if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
                return 0;
        fp = *(u64 *)(p->thread.sp);
        do {
                if (fp < (unsigned long)stack ||
-                   fp > (unsigned long)stack+THREAD_SIZE)
+                   fp >= (unsigned long)stack+THREAD_SIZE)
                        return 0;
                ip = *(u64 *)(fp+8);
                if (!in_sched_functions(ip))