diff options
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r-- | arch/i386/kernel/process.c | 39 |
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 | |||
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,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. */ | ||
153 | static 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 | ||
172 | static 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 | */ |
152 | void cpu_idle (void) | 184 | void 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 | } |