blob: 6a8f3b53ab8343d98bea81433d80de7399a63038 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +01002/*
3 * Xen SMP support
4 *
5 * This file implements the Xen versions of smp_ops. SMP under Xen is
6 * very straightforward. Bringing a CPU up is simply a matter of
7 * loading its initial context and setting it running.
8 *
9 * IPIs are handled through the Xen event mechanism.
10 *
11 * Because virtual CPUs can be scheduled onto any real CPU, there's no
12 * useful topology information for the kernel to make use of. As a
13 * result, all CPUs are treated as if they're single-core and
14 * single-threaded.
15 */
16#include <linux/sched.h>
Andy Lutomirskif16b3da2017-11-02 00:59:12 -070017#include <linux/sched/task_stack.h>
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010018#include <linux/err.h>
19#include <linux/slab.h>
20#include <linux/smp.h>
21#include <linux/irq_work.h>
22#include <linux/tick.h>
23#include <linux/nmi.h>
Juergen Grossc185dde2017-07-05 16:05:20 +020024#include <linux/cpuhotplug.h>
Christophe Leroy977e4be2018-10-20 09:26:49 +020025#include <linux/stackprotector.h>
Mike Rapoport65fddcf2020-06-08 21:32:42 -070026#include <linux/pgtable.h>
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010027
28#include <asm/paravirt.h>
Thomas Gleixner2f6474e2020-05-21 22:05:26 +020029#include <asm/idtentry.h>
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010030#include <asm/desc.h>
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010031#include <asm/cpu.h>
Ingo Molnar13c01132020-08-06 14:34:32 +020032#include <asm/io_apic.h>
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010033
34#include <xen/interface/xen.h>
35#include <xen/interface/vcpu.h>
36#include <xen/interface/xenpmu.h>
37
Juergen Gross74899d92018-06-21 10:43:31 +020038#include <asm/spec-ctrl.h>
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010039#include <asm/xen/interface.h>
40#include <asm/xen/hypercall.h>
41
42#include <xen/xen.h>
43#include <xen/page.h>
44#include <xen/events.h>
45
46#include <xen/hvc-console.h>
47#include "xen-ops.h"
48#include "mmu.h"
49#include "smp.h"
50#include "pmu.h"
51
52cpumask_var_t xen_cpu_initialized_map;
53
54static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 };
55static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .irq = -1 };
56
57static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id);
Miroslav Benesc3881eb2020-03-26 10:26:03 +010058void asm_cpu_bringup_and_idle(void);
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010059
60static void cpu_bringup(void)
61{
62 int cpu;
63
Thomas Gleixner7652ac92019-07-10 21:42:46 +020064 cr4_init();
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010065 cpu_init();
66 touch_softlockup_watchdog();
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010067
68 /* PVH runs in ring 0 and allows us to do native syscalls. Yay! */
69 if (!xen_feature(XENFEAT_supervisor_mode_kernel)) {
70 xen_enable_sysenter();
71 xen_enable_syscall();
72 }
73 cpu = smp_processor_id();
74 smp_store_cpu_info(cpu);
75 cpu_data(cpu).x86_max_cores = 1;
76 set_cpu_sibling_map(cpu);
77
Juergen Gross74899d92018-06-21 10:43:31 +020078 speculative_store_bypass_ht_init();
79
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +010080 xen_setup_cpu_clockevents();
81
82 notify_cpu_starting(cpu);
83
84 set_cpu_online(cpu, true);
85
86 cpu_set_state_online(cpu); /* Implies full memory barrier. */
87
88 /* We can take interrupts now: we're officially "up". */
89 local_irq_enable();
90}
91
92asmlinkage __visible void cpu_bringup_and_idle(void)
93{
94 cpu_bringup();
95 cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
96}
97
98void xen_smp_intr_free_pv(unsigned int cpu)
99{
100 if (per_cpu(xen_irq_work, cpu).irq >= 0) {
101 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
102 per_cpu(xen_irq_work, cpu).irq = -1;
103 kfree(per_cpu(xen_irq_work, cpu).name);
104 per_cpu(xen_irq_work, cpu).name = NULL;
105 }
106
107 if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
108 unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
109 per_cpu(xen_pmu_irq, cpu).irq = -1;
110 kfree(per_cpu(xen_pmu_irq, cpu).name);
111 per_cpu(xen_pmu_irq, cpu).name = NULL;
112 }
113}
114
115int xen_smp_intr_init_pv(unsigned int cpu)
116{
117 int rc;
118 char *callfunc_name, *pmu_name;
119
120 callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
121 rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
122 cpu,
123 xen_irq_work_interrupt,
124 IRQF_PERCPU|IRQF_NOBALANCING,
125 callfunc_name,
126 NULL);
127 if (rc < 0)
128 goto fail;
129 per_cpu(xen_irq_work, cpu).irq = rc;
130 per_cpu(xen_irq_work, cpu).name = callfunc_name;
131
132 if (is_xen_pmu(cpu)) {
133 pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
134 rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
135 xen_pmu_irq_handler,
136 IRQF_PERCPU|IRQF_NOBALANCING,
137 pmu_name, NULL);
138 if (rc < 0)
139 goto fail;
140 per_cpu(xen_pmu_irq, cpu).irq = rc;
141 per_cpu(xen_pmu_irq, cpu).name = pmu_name;
142 }
143
144 return 0;
145
146 fail:
147 xen_smp_intr_free_pv(cpu);
148 return rc;
149}
150
151static void __init xen_fill_possible_map(void)
152{
153 int i, rc;
154
155 if (xen_initial_domain())
156 return;
157
158 for (i = 0; i < nr_cpu_ids; i++) {
159 rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
160 if (rc >= 0) {
161 num_processors++;
162 set_cpu_possible(i, true);
163 }
164 }
165}
166
167static void __init xen_filter_cpu_maps(void)
168{
169 int i, rc;
170 unsigned int subtract = 0;
171
172 if (!xen_initial_domain())
173 return;
174
175 num_processors = 0;
176 disabled_cpus = 0;
177 for (i = 0; i < nr_cpu_ids; i++) {
178 rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
179 if (rc >= 0) {
180 num_processors++;
181 set_cpu_possible(i, true);
182 } else {
183 set_cpu_possible(i, false);
184 set_cpu_present(i, false);
185 subtract++;
186 }
187 }
188#ifdef CONFIG_HOTPLUG_CPU
189 /* This is akin to using 'nr_cpus' on the Linux command line.
190 * Which is OK as when we use 'dom0_max_vcpus=X' we can only
191 * have up to X, while nr_cpu_ids is greater than X. This
192 * normally is not a problem, except when CPU hotplugging
193 * is involved and then there might be more than X CPUs
194 * in the guest - which will not work as there is no
195 * hypercall to expand the max number of VCPUs an already
196 * running guest has. So cap it up to X. */
197 if (subtract)
198 nr_cpu_ids = nr_cpu_ids - subtract;
199#endif
200
201}
202
203static void __init xen_pv_smp_prepare_boot_cpu(void)
204{
205 BUG_ON(smp_processor_id() != 0);
206 native_smp_prepare_boot_cpu();
207
208 if (!xen_feature(XENFEAT_writable_page_tables))
209 /* We've switched to the "real" per-cpu gdt, so make
210 * sure the old memory can be recycled. */
211 make_lowmem_page_readwrite(xen_initial_gdt);
212
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100213 xen_filter_cpu_maps();
214 xen_setup_vcpu_info_placement();
215
216 /*
217 * The alternative logic (which patches the unlock/lock) runs before
218 * the smp bootup up code is activated. Hence we need to set this up
219 * the core kernel is being patched. Otherwise we will have only
220 * modules patched but not core code.
221 */
222 xen_init_spinlocks();
223}
224
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100225static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus)
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100226{
227 unsigned cpu;
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100228
229 if (skip_ioapic_setup) {
230 char *m = (max_cpus == 0) ?
231 "The nosmp parameter is incompatible with Xen; " \
232 "use Xen dom0_max_vcpus=1 parameter" :
233 "The noapic parameter is incompatible with Xen";
234
235 xen_raw_printk(m);
236 panic(m);
237 }
238 xen_init_lock_cpu(0);
239
Boris Ostrovskyce2612b2021-11-02 19:36:36 -0400240 smp_prepare_cpus_common();
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100241
Boris Ostrovskyce2612b2021-11-02 19:36:36 -0400242 cpu_data(0).x86_max_cores = 1;
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100243
Juergen Gross74899d92018-06-21 10:43:31 +0200244 speculative_store_bypass_ht_init();
245
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100246 xen_pmu_init(0);
247
Boris Ostrovskyf31b9692017-04-26 09:42:48 -0400248 if (xen_smp_intr_init(0) || xen_smp_intr_init_pv(0))
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100249 BUG();
250
251 if (!alloc_cpumask_var(&xen_cpu_initialized_map, GFP_KERNEL))
252 panic("could not allocate xen_cpu_initialized_map\n");
253
254 cpumask_copy(xen_cpu_initialized_map, cpumask_of(0));
255
256 /* Restrict the possible_map according to max_cpus. */
257 while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
258 for (cpu = nr_cpu_ids - 1; !cpu_possible(cpu); cpu--)
259 continue;
260 set_cpu_possible(cpu, false);
261 }
262
263 for_each_possible_cpu(cpu)
264 set_cpu_present(cpu, true);
265}
266
267static int
268cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
269{
270 struct vcpu_guest_context *ctxt;
271 struct desc_struct *gdt;
272 unsigned long gdt_mfn;
273
274 /* used to tell cpu_init() that it can proceed with initialization */
275 cpumask_set_cpu(cpu, cpu_callout_mask);
276 if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map))
277 return 0;
278
279 ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
280 if (ctxt == NULL)
281 return -ENOMEM;
282
283 gdt = get_cpu_gdt_rw(cpu);
284
Andy Lutomirskif16b3da2017-11-02 00:59:12 -0700285 /*
286 * Bring up the CPU in cpu_bringup_and_idle() with the stack
287 * pointing just below where pt_regs would be if it were a normal
288 * kernel entry.
289 */
Miroslav Benesc3881eb2020-03-26 10:26:03 +0100290 ctxt->user_regs.eip = (unsigned long)asm_cpu_bringup_and_idle;
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100291 ctxt->flags = VGCF_IN_KERNEL;
292 ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
293 ctxt->user_regs.ds = __USER_DS;
294 ctxt->user_regs.es = __USER_DS;
295 ctxt->user_regs.ss = __KERNEL_DS;
Andy Lutomirskif16b3da2017-11-02 00:59:12 -0700296 ctxt->user_regs.cs = __KERNEL_CS;
297 ctxt->user_regs.esp = (unsigned long)task_pt_regs(idle);
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100298
299 xen_copy_trap_info(ctxt->trap_ctxt);
300
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100301 BUG_ON((unsigned long)gdt & ~PAGE_MASK);
302
303 gdt_mfn = arbitrary_virt_to_mfn(gdt);
304 make_lowmem_page_readonly(gdt);
305 make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
306
307 ctxt->gdt_frames[0] = gdt_mfn;
308 ctxt->gdt_ents = GDT_ENTRIES;
309
Andy Lutomirskif16b3da2017-11-02 00:59:12 -0700310 /*
311 * Set SS:SP that Xen will use when entering guest kernel mode
312 * from guest user mode. Subsequent calls to load_sp0() can
313 * change this value.
314 */
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100315 ctxt->kernel_ss = __KERNEL_DS;
Andy Lutomirskif16b3da2017-11-02 00:59:12 -0700316 ctxt->kernel_sp = task_top_of_stack(idle);
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100317
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100318 ctxt->gs_base_kernel = per_cpu_offset(cpu);
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100319 ctxt->event_callback_eip =
Thomas Gleixner2f6474e2020-05-21 22:05:26 +0200320 (unsigned long)xen_asm_exc_xen_hypervisor_callback;
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100321 ctxt->failsafe_callback_eip =
322 (unsigned long)xen_failsafe_callback;
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100323 per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
324
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100325 ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_gfn(swapper_pg_dir));
326 if (HYPERVISOR_vcpu_op(VCPUOP_initialise, xen_vcpu_nr(cpu), ctxt))
327 BUG();
328
329 kfree(ctxt);
330 return 0;
331}
332
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100333static int xen_pv_cpu_up(unsigned int cpu, struct task_struct *idle)
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100334{
335 int rc;
336
Thomas Gleixner66c7ceb2019-04-14 18:00:04 +0200337 rc = common_cpu_up(cpu, idle);
338 if (rc)
339 return rc;
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100340
341 xen_setup_runstate_info(cpu);
342
343 /*
344 * PV VCPUs are always successfully taken down (see 'while' loop
345 * in xen_cpu_die()), so -EBUSY is an error.
346 */
347 rc = cpu_check_up_prepare(cpu);
348 if (rc)
349 return rc;
350
351 /* make sure interrupts start blocked */
352 per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
353
354 rc = cpu_initialize_context(cpu, idle);
355 if (rc)
356 return rc;
357
358 xen_pmu_init(cpu);
359
360 rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL);
361 BUG_ON(rc);
362
363 while (cpu_report_state(cpu) != CPU_ONLINE)
364 HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
365
366 return 0;
367}
368
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100369#ifdef CONFIG_HOTPLUG_CPU
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100370static int xen_pv_cpu_disable(void)
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100371{
372 unsigned int cpu = smp_processor_id();
373 if (cpu == 0)
374 return -EBUSY;
375
376 cpu_disable_common();
377
378 load_cr3(swapper_pg_dir);
379 return 0;
380}
381
382static void xen_pv_cpu_die(unsigned int cpu)
383{
384 while (HYPERVISOR_vcpu_op(VCPUOP_is_up,
385 xen_vcpu_nr(cpu), NULL)) {
386 __set_current_state(TASK_UNINTERRUPTIBLE);
387 schedule_timeout(HZ/10);
388 }
389
390 if (common_cpu_die(cpu) == 0) {
391 xen_smp_intr_free(cpu);
392 xen_uninit_lock_cpu(cpu);
393 xen_teardown_timer(cpu);
394 xen_pmu_finish(cpu);
395 }
396}
397
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100398static void xen_pv_play_dead(void) /* used only with HOTPLUG_CPU */
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100399{
400 play_dead_common();
401 HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(smp_processor_id()), NULL);
402 cpu_bringup();
403 /*
404 * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down)
405 * clears certain data that the cpu_idle loop (which called us
406 * and that we return from) expects. The only way to get that
407 * data back is to call:
408 */
409 tick_nohz_idle_enter();
Rafael J. Wysocki0e776762018-04-05 18:58:27 +0200410 tick_nohz_idle_stop_tick_protected();
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100411
Juergen Grossc185dde2017-07-05 16:05:20 +0200412 cpuhp_online_idle(CPUHP_AP_ONLINE_IDLE);
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100413}
414
415#else /* !CONFIG_HOTPLUG_CPU */
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100416static int xen_pv_cpu_disable(void)
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100417{
418 return -ENOSYS;
419}
420
421static void xen_pv_cpu_die(unsigned int cpu)
422{
423 BUG();
424}
425
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100426static void xen_pv_play_dead(void)
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100427{
428 BUG();
429}
430
431#endif
432static void stop_self(void *v)
433{
434 int cpu = smp_processor_id();
435
436 /* make sure we're not pinning something down */
437 load_cr3(swapper_pg_dir);
438 /* should set up a minimal gdt */
439
440 set_cpu_online(cpu, false);
441
442 HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL);
443 BUG();
444}
445
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100446static void xen_pv_stop_other_cpus(int wait)
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100447{
448 smp_call_function(stop_self, NULL, wait);
449}
450
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100451static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id)
452{
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100453 irq_work_run();
454 inc_irq_stat(apic_irq_work_irqs);
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100455
456 return IRQ_HANDLED;
457}
458
459static const struct smp_ops xen_smp_ops __initconst = {
460 .smp_prepare_boot_cpu = xen_pv_smp_prepare_boot_cpu,
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100461 .smp_prepare_cpus = xen_pv_smp_prepare_cpus,
Ankur Aroraae039002017-06-02 17:06:02 -0700462 .smp_cpus_done = xen_smp_cpus_done,
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100463
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100464 .cpu_up = xen_pv_cpu_up,
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100465 .cpu_die = xen_pv_cpu_die,
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100466 .cpu_disable = xen_pv_cpu_disable,
467 .play_dead = xen_pv_play_dead,
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100468
Vitaly Kuznetsov8cb6de32017-03-14 18:35:56 +0100469 .stop_other_cpus = xen_pv_stop_other_cpus,
Vitaly Kuznetsov83b96792017-03-14 18:35:46 +0100470 .smp_send_reschedule = xen_smp_send_reschedule,
471
472 .send_call_func_ipi = xen_smp_send_call_function_ipi,
473 .send_call_func_single_ipi = xen_smp_send_call_function_single_ipi,
474};
475
476void __init xen_smp_init(void)
477{
478 smp_ops = xen_smp_ops;
479 xen_fill_possible_map();
480}