x86: use generic register name in the thread and tss structures
[safe/jmp/linux-2.6] / arch / x86 / kernel / process_64.c
index 9895655..2381938 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/x86-64/kernel/process.c
- *
  *  Copyright (C) 1995  Linus Torvalds
  *
  *  Pentium III FXSR, SSE support
@@ -38,6 +36,7 @@
 #include <linux/notifier.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
+#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -73,13 +72,6 @@ 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(idle_notifier_unregister);
 
 void enter_idle(void)
 {
@@ -117,11 +109,18 @@ static void default_idle(void)
        smp_mb();
        local_irq_disable();
        if (!need_resched()) {
-               /* Enables interrupts one instruction before HLT.
-                  x86 special cases this so there is no race. */
-               safe_halt();
-       } else
-               local_irq_enable();
+               ktime_t t0, t1;
+               u64 t0n, t1n;
+
+               t0 = ktime_get();
+               t0n = ktime_to_ns(t0);
+               safe_halt();    /* enables interrupts racelessly */
+               local_irq_disable();
+               t1 = ktime_get();
+               t1n = ktime_to_ns(t1);
+               sched_clock_idle_wakeup_event(t1n - t0n);
+       }
+       local_irq_enable();
        current_thread_info()->status |= TS_POLLING;
 }
 
@@ -136,6 +135,10 @@ static void poll_idle (void)
        cpu_relax();
 }
 
+static void do_nothing(void *unused)
+{
+}
+
 void cpu_idle_wait(void)
 {
        unsigned int cpu, this_cpu = get_cpu();
@@ -161,6 +164,13 @@ void cpu_idle_wait(void)
                                cpu_clear(cpu, map);
                }
                cpus_and(map, map, cpu_online_map);
+               /*
+                * We waited 1 sec, if a CPU still did not call idle
+                * it may be because it is in idle and not waking up
+                * because it has nothing to do.
+                * Give all the remaining CPUS a kick.
+                */
+               smp_call_function_mask(map, do_nothing, 0, 0);
        } while (!cpus_empty(map));
 
        set_cpus_allowed(current, tmp);
@@ -197,7 +207,7 @@ static inline void play_dead(void)
  * low exit latency (ie sit in a loop waiting for
  * somebody to say that they'd like to reschedule)
  */
-void cpu_idle (void)
+void cpu_idle(void)
 {
        current_thread_info()->status |= TS_POLLING;
        /* endless idle loop with no priority at all */
@@ -208,6 +218,8 @@ void cpu_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)
@@ -228,6 +240,7 @@ void cpu_idle (void)
                        __exit_idle();
                }
 
+               tick_nohz_restart_sched_tick();
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
@@ -244,13 +257,13 @@ void cpu_idle (void)
  * New with Core Duo processors, MWAIT can take some hints based on CPU
  * capability.
  */
-void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
+void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
 {
        if (!need_resched()) {
                __monitor((void *)&current_thread_info()->flags, 0, 0);
                smp_mb();
                if (!need_resched())
-                       __mwait(eax, ecx);
+                       __mwait(ax, cx);
        }
 }
 
@@ -317,16 +330,16 @@ void __show_regs(struct pt_regs * regs)
                init_utsname()->release,
                (int)strcspn(init_utsname()->version, " "),
                init_utsname()->version);
-       printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
-       printk_address(regs->rip); 
-       printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp,
-               regs->eflags);
+       printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
+       printk_address(regs->ip);
+       printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->sp,
+               regs->flags);
        printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
-              regs->rax, regs->rbx, regs->rcx);
+              regs->ax, regs->bx, regs->cx);
        printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
-              regs->rdx, regs->rsi, regs->rdi); 
+              regs->dx, regs->si, regs->di);
        printk("RBP: %016lx R08: %016lx R09: %016lx\n",
-              regs->rbp, regs->r8, regs->r9); 
+              regs->bp, regs->r8, regs->r9);
        printk("R10: %016lx R11: %016lx R12: %016lx\n",
               regs->r10, regs->r11, regs->r12); 
        printk("R13: %016lx R14: %016lx R15: %016lx\n",
@@ -451,11 +464,7 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
 
 static inline u32 read_32bit_tls(struct task_struct *t, int tls)
 {
-       struct desc_struct *desc = (void *)t->thread.tls_array;
-       desc += tls;
-       return desc->base0 | 
-               (((u32)desc->base1) << 16) | 
-               (((u32)desc->base2) << 24);
+       return get_desc_base(&t->thread.tls_array[tls]);
 }
 
 /*
@@ -467,7 +476,7 @@ void prepare_to_copy(struct task_struct *tsk)
        unlazy_fpu(tsk);
 }
 
-int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, 
+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
                unsigned long unused,
        struct task_struct * p, struct pt_regs * regs)
 {
@@ -479,14 +488,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
                        (THREAD_SIZE + task_stack_page(p))) - 1;
        *childregs = *regs;
 
-       childregs->rax = 0;
-       childregs->rsp = rsp;
-       if (rsp == ~0UL)
-               childregs->rsp = (unsigned long)childregs;
+       childregs->ax = 0;
+       childregs->sp = sp;
+       if (sp == ~0UL)
+               childregs->sp = (unsigned long)childregs;
 
-       p->thread.rsp = (unsigned long) childregs;
-       p->thread.rsp0 = (unsigned long) (childregs+1);
-       p->thread.userrsp = me->thread.userrsp; 
+       p->thread.sp = (unsigned long) childregs;
+       p->thread.sp0 = (unsigned long) (childregs+1);
+       p->thread.usersp = me->thread.usersp;
 
        set_tsk_thread_flag(p, TIF_FORK);
 
@@ -515,7 +524,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
        if (clone_flags & CLONE_SETTLS) {
 #ifdef CONFIG_IA32_EMULATION
                if (test_thread_flag(TIF_IA32))
-                       err = ia32_child_tls(p, childregs); 
+                       err = do_set_thread_area(p, -1,
+                               (struct user_desc __user *)childregs->si, 0);
                else                    
 #endif  
                        err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); 
@@ -545,6 +555,9 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
        prev = &prev_p->thread,
        next = &next_p->thread;
 
+       if (next->debugctlmsr != prev->debugctlmsr)
+               wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
+
        if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
                loaddebug(next, 0);
                loaddebug(next, 1);
@@ -579,7 +592,7 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
  *
  * Kprobes not supported here. Set the probe on schedule instead.
  */
-__kprobes struct task_struct *
+struct task_struct *
 __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 {
        struct thread_struct *prev = &prev_p->thread,
@@ -594,7 +607,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /*
         * Reload esp0, LDT and the page table pointer:
         */
-       tss->rsp0 = next->rsp0;
+       tss->sp0 = next->sp0;
 
        /* 
         * Switch DS and ES.
@@ -653,8 +666,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /* 
         * Switch the PDA and FPU contexts.
         */
-       prev->userrsp = read_pda(oldrsp); 
-       write_pda(oldrsp, next->userrsp); 
+       prev->usersp = read_pda(oldrsp);
+       write_pda(oldrsp, next->usersp);
        write_pda(pcurrent, next_p); 
 
        write_pda(kernelstack,
@@ -699,11 +712,6 @@ long sys_execve(char __user *name, char __user * __user *argv,
        if (IS_ERR(filename)) 
                return error;
        error = do_execve(filename, argv, envp, &regs); 
-       if (error == 0) {
-               task_lock(current);
-               current->ptrace &= ~PT_DTRACE;
-               task_unlock(current);
-       }
        putname(filename);
        return error;
 }
@@ -724,7 +732,7 @@ void set_personality_64bit(void)
 
 asmlinkage long sys_fork(struct pt_regs *regs)
 {
-       return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
+       return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
 }
 
 asmlinkage long
@@ -732,7 +740,7 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
          void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
 {
        if (!newsp)
-               newsp = regs->rsp;
+               newsp = regs->sp;
        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
@@ -748,29 +756,29 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
  */
 asmlinkage long sys_vfork(struct pt_regs *regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
                    NULL, NULL);
 }
 
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long stack;
-       u64 fp,rip;
+       u64 fp,ip;
        int count = 0;
 
        if (!p || p == current || p->state==TASK_RUNNING)
                return 0; 
        stack = (unsigned long)task_stack_page(p);
-       if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE)
+       if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE)
                return 0;
-       fp = *(u64 *)(p->thread.rsp);
+       fp = *(u64 *)(p->thread.sp);
        do { 
                if (fp < (unsigned long)stack ||
                    fp > (unsigned long)stack+THREAD_SIZE)
                        return 0; 
-               rip = *(u64 *)(fp+8); 
-               if (!in_sched_functions(rip))
-                       return rip; 
+               ip = *(u64 *)(fp+8);
+               if (!in_sched_functions(ip))
+                       return ip;
                fp = *(u64 *)fp; 
        } while (count++ < 16); 
        return 0;
@@ -901,3 +909,10 @@ unsigned long arch_align_stack(unsigned long sp)
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }
+
+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;
+}
+