summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-22 01:55:23 +0100
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 10:13:54 +0100
commit30c91d576e9ea41c963e7f28643219bda73b0ddc (patch)
tree1aa37a82f44084b5fd854bf010ac224d2d660079 /arch/sparc64/kernel
parent[SPARC64] math-emu: Delete debugging printk left by previous commit. (diff)
downloadlinux-30c91d576e9ea41c963e7f28643219bda73b0ddc.tar.xz
linux-30c91d576e9ea41c963e7f28643219bda73b0ddc.zip
[SPARC64]: Use sun4v_cpu_idle() in cpu_idle() on SUN4V.
We have to turn off the "polling nrflag" bit when we sleep the cpu like this, so that we'll get a cross-cpu interrupt to wake the processor up from the yield. We also have to disable PSTATE_IE in %pstate around the yield call and recheck need_resched() in order to avoid any races. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/process.c81
1 files changed, 32 insertions, 49 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 1ab8283efc4c..1c7ca2f712d9 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -46,62 +46,47 @@
#include <asm/cpudata.h>
#include <asm/mmu_context.h>
#include <asm/unistd.h>
+#include <asm/hypervisor.h>
/* #define VERBOSE_SHOWREGS */
-/*
- * Nothing special yet...
- */
-void default_idle(void)
-{
-}
-
-
-
-#ifndef CONFIG_SMP
-
-/*
- * the idle loop on a Sparc... ;)
- */
-void cpu_idle(void)
+static void sparc64_yield(void)
{
- /* endless idle loop with no priority at all */
- for (;;) {
- /* If current->work.need_resched is zero we should really
- * setup for a system wakup event and execute a shutdown
- * instruction.
- *
- * But this requires writing back the contents of the
- * L2 cache etc. so implement this later. -DaveM
- */
- while (!need_resched())
- barrier();
+ if (tlb_type != hypervisor)
+ return;
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- check_pgt_cache();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb__after_clear_bit();
+
+ while (!need_resched()) {
+ unsigned long pstate;
+
+ /* Disable interrupts. */
+ __asm__ __volatile__(
+ "rdpr %%pstate, %0\n\t"
+ "andn %0, %1, %0\n\t"
+ "wrpr %0, %%g0, %%pstate"
+ : "=&r" (pstate)
+ : "i" (PSTATE_IE));
+
+ if (!need_resched())
+ sun4v_cpu_yield();
+
+ /* Re-enable interrupts. */
+ __asm__ __volatile__(
+ "rdpr %%pstate, %0\n\t"
+ "or %0, %1, %0\n\t"
+ "wrpr %0, %%g0, %%pstate"
+ : "=&r" (pstate)
+ : "i" (PSTATE_IE));
}
-}
-#else
+ set_thread_flag(TIF_POLLING_NRFLAG);
+}
-/*
- * 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.
- */
+/* The idle loop on sparc64. */
void cpu_idle(void)
{
- cpuinfo_sparc *cpuinfo = &local_cpu_data();
set_thread_flag(TIF_POLLING_NRFLAG);
while(1) {
@@ -109,13 +94,11 @@ void cpu_idle(void)
preempt_enable_no_resched();
schedule();
preempt_disable();
- check_pgt_cache();
}
+ sparc64_yield();
}
}
-#endif
-
extern char reboot_command [];
extern void (*prom_palette)(int);