aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/process.c')
-rw-r--r--arch/x86_64/kernel/process.c80
1 files changed, 76 insertions, 4 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 761b6d35e338..7577f9d7a75d 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -8,7 +8,8 @@
8 * 8 *
9 * X86-64 port 9 * X86-64 port
10 * Andi Kleen. 10 * Andi Kleen.
11 * 11 *
12 * CPU hotplug support - ashok.raj@intel.com
12 * $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $ 13 * $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $
13 */ 14 */
14 15
@@ -18,6 +19,7 @@
18 19
19#include <stdarg.h> 20#include <stdarg.h>
20 21
22#include <linux/cpu.h>
21#include <linux/errno.h> 23#include <linux/errno.h>
22#include <linux/sched.h> 24#include <linux/sched.h>
23#include <linux/kernel.h> 25#include <linux/kernel.h>
@@ -34,6 +36,7 @@
34#include <linux/ptrace.h> 36#include <linux/ptrace.h>
35#include <linux/utsname.h> 37#include <linux/utsname.h>
36#include <linux/random.h> 38#include <linux/random.h>
39#include <linux/kprobes.h>
37 40
38#include <asm/uaccess.h> 41#include <asm/uaccess.h>
39#include <asm/pgtable.h> 42#include <asm/pgtable.h>
@@ -153,6 +156,29 @@ void cpu_idle_wait(void)
153} 156}
154EXPORT_SYMBOL_GPL(cpu_idle_wait); 157EXPORT_SYMBOL_GPL(cpu_idle_wait);
155 158
159#ifdef CONFIG_HOTPLUG_CPU
160DECLARE_PER_CPU(int, cpu_state);
161
162#include <asm/nmi.h>
163/* We don't actually take CPU down, just spin without interrupts. */
164static inline void play_dead(void)
165{
166 idle_task_exit();
167 wbinvd();
168 mb();
169 /* Ack it */
170 __get_cpu_var(cpu_state) = CPU_DEAD;
171
172 while (1)
173 safe_halt();
174}
175#else
176static inline void play_dead(void)
177{
178 BUG();
179}
180#endif /* CONFIG_HOTPLUG_CPU */
181
156/* 182/*
157 * The idle thread. There's no useful work to be 183 * The idle thread. There's no useful work to be
158 * done, so just try to conserve power and have a 184 * done, so just try to conserve power and have a
@@ -173,6 +199,8 @@ void cpu_idle (void)
173 idle = pm_idle; 199 idle = pm_idle;
174 if (!idle) 200 if (!idle)
175 idle = default_idle; 201 idle = default_idle;
202 if (cpu_is_offline(smp_processor_id()))
203 play_dead();
176 idle(); 204 idle();
177 } 205 }
178 206
@@ -203,7 +231,7 @@ static void mwait_idle(void)
203 } 231 }
204} 232}
205 233
206void __init select_idle_routine(const struct cpuinfo_x86 *c) 234void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
207{ 235{
208 static int printed; 236 static int printed;
209 if (cpu_has(c, X86_FEATURE_MWAIT)) { 237 if (cpu_has(c, X86_FEATURE_MWAIT)) {
@@ -293,6 +321,14 @@ void exit_thread(void)
293{ 321{
294 struct task_struct *me = current; 322 struct task_struct *me = current;
295 struct thread_struct *t = &me->thread; 323 struct thread_struct *t = &me->thread;
324
325 /*
326 * Remove function-return probe instances associated with this task
327 * and put them back on the free list. Do not insert an exit probe for
328 * this function, it will be disabled by kprobe_flush_task if you do.
329 */
330 kprobe_flush_task(me);
331
296 if (me->thread.io_bitmap_ptr) { 332 if (me->thread.io_bitmap_ptr) {
297 struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); 333 struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
298 334
@@ -312,6 +348,13 @@ void flush_thread(void)
312 struct task_struct *tsk = current; 348 struct task_struct *tsk = current;
313 struct thread_info *t = current_thread_info(); 349 struct thread_info *t = current_thread_info();
314 350
351 /*
352 * Remove function-return probe instances associated with this task
353 * and put them back on the free list. Do not insert an exit probe for
354 * this function, it will be disabled by kprobe_flush_task if you do.
355 */
356 kprobe_flush_task(tsk);
357
315 if (t->flags & _TIF_ABI_PENDING) 358 if (t->flags & _TIF_ABI_PENDING)
316 t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); 359 t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
317 360
@@ -439,6 +482,33 @@ out:
439} 482}
440 483
441/* 484/*
485 * This function selects if the context switch from prev to next
486 * has to tweak the TSC disable bit in the cr4.
487 */
488static inline void disable_tsc(struct task_struct *prev_p,
489 struct task_struct *next_p)
490{
491 struct thread_info *prev, *next;
492
493 /*
494 * gcc should eliminate the ->thread_info dereference if
495 * has_secure_computing returns 0 at compile time (SECCOMP=n).
496 */
497 prev = prev_p->thread_info;
498 next = next_p->thread_info;
499
500 if (has_secure_computing(prev) || has_secure_computing(next)) {
501 /* slow path here */
502 if (has_secure_computing(prev) &&
503 !has_secure_computing(next)) {
504 write_cr4(read_cr4() & ~X86_CR4_TSD);
505 } else if (!has_secure_computing(prev) &&
506 has_secure_computing(next))
507 write_cr4(read_cr4() | X86_CR4_TSD);
508 }
509}
510
511/*
442 * This special macro can be used to load a debugging register 512 * This special macro can be used to load a debugging register
443 */ 513 */
444#define loaddebug(thread,r) set_debug(thread->debugreg ## r, r) 514#define loaddebug(thread,r) set_debug(thread->debugreg ## r, r)
@@ -556,6 +626,8 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
556 } 626 }
557 } 627 }
558 628
629 disable_tsc(prev_p, next_p);
630
559 return prev_p; 631 return prev_p;
560} 632}
561 633
@@ -656,7 +728,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
656 728
657 switch (code) { 729 switch (code) {
658 case ARCH_SET_GS: 730 case ARCH_SET_GS:
659 if (addr >= TASK_SIZE) 731 if (addr >= TASK_SIZE_OF(task))
660 return -EPERM; 732 return -EPERM;
661 cpu = get_cpu(); 733 cpu = get_cpu();
662 /* handle small bases via the GDT because that's faster to 734 /* handle small bases via the GDT because that's faster to
@@ -682,7 +754,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
682 case ARCH_SET_FS: 754 case ARCH_SET_FS:
683 /* Not strictly needed for fs, but do it for symmetry 755 /* Not strictly needed for fs, but do it for symmetry
684 with gs */ 756 with gs */
685 if (addr >= TASK_SIZE) 757 if (addr >= TASK_SIZE_OF(task))
686 return -EPERM; 758 return -EPERM;
687 cpu = get_cpu(); 759 cpu = get_cpu();
688 /* handle small bases via the GDT because that's faster to 760 /* handle small bases via the GDT because that's faster to