1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | #include <linux/thread_info.h> |
3 | #include <asm/smp.h> |
4 | |
5 | #include <xen/events.h> |
6 | |
7 | #include "xen-ops.h" |
8 | #include "smp.h" |
9 | |
10 | |
11 | static void __init xen_hvm_smp_prepare_boot_cpu(void) |
12 | { |
13 | BUG_ON(smp_processor_id() != 0); |
14 | native_smp_prepare_boot_cpu(); |
15 | |
16 | /* |
17 | * Setup vcpu_info for boot CPU. Secondary CPUs get their vcpu_info |
18 | * in xen_cpu_up_prepare_hvm(). |
19 | */ |
20 | xen_vcpu_setup(cpu: 0); |
21 | |
22 | /* |
23 | * Called again in case the kernel boots on vcpu >= MAX_VIRT_CPUS. |
24 | * Refer to comments in xen_hvm_init_time_ops(). |
25 | */ |
26 | xen_hvm_init_time_ops(); |
27 | |
28 | /* |
29 | * The alternative logic (which patches the unlock/lock) runs before |
30 | * the smp bootup up code is activated. Hence we need to set this up |
31 | * the core kernel is being patched. Otherwise we will have only |
32 | * modules patched but not core code. |
33 | */ |
34 | xen_init_spinlocks(); |
35 | } |
36 | |
37 | static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) |
38 | { |
39 | int cpu; |
40 | |
41 | native_smp_prepare_cpus(max_cpus); |
42 | |
43 | if (xen_have_vector_callback) { |
44 | WARN_ON(xen_smp_intr_init(0)); |
45 | xen_init_lock_cpu(cpu: 0); |
46 | } |
47 | |
48 | for_each_possible_cpu(cpu) { |
49 | if (cpu == 0) |
50 | continue; |
51 | |
52 | /* Set default vcpu_id to make sure that we don't use cpu-0's */ |
53 | per_cpu(xen_vcpu_id, cpu) = XEN_VCPU_ID_INVALID; |
54 | } |
55 | } |
56 | |
57 | #ifdef CONFIG_HOTPLUG_CPU |
58 | static void xen_hvm_cleanup_dead_cpu(unsigned int cpu) |
59 | { |
60 | if (xen_have_vector_callback) { |
61 | xen_smp_intr_free(cpu); |
62 | xen_uninit_lock_cpu(cpu); |
63 | xen_teardown_timer(cpu); |
64 | } |
65 | } |
66 | #else |
67 | static void xen_hvm_cleanup_dead_cpu(unsigned int cpu) |
68 | { |
69 | BUG(); |
70 | } |
71 | #endif |
72 | |
73 | void __init xen_hvm_smp_init(void) |
74 | { |
75 | smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu; |
76 | smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; |
77 | smp_ops.smp_cpus_done = xen_smp_cpus_done; |
78 | smp_ops.cleanup_dead_cpu = xen_hvm_cleanup_dead_cpu; |
79 | |
80 | if (!xen_have_vector_callback) { |
81 | #ifdef CONFIG_PARAVIRT_SPINLOCKS |
82 | nopvspin = true; |
83 | #endif |
84 | return; |
85 | } |
86 | |
87 | smp_ops.smp_send_reschedule = xen_smp_send_reschedule; |
88 | smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi; |
89 | smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi; |
90 | } |
91 |