]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/process_64.c
Merge branch 'master' of ../linux-2.6/
[linux-2.6] / arch / x86 / kernel / process_64.c
index 057b5442ffdab96ef00ac78f5c3021e645d63fa1..b0cc8f0136d8096e9e4cdad316787f89d4f55a8c 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/smp.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/utsname.h>
 #include <linux/delay.h>
@@ -170,14 +169,13 @@ void cpu_idle(void)
        current_thread_info()->status |= TS_POLLING;
        /* endless idle loop with no priority at all */
        while (1) {
+               tick_nohz_stop_sched_tick();
                while (!need_resched()) {
                        void (*idle)(void);
 
                        if (__get_cpu_var(cpu_idle_state))
                                __get_cpu_var(cpu_idle_state) = 0;
 
-                       tick_nohz_stop_sched_tick();
-
                        rmb();
                        idle = pm_idle;
                        if (!idle)
@@ -281,22 +279,38 @@ static void mwait_idle(void)
        }
 }
 
+
+static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+{
+       if (force_mwait)
+               return 1;
+       /* Any C1 states supported? */
+       return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0;
+}
+
 void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
-       static int printed;
-       if (cpu_has(c, X86_FEATURE_MWAIT)) {
+       static int selected;
+
+       if (selected)
+               return;
+#ifdef CONFIG_X86_SMP
+       if (pm_idle == poll_idle && smp_num_siblings > 1) {
+               printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+                       " performance may degrade.\n");
+       }
+#endif
+       if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
                /*
                 * Skip, if setup has overridden idle.
                 * One CPU supports mwait => All CPUs supports mwait
                 */
                if (!pm_idle) {
-                       if (!printed) {
-                               printk(KERN_INFO "using mwait in idle threads.\n");
-                               printed = 1;
-                       }
+                       printk(KERN_INFO "using mwait in idle threads.\n");
                        pm_idle = mwait_idle;
                }
        }
+       selected = 1;
 }
 
 static int __init idle_setup(char *str)
@@ -330,7 +344,7 @@ void __show_regs(struct pt_regs * regs)
                (int)strcspn(init_utsname()->version, " "),
                init_utsname()->version);
        printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
-       printk_address(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",
@@ -378,7 +392,7 @@ void show_regs(struct pt_regs *regs)
 {
        printk("CPU %d:", smp_processor_id());
        __show_regs(regs);
-       show_trace(NULL, regs, (void *)(regs + 1));
+       show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
 }
 
 /*
@@ -455,10 +469,9 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
                .limit_in_pages = 1,
                .useable = 1,
        };
-       struct n_desc_struct *desc = (void *)t->thread.tls_array;
+       struct desc_struct *desc = t->thread.tls_array;
        desc += tls;
-       desc->a = LDT_entry_a(&ud);
-       desc->b = LDT_entry_b(&ud);
+       fill_ldt(desc, &ud);
 }
 
 static inline u32 read_32bit_tls(struct task_struct *t, int tls)
@@ -545,34 +558,26 @@ out:
  */
 #define loaddebug(thread, r) set_debugreg(thread->debugreg ## r, r)
 
-/*
- * Capture the user space registers if the task is not running (in user space)
- */
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-       struct pt_regs *pp, ptregs;
-
-       pp = task_pt_regs(tsk);
-
-       ptregs = *pp;
-       ptregs.cs &= 0xffff;
-       ptregs.ss &= 0xffff;
-
-       elf_core_copy_regs(regs, &ptregs);
-
-       return 1;
-}
-
 static inline void __switch_to_xtra(struct task_struct *prev_p,
                                    struct task_struct *next_p,
                                    struct tss_struct *tss)
 {
        struct thread_struct *prev, *next;
+       unsigned long debugctl;
 
        prev = &prev_p->thread,
        next = &next_p->thread;
 
-       if (next->debugctlmsr != prev->debugctlmsr)
+       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;
+               wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
+               wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
+       }
+
+       if (next->debugctlmsr != debugctl)
                wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
 
        if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
@@ -598,6 +603,12 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
                 */
                memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
        }
+
+       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);
 }
 
 /*
@@ -624,7 +635,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /*
         * Reload esp0, LDT and the page table pointer:
         */
-       tss->sp0 = next->sp0;
+       load_sp0(tss, next);
 
        /* 
         * Switch DS and ES.
@@ -701,8 +712,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /*
         * Now maybe reload the debug registers and handle I/O bitmaps
         */
-       if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
-           || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
+       if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
+                    task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
                __switch_to_xtra(prev_p, next_p, tss);
 
        /* If the task has used fpu the last 5 timeslices, just do a full
@@ -914,4 +925,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
        unsigned long range_end = mm->brk + 0x02000000;
        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
 }
-