diff options
Diffstat (limited to 'arch/x86/kernel/process_64.c')
-rw-r--r-- | arch/x86/kernel/process_64.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 416fb9282f4f..836ef6575f01 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <stdarg.h> | 17 | #include <stdarg.h> |
18 | 18 | ||
19 | #include <linux/stackprotector.h> | ||
19 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
20 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
@@ -40,13 +41,13 @@ | |||
40 | #include <linux/uaccess.h> | 41 | #include <linux/uaccess.h> |
41 | #include <linux/io.h> | 42 | #include <linux/io.h> |
42 | #include <linux/ftrace.h> | 43 | #include <linux/ftrace.h> |
44 | #include <linux/dmi.h> | ||
43 | 45 | ||
44 | #include <asm/pgtable.h> | 46 | #include <asm/pgtable.h> |
45 | #include <asm/system.h> | 47 | #include <asm/system.h> |
46 | #include <asm/processor.h> | 48 | #include <asm/processor.h> |
47 | #include <asm/i387.h> | 49 | #include <asm/i387.h> |
48 | #include <asm/mmu_context.h> | 50 | #include <asm/mmu_context.h> |
49 | #include <asm/pda.h> | ||
50 | #include <asm/prctl.h> | 51 | #include <asm/prctl.h> |
51 | #include <asm/desc.h> | 52 | #include <asm/desc.h> |
52 | #include <asm/proto.h> | 53 | #include <asm/proto.h> |
@@ -57,6 +58,12 @@ | |||
57 | 58 | ||
58 | asmlinkage extern void ret_from_fork(void); | 59 | asmlinkage extern void ret_from_fork(void); |
59 | 60 | ||
61 | DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; | ||
62 | EXPORT_PER_CPU_SYMBOL(current_task); | ||
63 | |||
64 | DEFINE_PER_CPU(unsigned long, old_rsp); | ||
65 | static DEFINE_PER_CPU(unsigned char, is_idle); | ||
66 | |||
60 | unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; | 67 | unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; |
61 | 68 | ||
62 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); | 69 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); |
@@ -75,13 +82,13 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister); | |||
75 | 82 | ||
76 | void enter_idle(void) | 83 | void enter_idle(void) |
77 | { | 84 | { |
78 | write_pda(isidle, 1); | 85 | percpu_write(is_idle, 1); |
79 | atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); | 86 | atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); |
80 | } | 87 | } |
81 | 88 | ||
82 | static void __exit_idle(void) | 89 | static void __exit_idle(void) |
83 | { | 90 | { |
84 | if (test_and_clear_bit_pda(0, isidle) == 0) | 91 | if (x86_test_and_clear_bit_percpu(0, is_idle) == 0) |
85 | return; | 92 | return; |
86 | atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); | 93 | atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); |
87 | } | 94 | } |
@@ -111,6 +118,16 @@ static inline void play_dead(void) | |||
111 | void cpu_idle(void) | 118 | void cpu_idle(void) |
112 | { | 119 | { |
113 | current_thread_info()->status |= TS_POLLING; | 120 | current_thread_info()->status |= TS_POLLING; |
121 | |||
122 | /* | ||
123 | * If we're the non-boot CPU, nothing set the stack canary up | ||
124 | * for us. CPU0 already has it initialized but no harm in | ||
125 | * doing it again. This is a good place for updating it, as | ||
126 | * we wont ever return from this function (so the invalid | ||
127 | * canaries already on the stack wont ever trigger). | ||
128 | */ | ||
129 | boot_init_stack_canary(); | ||
130 | |||
114 | /* endless idle loop with no priority at all */ | 131 | /* endless idle loop with no priority at all */ |
115 | while (1) { | 132 | while (1) { |
116 | tick_nohz_stop_sched_tick(1); | 133 | tick_nohz_stop_sched_tick(1); |
@@ -151,14 +168,18 @@ void __show_regs(struct pt_regs *regs, int all) | |||
151 | unsigned long d0, d1, d2, d3, d6, d7; | 168 | unsigned long d0, d1, d2, d3, d6, d7; |
152 | unsigned int fsindex, gsindex; | 169 | unsigned int fsindex, gsindex; |
153 | unsigned int ds, cs, es; | 170 | unsigned int ds, cs, es; |
171 | const char *board; | ||
154 | 172 | ||
155 | printk("\n"); | 173 | printk("\n"); |
156 | print_modules(); | 174 | print_modules(); |
157 | printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n", | 175 | board = dmi_get_system_info(DMI_PRODUCT_NAME); |
176 | if (!board) | ||
177 | board = ""; | ||
178 | printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n", | ||
158 | current->pid, current->comm, print_tainted(), | 179 | current->pid, current->comm, print_tainted(), |
159 | init_utsname()->release, | 180 | init_utsname()->release, |
160 | (int)strcspn(init_utsname()->version, " "), | 181 | (int)strcspn(init_utsname()->version, " "), |
161 | init_utsname()->version); | 182 | init_utsname()->version, board); |
162 | printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); | 183 | printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); |
163 | printk_address(regs->ip, 1); | 184 | printk_address(regs->ip, 1); |
164 | printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, | 185 | printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, |
@@ -392,7 +413,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
392 | load_gs_index(0); | 413 | load_gs_index(0); |
393 | regs->ip = new_ip; | 414 | regs->ip = new_ip; |
394 | regs->sp = new_sp; | 415 | regs->sp = new_sp; |
395 | write_pda(oldrsp, new_sp); | 416 | percpu_write(old_rsp, new_sp); |
396 | regs->cs = __USER_CS; | 417 | regs->cs = __USER_CS; |
397 | regs->ss = __USER_DS; | 418 | regs->ss = __USER_DS; |
398 | regs->flags = 0x200; | 419 | regs->flags = 0x200; |
@@ -613,21 +634,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
613 | /* | 634 | /* |
614 | * Switch the PDA and FPU contexts. | 635 | * Switch the PDA and FPU contexts. |
615 | */ | 636 | */ |
616 | prev->usersp = read_pda(oldrsp); | 637 | prev->usersp = percpu_read(old_rsp); |
617 | write_pda(oldrsp, next->usersp); | 638 | percpu_write(old_rsp, next->usersp); |
618 | write_pda(pcurrent, next_p); | 639 | percpu_write(current_task, next_p); |
619 | 640 | ||
620 | write_pda(kernelstack, | 641 | percpu_write(kernel_stack, |
621 | (unsigned long)task_stack_page(next_p) + | 642 | (unsigned long)task_stack_page(next_p) + |
622 | THREAD_SIZE - PDA_STACKOFFSET); | 643 | THREAD_SIZE - KERNEL_STACK_OFFSET); |
623 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
624 | write_pda(stack_canary, next_p->stack_canary); | ||
625 | /* | ||
626 | * Build time only check to make sure the stack_canary is at | ||
627 | * offset 40 in the pda; this is a gcc ABI requirement | ||
628 | */ | ||
629 | BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); | ||
630 | #endif | ||
631 | 644 | ||
632 | /* | 645 | /* |
633 | * Now maybe reload the debug registers and handle I/O bitmaps | 646 | * Now maybe reload the debug registers and handle I/O bitmaps |