diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/smp.c | 3 | ||||
-rw-r--r-- | arch/x86_64/kernel/time.c | 11 | ||||
-rw-r--r-- | arch/x86_64/kernel/vsyscall.c | 45 |
3 files changed, 26 insertions, 33 deletions
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 4f67697f5036..9f74c883568c 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c | |||
@@ -376,9 +376,8 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, | |||
376 | /* prevent preemption and reschedule on another processor */ | 376 | /* prevent preemption and reschedule on another processor */ |
377 | int me = get_cpu(); | 377 | int me = get_cpu(); |
378 | if (cpu == me) { | 378 | if (cpu == me) { |
379 | WARN_ON(1); | ||
380 | put_cpu(); | 379 | put_cpu(); |
381 | return -EBUSY; | 380 | return 0; |
382 | } | 381 | } |
383 | spin_lock_bh(&call_lock); | 382 | spin_lock_bh(&call_lock); |
384 | __smp_call_function_single(cpu, func, info, nonatomic, wait); | 383 | __smp_call_function_single(cpu, func, info, nonatomic, wait); |
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 88722f11ca13..e3ef544d2cfb 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c | |||
@@ -876,15 +876,6 @@ static struct irqaction irq0 = { | |||
876 | timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL | 876 | timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL |
877 | }; | 877 | }; |
878 | 878 | ||
879 | static int __cpuinit | ||
880 | time_cpu_notifier(struct notifier_block *nb, unsigned long action, void *hcpu) | ||
881 | { | ||
882 | unsigned cpu = (unsigned long) hcpu; | ||
883 | if (action == CPU_ONLINE) | ||
884 | vsyscall_set_cpu(cpu); | ||
885 | return NOTIFY_DONE; | ||
886 | } | ||
887 | |||
888 | void __init time_init(void) | 879 | void __init time_init(void) |
889 | { | 880 | { |
890 | if (nohpet) | 881 | if (nohpet) |
@@ -925,8 +916,6 @@ void __init time_init(void) | |||
925 | vxtime.last_tsc = get_cycles_sync(); | 916 | vxtime.last_tsc = get_cycles_sync(); |
926 | set_cyc2ns_scale(cpu_khz); | 917 | set_cyc2ns_scale(cpu_khz); |
927 | setup_irq(0, &irq0); | 918 | setup_irq(0, &irq0); |
928 | hotcpu_notifier(time_cpu_notifier, 0); | ||
929 | time_cpu_notifier(NULL, CPU_ONLINE, (void *)(long)smp_processor_id()); | ||
930 | 919 | ||
931 | #ifndef CONFIG_SMP | 920 | #ifndef CONFIG_SMP |
932 | time_init_gtod(); | 921 | time_init_gtod(); |
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index a98b460af6a1..a730bacecb0b 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/sysctl.h> | 28 | #include <linux/sysctl.h> |
29 | #include <linux/getcpu.h> | 29 | #include <linux/getcpu.h> |
30 | #include <linux/cpu.h> | ||
31 | #include <linux/smp.h> | ||
32 | #include <linux/notifier.h> | ||
30 | 33 | ||
31 | #include <asm/vsyscall.h> | 34 | #include <asm/vsyscall.h> |
32 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
@@ -243,32 +246,17 @@ static ctl_table kernel_root_table2[] = { | |||
243 | 246 | ||
244 | #endif | 247 | #endif |
245 | 248 | ||
246 | static void __cpuinit write_rdtscp_cb(void *info) | 249 | /* Assume __initcall executes before all user space. Hopefully kmod |
247 | { | 250 | doesn't violate that. We'll find out if it does. */ |
248 | write_rdtscp_aux((unsigned long)info); | 251 | static void __cpuinit vsyscall_set_cpu(int cpu) |
249 | } | ||
250 | |||
251 | void __cpuinit vsyscall_set_cpu(int cpu) | ||
252 | { | 252 | { |
253 | unsigned long *d; | 253 | unsigned long *d; |
254 | unsigned long node = 0; | 254 | unsigned long node = 0; |
255 | #ifdef CONFIG_NUMA | 255 | #ifdef CONFIG_NUMA |
256 | node = cpu_to_node[cpu]; | 256 | node = cpu_to_node[cpu]; |
257 | #endif | 257 | #endif |
258 | if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) { | 258 | if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) |
259 | void *info = (void *)((node << 12) | cpu); | 259 | write_rdtscp_aux((node << 12) | cpu); |
260 | /* Can happen on preemptive kernel */ | ||
261 | if (get_cpu() == cpu) | ||
262 | write_rdtscp_cb(info); | ||
263 | #ifdef CONFIG_SMP | ||
264 | else { | ||
265 | /* the notifier is unfortunately not executed on the | ||
266 | target CPU */ | ||
267 | smp_call_function_single(cpu,write_rdtscp_cb,info,0,1); | ||
268 | } | ||
269 | #endif | ||
270 | put_cpu(); | ||
271 | } | ||
272 | 260 | ||
273 | /* Store cpu number in limit so that it can be loaded quickly | 261 | /* Store cpu number in limit so that it can be loaded quickly |
274 | in user space in vgetcpu. | 262 | in user space in vgetcpu. |
@@ -280,6 +268,21 @@ void __cpuinit vsyscall_set_cpu(int cpu) | |||
280 | *d |= (node >> 4) << 48; | 268 | *d |= (node >> 4) << 48; |
281 | } | 269 | } |
282 | 270 | ||
271 | static void __cpuinit cpu_vsyscall_init(void *arg) | ||
272 | { | ||
273 | /* preemption should be already off */ | ||
274 | vsyscall_set_cpu(raw_smp_processor_id()); | ||
275 | } | ||
276 | |||
277 | static int __cpuinit | ||
278 | cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) | ||
279 | { | ||
280 | long cpu = (long)arg; | ||
281 | if (action == CPU_ONLINE) | ||
282 | smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1); | ||
283 | return NOTIFY_DONE; | ||
284 | } | ||
285 | |||
283 | static void __init map_vsyscall(void) | 286 | static void __init map_vsyscall(void) |
284 | { | 287 | { |
285 | extern char __vsyscall_0; | 288 | extern char __vsyscall_0; |
@@ -299,6 +302,8 @@ static int __init vsyscall_init(void) | |||
299 | #ifdef CONFIG_SYSCTL | 302 | #ifdef CONFIG_SYSCTL |
300 | register_sysctl_table(kernel_root_table2, 0); | 303 | register_sysctl_table(kernel_root_table2, 0); |
301 | #endif | 304 | #endif |
305 | on_each_cpu(cpu_vsyscall_init, NULL, 0, 1); | ||
306 | hotcpu_notifier(cpu_vsyscall_notifier, 0); | ||
302 | return 0; | 307 | return 0; |
303 | } | 308 | } |
304 | 309 | ||