diff options
Diffstat (limited to 'arch/x86/kernel/process_32.c')
-rw-r--r-- | arch/x86/kernel/process_32.c | 101 |
1 files changed, 53 insertions, 48 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 3b7a1ddcc0bc..922c14058f97 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/tick.h> | 37 | #include <linux/tick.h> |
38 | #include <linux/percpu.h> | 38 | #include <linux/percpu.h> |
39 | #include <linux/prctl.h> | 39 | #include <linux/prctl.h> |
40 | #include <linux/dmi.h> | ||
40 | 41 | ||
41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
42 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
@@ -55,6 +56,9 @@ | |||
55 | #include <asm/tlbflush.h> | 56 | #include <asm/tlbflush.h> |
56 | #include <asm/cpu.h> | 57 | #include <asm/cpu.h> |
57 | #include <asm/kdebug.h> | 58 | #include <asm/kdebug.h> |
59 | #include <asm/idle.h> | ||
60 | #include <asm/syscalls.h> | ||
61 | #include <asm/smp.h> | ||
58 | 62 | ||
59 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 63 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
60 | 64 | ||
@@ -72,46 +76,12 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
72 | return ((unsigned long *)tsk->thread.sp)[3]; | 76 | return ((unsigned long *)tsk->thread.sp)[3]; |
73 | } | 77 | } |
74 | 78 | ||
75 | #ifdef CONFIG_HOTPLUG_CPU | 79 | #ifndef CONFIG_SMP |
76 | #include <asm/nmi.h> | ||
77 | |||
78 | static void cpu_exit_clear(void) | ||
79 | { | ||
80 | int cpu = raw_smp_processor_id(); | ||
81 | |||
82 | idle_task_exit(); | ||
83 | |||
84 | cpu_uninit(); | ||
85 | irq_ctx_exit(cpu); | ||
86 | |||
87 | cpu_clear(cpu, cpu_callout_map); | ||
88 | cpu_clear(cpu, cpu_callin_map); | ||
89 | |||
90 | numa_remove_cpu(cpu); | ||
91 | } | ||
92 | |||
93 | /* We don't actually take CPU down, just spin without interrupts. */ | ||
94 | static inline void play_dead(void) | ||
95 | { | ||
96 | /* This must be done before dead CPU ack */ | ||
97 | cpu_exit_clear(); | ||
98 | mb(); | ||
99 | /* Ack it */ | ||
100 | __get_cpu_var(cpu_state) = CPU_DEAD; | ||
101 | |||
102 | /* | ||
103 | * With physical CPU hotplug, we should halt the cpu | ||
104 | */ | ||
105 | local_irq_disable(); | ||
106 | /* mask all interrupts, flush any and all caches, and halt */ | ||
107 | wbinvd_halt(); | ||
108 | } | ||
109 | #else | ||
110 | static inline void play_dead(void) | 80 | static inline void play_dead(void) |
111 | { | 81 | { |
112 | BUG(); | 82 | BUG(); |
113 | } | 83 | } |
114 | #endif /* CONFIG_HOTPLUG_CPU */ | 84 | #endif |
115 | 85 | ||
116 | /* | 86 | /* |
117 | * The idle thread. There's no useful work to be | 87 | * The idle thread. There's no useful work to be |
@@ -159,6 +129,7 @@ void __show_registers(struct pt_regs *regs, int all) | |||
159 | unsigned long d0, d1, d2, d3, d6, d7; | 129 | unsigned long d0, d1, d2, d3, d6, d7; |
160 | unsigned long sp; | 130 | unsigned long sp; |
161 | unsigned short ss, gs; | 131 | unsigned short ss, gs; |
132 | const char *board; | ||
162 | 133 | ||
163 | if (user_mode_vm(regs)) { | 134 | if (user_mode_vm(regs)) { |
164 | sp = regs->sp; | 135 | sp = regs->sp; |
@@ -171,11 +142,15 @@ void __show_registers(struct pt_regs *regs, int all) | |||
171 | } | 142 | } |
172 | 143 | ||
173 | printk("\n"); | 144 | printk("\n"); |
174 | printk("Pid: %d, comm: %s %s (%s %.*s)\n", | 145 | |
146 | board = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
147 | if (!board) | ||
148 | board = ""; | ||
149 | printk("Pid: %d, comm: %s %s (%s %.*s) %s\n", | ||
175 | task_pid_nr(current), current->comm, | 150 | task_pid_nr(current), current->comm, |
176 | print_tainted(), init_utsname()->release, | 151 | print_tainted(), init_utsname()->release, |
177 | (int)strcspn(init_utsname()->version, " "), | 152 | (int)strcspn(init_utsname()->version, " "), |
178 | init_utsname()->version); | 153 | init_utsname()->version, board); |
179 | 154 | ||
180 | printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", | 155 | printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", |
181 | (u16)regs->cs, regs->ip, regs->flags, | 156 | (u16)regs->cs, regs->ip, regs->flags, |
@@ -275,6 +250,14 @@ void exit_thread(void) | |||
275 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | 250 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; |
276 | put_cpu(); | 251 | put_cpu(); |
277 | } | 252 | } |
253 | #ifdef CONFIG_X86_DS | ||
254 | /* Free any DS contexts that have not been properly released. */ | ||
255 | if (unlikely(current->thread.ds_ctx)) { | ||
256 | /* we clear debugctl to make sure DS is not used. */ | ||
257 | update_debugctlmsr(0); | ||
258 | ds_free(current->thread.ds_ctx); | ||
259 | } | ||
260 | #endif /* CONFIG_X86_DS */ | ||
278 | } | 261 | } |
279 | 262 | ||
280 | void flush_thread(void) | 263 | void flush_thread(void) |
@@ -436,6 +419,35 @@ int set_tsc_mode(unsigned int val) | |||
436 | return 0; | 419 | return 0; |
437 | } | 420 | } |
438 | 421 | ||
422 | #ifdef CONFIG_X86_DS | ||
423 | static int update_debugctl(struct thread_struct *prev, | ||
424 | struct thread_struct *next, unsigned long debugctl) | ||
425 | { | ||
426 | unsigned long ds_prev = 0; | ||
427 | unsigned long ds_next = 0; | ||
428 | |||
429 | if (prev->ds_ctx) | ||
430 | ds_prev = (unsigned long)prev->ds_ctx->ds; | ||
431 | if (next->ds_ctx) | ||
432 | ds_next = (unsigned long)next->ds_ctx->ds; | ||
433 | |||
434 | if (ds_next != ds_prev) { | ||
435 | /* we clear debugctl to make sure DS | ||
436 | * is not in use when we change it */ | ||
437 | debugctl = 0; | ||
438 | update_debugctlmsr(0); | ||
439 | wrmsr(MSR_IA32_DS_AREA, ds_next, 0); | ||
440 | } | ||
441 | return debugctl; | ||
442 | } | ||
443 | #else | ||
444 | static int update_debugctl(struct thread_struct *prev, | ||
445 | struct thread_struct *next, unsigned long debugctl) | ||
446 | { | ||
447 | return debugctl; | ||
448 | } | ||
449 | #endif /* CONFIG_X86_DS */ | ||
450 | |||
439 | static noinline void | 451 | static noinline void |
440 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | 452 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, |
441 | struct tss_struct *tss) | 453 | struct tss_struct *tss) |
@@ -446,14 +458,7 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
446 | prev = &prev_p->thread; | 458 | prev = &prev_p->thread; |
447 | next = &next_p->thread; | 459 | next = &next_p->thread; |
448 | 460 | ||
449 | debugctl = prev->debugctlmsr; | 461 | debugctl = update_debugctl(prev, next, prev->debugctlmsr); |
450 | if (next->ds_area_msr != prev->ds_area_msr) { | ||
451 | /* we clear debugctl to make sure DS | ||
452 | * is not in use when we change it */ | ||
453 | debugctl = 0; | ||
454 | update_debugctlmsr(0); | ||
455 | wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0); | ||
456 | } | ||
457 | 462 | ||
458 | if (next->debugctlmsr != debugctl) | 463 | if (next->debugctlmsr != debugctl) |
459 | update_debugctlmsr(next->debugctlmsr); | 464 | update_debugctlmsr(next->debugctlmsr); |
@@ -477,13 +482,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
477 | hard_enable_TSC(); | 482 | hard_enable_TSC(); |
478 | } | 483 | } |
479 | 484 | ||
480 | #ifdef X86_BTS | 485 | #ifdef CONFIG_X86_PTRACE_BTS |
481 | if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) | 486 | if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) |
482 | ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); | 487 | ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); |
483 | 488 | ||
484 | if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) | 489 | if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) |
485 | ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); | 490 | ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); |
486 | #endif | 491 | #endif /* CONFIG_X86_PTRACE_BTS */ |
487 | 492 | ||
488 | 493 | ||
489 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 494 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { |