diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-21 19:55:23 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:13:54 -0500 |
commit | 30c91d576e9ea41c963e7f28643219bda73b0ddc (patch) | |
tree | 1aa37a82f44084b5fd854bf010ac224d2d660079 /arch/sparc64/kernel/process.c | |
parent | 689126a48a4cf7efc77d0d090b2db4e8927d7819 (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/sparc64/kernel/process.c')
-rw-r--r-- | arch/sparc64/kernel/process.c | 81 |
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 | /* | 53 | static void sparc64_yield(void) |
53 | * Nothing special yet... | ||
54 | */ | ||
55 | void default_idle(void) | ||
56 | { | ||
57 | } | ||
58 | |||
59 | |||
60 | |||
61 | #ifndef CONFIG_SMP | ||
62 | |||
63 | /* | ||
64 | * the idle loop on a Sparc... ;) | ||
65 | */ | ||
66 | void 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 | */ | ||
102 | void cpu_idle(void) | 88 | void 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 | |||
119 | extern char reboot_command []; | 102 | extern char reboot_command []; |
120 | 103 | ||
121 | extern void (*prom_palette)(int); | 104 | extern void (*prom_palette)(int); |