aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r--arch/i386/kernel/process.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index aea2ce1145df..c1b11e8df60b 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
58asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 62asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
59 63
60static int hlt_counter; 64static int hlt_counter;
@@ -143,14 +147,44 @@ 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. */
153static inline void play_dead(void)
154{
155 /* Ack it */
156 __get_cpu_var(cpu_state) = CPU_DEAD;
157
158 /* We shouldn't have to disable interrupts while dead, but
159 * some interrupts just don't seem to go away, and this makes
160 * it "work" for testing purposes. */
161 /* Death loop */
162 while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
163 cpu_relax();
164
165 local_irq_disable();
166 __flush_tlb_all();
167 cpu_set(smp_processor_id(), cpu_online_map);
168 enable_APIC_timer();
169 local_irq_enable();
170}
171#else
172static inline void play_dead(void)
173{
174 BUG();
175}
176#endif /* CONFIG_HOTPLUG_CPU */
177
146/* 178/*
147 * The idle thread. There's no useful work to be 179 * The idle thread. There's no useful work to be
148 * done, so just try to conserve power and have a 180 * done, so just try to conserve power and have a
149 * low exit latency (ie sit in a loop waiting for 181 * low exit latency (ie sit in a loop waiting for
150 * somebody to say that they'd like to reschedule) 182 * somebody to say that they'd like to reschedule)
151 */ 183 */
152void cpu_idle (void) 184void cpu_idle(void)
153{ 185{
186 int cpu = raw_smp_processor_id();
187
154 /* endless idle loop with no priority at all */ 188 /* endless idle loop with no priority at all */
155 while (1) { 189 while (1) {
156 while (!need_resched()) { 190 while (!need_resched()) {
@@ -165,6 +199,9 @@ void cpu_idle (void)
165 if (!idle) 199 if (!idle)
166 idle = default_idle; 200 idle = default_idle;
167 201
202 if (cpu_is_offline(cpu))
203 play_dead();
204
168 __get_cpu_var(irq_stat).idle_timestamp = jiffies; 205 __get_cpu_var(irq_stat).idle_timestamp = jiffies;
169 idle(); 206 idle();
170 } 207 }