[SPARC64]: Add infrastructure for dynamic TSB sizing.
[linux-2.6.git] / arch / sparc64 / kernel / process.c
index cffb1c8ab4fc4adb071e288954e6b95be9adf7cd..26548fc604b690377334ba548fe2b4f67ca26526 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/fpumacro.h>
 #include <asm/head.h>
 #include <asm/cpudata.h>
+#include <asm/mmu_context.h>
 #include <asm/unistd.h>
 
 /* #define VERBOSE_SHOWREGS */
@@ -74,7 +75,9 @@ void cpu_idle(void)
                while (!need_resched())
                        barrier();
 
+               preempt_enable_no_resched();
                schedule();
+               preempt_disable();
                check_pgt_cache();
        }
 }
@@ -83,27 +86,37 @@ void cpu_idle(void)
 
 /*
  * the idle loop on a UltraMultiPenguin...
+ *
+ * TIF_POLLING_NRFLAG is set because we do not sleep the cpu
+ * inside of the idler task, so an interrupt is not needed
+ * to get a clean fast response.
+ *
+ * XXX Reverify this assumption... -DaveM
+ *
+ * Addendum: We do want it to do something for the signal
+ *           delivery case, we detect that by just seeing
+ *           if we are trying to send this to an idler or not.
  */
-#define idle_me_harder()       (cpu_data(smp_processor_id()).idle_volume += 1)
-#define unidle_me()            (cpu_data(smp_processor_id()).idle_volume = 0)
 void cpu_idle(void)
 {
+       cpuinfo_sparc *cpuinfo = &local_cpu_data();
        set_thread_flag(TIF_POLLING_NRFLAG);
+
        while(1) {
                if (need_resched()) {
-                       unidle_me();
-                       clear_thread_flag(TIF_POLLING_NRFLAG);
+                       cpuinfo->idle_volume = 0;
+                       preempt_enable_no_resched();
                        schedule();
-                       set_thread_flag(TIF_POLLING_NRFLAG);
+                       preempt_disable();
                        check_pgt_cache();
                }
-               idle_me_harder();
+               cpuinfo->idle_volume++;
 
                /* The store ordering is so that IRQ handlers on
                 * other cpus see our increasing idleness for the buddy
                 * redistribution algorithm.  -DaveM
                 */
-               membar("#StoreStore | #StoreLoad");
+               membar_storeload_storestore();
        }
 }
 
@@ -124,8 +137,6 @@ void machine_halt(void)
        panic("Halt failed!");
 }
 
-EXPORT_SYMBOL(machine_halt);
-
 void machine_alt_power_off(void)
 {
        if (!serial_console && prom_palette)
@@ -154,8 +165,7 @@ void machine_restart(char * cmd)
        panic("Reboot failed!");
 }
 
-EXPORT_SYMBOL(machine_restart);
-
+#ifdef CONFIG_COMPAT
 static void show_regwindow32(struct pt_regs *regs)
 {
        struct reg_window32 __user *rw;
@@ -181,6 +191,9 @@ static void show_regwindow32(struct pt_regs *regs)
               r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3],
               r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);
 }
+#else
+#define show_regwindow32(regs) do { } while (0)
+#endif
 
 static void show_regwindow(struct pt_regs *regs)
 {
@@ -382,7 +395,7 @@ void show_regs32(struct pt_regs32 *regs)
 
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-       struct thread_info *ti = tsk->thread_info;
+       struct thread_info *ti = task_thread_info(tsk);
        unsigned long ret = 0xdeadbeefUL;
        
        if (ti && ti->ksp) {
@@ -421,30 +434,15 @@ void exit_thread(void)
 void flush_thread(void)
 {
        struct thread_info *t = current_thread_info();
+       struct mm_struct *mm;
 
        if (t->flags & _TIF_ABI_PENDING)
                t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT);
 
-       if (t->task->mm) {
-               unsigned long pgd_cache = 0UL;
-               if (test_thread_flag(TIF_32BIT)) {
-                       struct mm_struct *mm = t->task->mm;
-                       pgd_t *pgd0 = &mm->pgd[0];
-                       pud_t *pud0 = pud_offset(pgd0, 0);
+       mm = t->task->mm;
+       if (mm)
+               tsb_context_switch(mm);
 
-                       if (pud_none(*pud0)) {
-                               pmd_t *page = pmd_alloc_one(mm, 0);
-                               pud_set(pud0, page);
-                       }
-                       pgd_cache = get_pgd_cache(pgd0);
-               }
-               __asm__ __volatile__("stxa %0, [%1] %2\n\t"
-                                    "membar #Sync"
-                                    : /* no outputs */
-                                    : "r" (pgd_cache),
-                                    "r" (TSB_REG),
-                                    "i" (ASI_DMMU));
-       }
        set_thread_wsaved(0);
 
        /* Turn off performance counters if on. */
@@ -608,16 +606,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
                unsigned long unused,
                struct task_struct *p, struct pt_regs *regs)
 {
-       struct thread_info *t = p->thread_info;
+       struct thread_info *t = task_thread_info(p);
        char *child_trap_frame;
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-       p->thread.smp_lock_count = 0;
-       p->thread.smp_lock_pc = 0;
-#endif
-
        /* Calculate offset to stack_frame & pt_regs */
-       child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
+       child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
        memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ));
 
        t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
@@ -842,9 +835,9 @@ unsigned long get_wchan(struct task_struct *task)
             task->state == TASK_RUNNING)
                goto out;
 
-       thread_info_base = (unsigned long) task->thread_info;
+       thread_info_base = (unsigned long) task_stack_page(task);
        bias = STACK_BIAS;
-       fp = task->thread_info->ksp + bias;
+       fp = task_thread_info(task)->ksp + bias;
 
        do {
                /* Bogus frame pointer? */