diff options
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r-- | arch/i386/kernel/process.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index aea2ce1145df..5f8cfa6b7940 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <stdarg.h> | 14 | #include <stdarg.h> |
15 | 15 | ||
16 | #include <linux/cpu.h> | ||
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
@@ -55,6 +56,9 @@ | |||
55 | #include <linux/irq.h> | 56 | #include <linux/irq.h> |
56 | #include <linux/err.h> | 57 | #include <linux/err.h> |
57 | 58 | ||
59 | #include <asm/tlbflush.h> | ||
60 | #include <asm/cpu.h> | ||
61 | |||
58 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 62 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
59 | 63 | ||
60 | static int hlt_counter; | 64 | static int hlt_counter; |
@@ -143,14 +147,42 @@ static void poll_idle (void) | |||
143 | } | 147 | } |
144 | } | 148 | } |
145 | 149 | ||
150 | #ifdef CONFIG_HOTPLUG_CPU | ||
151 | #include <asm/nmi.h> | ||
152 | /* We don't actually take CPU down, just spin without interrupts. */ | ||
153 | static inline void play_dead(void) | ||
154 | { | ||
155 | /* This must be done before dead CPU ack */ | ||
156 | cpu_exit_clear(); | ||
157 | wbinvd(); | ||
158 | mb(); | ||
159 | /* Ack it */ | ||
160 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
161 | |||
162 | /* | ||
163 | * With physical CPU hotplug, we should halt the cpu | ||
164 | */ | ||
165 | local_irq_disable(); | ||
166 | while (1) | ||
167 | __asm__ __volatile__("hlt":::"memory"); | ||
168 | } | ||
169 | #else | ||
170 | static inline void play_dead(void) | ||
171 | { | ||
172 | BUG(); | ||
173 | } | ||
174 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
175 | |||
146 | /* | 176 | /* |
147 | * The idle thread. There's no useful work to be | 177 | * The idle thread. There's no useful work to be |
148 | * done, so just try to conserve power and have a | 178 | * done, so just try to conserve power and have a |
149 | * low exit latency (ie sit in a loop waiting for | 179 | * low exit latency (ie sit in a loop waiting for |
150 | * somebody to say that they'd like to reschedule) | 180 | * somebody to say that they'd like to reschedule) |
151 | */ | 181 | */ |
152 | void cpu_idle (void) | 182 | void cpu_idle(void) |
153 | { | 183 | { |
184 | int cpu = raw_smp_processor_id(); | ||
185 | |||
154 | /* endless idle loop with no priority at all */ | 186 | /* endless idle loop with no priority at all */ |
155 | while (1) { | 187 | while (1) { |
156 | while (!need_resched()) { | 188 | while (!need_resched()) { |
@@ -165,6 +197,9 @@ void cpu_idle (void) | |||
165 | if (!idle) | 197 | if (!idle) |
166 | idle = default_idle; | 198 | idle = default_idle; |
167 | 199 | ||
200 | if (cpu_is_offline(cpu)) | ||
201 | play_dead(); | ||
202 | |||
168 | __get_cpu_var(irq_stat).idle_timestamp = jiffies; | 203 | __get_cpu_var(irq_stat).idle_timestamp = jiffies; |
169 | idle(); | 204 | idle(); |
170 | } | 205 | } |
@@ -223,7 +258,7 @@ static void mwait_idle(void) | |||
223 | } | 258 | } |
224 | } | 259 | } |
225 | 260 | ||
226 | void __init select_idle_routine(const struct cpuinfo_x86 *c) | 261 | void __devinit select_idle_routine(const struct cpuinfo_x86 *c) |
227 | { | 262 | { |
228 | if (cpu_has(c, X86_FEATURE_MWAIT)) { | 263 | if (cpu_has(c, X86_FEATURE_MWAIT)) { |
229 | printk("monitor/mwait feature present.\n"); | 264 | printk("monitor/mwait feature present.\n"); |