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"); |
