aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-21 19:55:23 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:13:54 -0500
commit30c91d576e9ea41c963e7f28643219bda73b0ddc (patch)
tree1aa37a82f44084b5fd854bf010ac224d2d660079 /arch
parent689126a48a4cf7efc77d0d090b2db4e8927d7819 (diff)
[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')
-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 @@
46#include <asm/cpudata.h> 46#include <asm/cpudata.h>
47#include <asm/mmu_context.h> 47#include <asm/mmu_context.h>
48#include <asm/unistd.h> 48#include <asm/unistd.h>
49#include <asm/hypervisor.h>
49 50
50/* #define VERBOSE_SHOWREGS */ 51/* #define VERBOSE_SHOWREGS */
51 52
52/* 53static void sparc64_yield(void)
53 * Nothing special yet...
54 */
55void default_idle(void)
56{
57}
58
59
60
61#ifndef CONFIG_SMP
62
63/*
64 * the idle loop on a Sparc... ;)
65 */
66void cpu_idle(void)
67{ 54{
68 /* endless idle loop with no priority at all */ 55 if (tlb_type != hypervisor)
69 for (;;) { 56 return;
70 /* If current->work.need_resched is zero we should really
71 * setup for a system wakup event and execute a shutdown
72 * instruction.
73 *
74 * But this requires writing back the contents of the
75 * L2 cache etc. so implement this later. -DaveM
76 */
77 while (!need_resched())
78 barrier();
79 57
80 preempt_enable_no_resched(); 58 clear_thread_flag(TIF_POLLING_NRFLAG);
81 schedule(); 59 smp_mb__after_clear_bit();
82 preempt_disable(); 60
83 check_pgt_cache(); 61 while (!need_resched()) {
62 unsigned long pstate;
63
64 /* Disable interrupts. */
65 __asm__ __volatile__(
66 "rdpr %%pstate, %0\n\t"
67 "andn %0, %1, %0\n\t"
68 "wrpr %0, %%g0, %%pstate"
69 : "=&r" (pstate)
70 : "i" (PSTATE_IE));
71
72 if (!need_resched())
73 sun4v_cpu_yield();
74
75 /* Re-enable interrupts. */
76 __asm__ __volatile__(
77 "rdpr %%pstate, %0\n\t"
78 "or %0, %1, %0\n\t"
79 "wrpr %0, %%g0, %%pstate"
80 : "=&r" (pstate)
81 : "i" (PSTATE_IE));
84 } 82 }
85}
86 83
87#else 84 set_thread_flag(TIF_POLLING_NRFLAG);
85}
88 86
89/* 87/* The idle loop on sparc64. */
90 * the idle loop on a UltraMultiPenguin...
91 *
92 * TIF_POLLING_NRFLAG is set because we do not sleep the cpu
93 * inside of the idler task, so an interrupt is not needed
94 * to get a clean fast response.
95 *
96 * XXX Reverify this assumption... -DaveM
97 *
98 * Addendum: We do want it to do something for the signal
99 * delivery case, we detect that by just seeing
100 * if we are trying to send this to an idler or not.
101 */
102void cpu_idle(void) 88void cpu_idle(void)
103{ 89{
104 cpuinfo_sparc *cpuinfo = &local_cpu_data();
105 set_thread_flag(TIF_POLLING_NRFLAG); 90 set_thread_flag(TIF_POLLING_NRFLAG);
106 91
107 while(1) { 92 while(1) {
@@ -109,13 +94,11 @@ void cpu_idle(void)
109 preempt_enable_no_resched(); 94 preempt_enable_no_resched();
110 schedule(); 95 schedule();
111 preempt_disable(); 96 preempt_disable();
112 check_pgt_cache();
113 } 97 }
98 sparc64_yield();
114 } 99 }
115} 100}
116 101
117#endif
118
119extern char reboot_command []; 102extern char reboot_command [];
120 103
121extern void (*prom_palette)(int); 104extern void (*prom_palette)(int);