]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/x86/xen/smp.c
xen/smp: Set the per-cpu IRQ number to a valid default.
[mirror_ubuntu-artful-kernel.git] / arch / x86 / xen / smp.c
1 /*
2 * Xen SMP support
3 *
4 * This file implements the Xen versions of smp_ops. SMP under Xen is
5 * very straightforward. Bringing a CPU up is simply a matter of
6 * loading its initial context and setting it running.
7 *
8 * IPIs are handled through the Xen event mechanism.
9 *
10 * Because virtual CPUs can be scheduled onto any real CPU, there's no
11 * useful topology information for the kernel to make use of. As a
12 * result, all CPUs are treated as if they're single-core and
13 * single-threaded.
14 */
15 #include <linux/sched.h>
16 #include <linux/err.h>
17 #include <linux/slab.h>
18 #include <linux/smp.h>
19 #include <linux/irq_work.h>
20
21 #include <asm/paravirt.h>
22 #include <asm/desc.h>
23 #include <asm/pgtable.h>
24 #include <asm/cpu.h>
25
26 #include <xen/interface/xen.h>
27 #include <xen/interface/vcpu.h>
28
29 #include <asm/xen/interface.h>
30 #include <asm/xen/hypercall.h>
31
32 #include <xen/xen.h>
33 #include <xen/page.h>
34 #include <xen/events.h>
35
36 #include <xen/hvc-console.h>
37 #include "xen-ops.h"
38 #include "mmu.h"
39
40 cpumask_var_t xen_cpu_initialized_map;
41
42 struct xen_common_irq {
43 int irq;
44 char *name;
45 };
46 static DEFINE_PER_CPU(struct xen_common_irq, xen_resched_irq) = { .irq = -1 };
47 static DEFINE_PER_CPU(struct xen_common_irq, xen_callfunc_irq) = { .irq = -1 };
48 static DEFINE_PER_CPU(struct xen_common_irq, xen_callfuncsingle_irq) = { .irq = -1 };
49 static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 };
50 static DEFINE_PER_CPU(struct xen_common_irq, xen_debug_irq) = { .irq = -1 };
51
52 static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
53 static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
54 static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id);
55
56 /*
57 * Reschedule call back.
58 */
59 static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
60 {
61 inc_irq_stat(irq_resched_count);
62 scheduler_ipi();
63
64 return IRQ_HANDLED;
65 }
66
67 static void __cpuinit cpu_bringup(void)
68 {
69 int cpu;
70
71 cpu_init();
72 touch_softlockup_watchdog();
73 preempt_disable();
74
75 xen_enable_sysenter();
76 xen_enable_syscall();
77
78 cpu = smp_processor_id();
79 smp_store_cpu_info(cpu);
80 cpu_data(cpu).x86_max_cores = 1;
81 set_cpu_sibling_map(cpu);
82
83 xen_setup_cpu_clockevents();
84
85 notify_cpu_starting(cpu);
86
87 set_cpu_online(cpu, true);
88
89 this_cpu_write(cpu_state, CPU_ONLINE);
90
91 wmb();
92
93 /* We can take interrupts now: we're officially "up". */
94 local_irq_enable();
95
96 wmb(); /* make sure everything is out */
97 }
98
99 static void __cpuinit cpu_bringup_and_idle(void)
100 {
101 cpu_bringup();
102 cpu_startup_entry(CPUHP_ONLINE);
103 }
104
105 static void xen_smp_intr_free(unsigned int cpu)
106 {
107 if (per_cpu(xen_resched_irq, cpu).irq >= 0) {
108 unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL);
109 per_cpu(xen_resched_irq, cpu).irq = -1;
110 }
111 if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) {
112 unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL);
113 per_cpu(xen_callfunc_irq, cpu).irq = -1;
114 }
115 if (per_cpu(xen_debug_irq, cpu).irq >= 0) {
116 unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL);
117 per_cpu(xen_debug_irq, cpu).irq = -1;
118 }
119 if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) {
120 unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq,
121 NULL);
122 per_cpu(xen_callfuncsingle_irq, cpu).irq = -1;
123 }
124 if (xen_hvm_domain())
125 return;
126
127 if (per_cpu(xen_irq_work, cpu).irq >= 0) {
128 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
129 per_cpu(xen_irq_work, cpu).irq = -1;
130 }
131 };
132 static int xen_smp_intr_init(unsigned int cpu)
133 {
134 int rc;
135 const char *resched_name, *callfunc_name, *debug_name;
136
137 resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
138 rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
139 cpu,
140 xen_reschedule_interrupt,
141 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
142 resched_name,
143 NULL);
144 if (rc < 0)
145 goto fail;
146 per_cpu(xen_resched_irq, cpu).irq = rc;
147
148 callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
149 rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
150 cpu,
151 xen_call_function_interrupt,
152 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
153 callfunc_name,
154 NULL);
155 if (rc < 0)
156 goto fail;
157 per_cpu(xen_callfunc_irq, cpu).irq = rc;
158
159 debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
160 rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
161 IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING,
162 debug_name, NULL);
163 if (rc < 0)
164 goto fail;
165 per_cpu(xen_debug_irq, cpu).irq = rc;
166
167 callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
168 rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
169 cpu,
170 xen_call_function_single_interrupt,
171 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
172 callfunc_name,
173 NULL);
174 if (rc < 0)
175 goto fail;
176 per_cpu(xen_callfuncsingle_irq, cpu).irq = rc;
177
178 /*
179 * The IRQ worker on PVHVM goes through the native path and uses the
180 * IPI mechanism.
181 */
182 if (xen_hvm_domain())
183 return 0;
184
185 callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
186 rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
187 cpu,
188 xen_irq_work_interrupt,
189 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
190 callfunc_name,
191 NULL);
192 if (rc < 0)
193 goto fail;
194 per_cpu(xen_irq_work, cpu).irq = rc;
195
196 return 0;
197
198 fail:
199 xen_smp_intr_free(cpu);
200 return rc;
201 }
202
203 static void __init xen_fill_possible_map(void)
204 {
205 int i, rc;
206
207 if (xen_initial_domain())
208 return;
209
210 for (i = 0; i < nr_cpu_ids; i++) {
211 rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
212 if (rc >= 0) {
213 num_processors++;
214 set_cpu_possible(i, true);
215 }
216 }
217 }
218
219 static void __init xen_filter_cpu_maps(void)
220 {
221 int i, rc;
222 unsigned int subtract = 0;
223
224 if (!xen_initial_domain())
225 return;
226
227 num_processors = 0;
228 disabled_cpus = 0;
229 for (i = 0; i < nr_cpu_ids; i++) {
230 rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
231 if (rc >= 0) {
232 num_processors++;
233 set_cpu_possible(i, true);
234 } else {
235 set_cpu_possible(i, false);
236 set_cpu_present(i, false);
237 subtract++;
238 }
239 }
240 #ifdef CONFIG_HOTPLUG_CPU
241 /* This is akin to using 'nr_cpus' on the Linux command line.
242 * Which is OK as when we use 'dom0_max_vcpus=X' we can only
243 * have up to X, while nr_cpu_ids is greater than X. This
244 * normally is not a problem, except when CPU hotplugging
245 * is involved and then there might be more than X CPUs
246 * in the guest - which will not work as there is no
247 * hypercall to expand the max number of VCPUs an already
248 * running guest has. So cap it up to X. */
249 if (subtract)
250 nr_cpu_ids = nr_cpu_ids - subtract;
251 #endif
252
253 }
254
255 static void __init xen_smp_prepare_boot_cpu(void)
256 {
257 BUG_ON(smp_processor_id() != 0);
258 native_smp_prepare_boot_cpu();
259
260 /* We've switched to the "real" per-cpu gdt, so make sure the
261 old memory can be recycled */
262 make_lowmem_page_readwrite(xen_initial_gdt);
263
264 xen_filter_cpu_maps();
265 xen_setup_vcpu_info_placement();
266 }
267
268 static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
269 {
270 unsigned cpu;
271 unsigned int i;
272
273 if (skip_ioapic_setup) {
274 char *m = (max_cpus == 0) ?
275 "The nosmp parameter is incompatible with Xen; " \
276 "use Xen dom0_max_vcpus=1 parameter" :
277 "The noapic parameter is incompatible with Xen";
278
279 xen_raw_printk(m);
280 panic(m);
281 }
282 xen_init_lock_cpu(0);
283
284 smp_store_boot_cpu_info();
285 cpu_data(0).x86_max_cores = 1;
286
287 for_each_possible_cpu(i) {
288 zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
289 zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
290 zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
291 }
292 set_cpu_sibling_map(0);
293
294 if (xen_smp_intr_init(0))
295 BUG();
296
297 if (!alloc_cpumask_var(&xen_cpu_initialized_map, GFP_KERNEL))
298 panic("could not allocate xen_cpu_initialized_map\n");
299
300 cpumask_copy(xen_cpu_initialized_map, cpumask_of(0));
301
302 /* Restrict the possible_map according to max_cpus. */
303 while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
304 for (cpu = nr_cpu_ids - 1; !cpu_possible(cpu); cpu--)
305 continue;
306 set_cpu_possible(cpu, false);
307 }
308
309 for_each_possible_cpu(cpu)
310 set_cpu_present(cpu, true);
311 }
312
313 static int __cpuinit
314 cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
315 {
316 struct vcpu_guest_context *ctxt;
317 struct desc_struct *gdt;
318 unsigned long gdt_mfn;
319
320 if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map))
321 return 0;
322
323 ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
324 if (ctxt == NULL)
325 return -ENOMEM;
326
327 gdt = get_cpu_gdt_table(cpu);
328
329 ctxt->flags = VGCF_IN_KERNEL;
330 ctxt->user_regs.ss = __KERNEL_DS;
331 #ifdef CONFIG_X86_32
332 ctxt->user_regs.fs = __KERNEL_PERCPU;
333 ctxt->user_regs.gs = __KERNEL_STACK_CANARY;
334 #else
335 ctxt->gs_base_kernel = per_cpu_offset(cpu);
336 #endif
337 ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
338
339 memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
340
341 {
342 ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
343 ctxt->user_regs.ds = __USER_DS;
344 ctxt->user_regs.es = __USER_DS;
345
346 xen_copy_trap_info(ctxt->trap_ctxt);
347
348 ctxt->ldt_ents = 0;
349
350 BUG_ON((unsigned long)gdt & ~PAGE_MASK);
351
352 gdt_mfn = arbitrary_virt_to_mfn(gdt);
353 make_lowmem_page_readonly(gdt);
354 make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
355
356 ctxt->gdt_frames[0] = gdt_mfn;
357 ctxt->gdt_ents = GDT_ENTRIES;
358
359 ctxt->kernel_ss = __KERNEL_DS;
360 ctxt->kernel_sp = idle->thread.sp0;
361
362 #ifdef CONFIG_X86_32
363 ctxt->event_callback_cs = __KERNEL_CS;
364 ctxt->failsafe_callback_cs = __KERNEL_CS;
365 #endif
366 ctxt->event_callback_eip =
367 (unsigned long)xen_hypervisor_callback;
368 ctxt->failsafe_callback_eip =
369 (unsigned long)xen_failsafe_callback;
370 }
371 ctxt->user_regs.cs = __KERNEL_CS;
372 ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
373
374 per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
375 ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
376
377 if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, ctxt))
378 BUG();
379
380 kfree(ctxt);
381 return 0;
382 }
383
384 static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle)
385 {
386 int rc;
387
388 per_cpu(current_task, cpu) = idle;
389 #ifdef CONFIG_X86_32
390 irq_ctx_init(cpu);
391 #else
392 clear_tsk_thread_flag(idle, TIF_FORK);
393 per_cpu(kernel_stack, cpu) =
394 (unsigned long)task_stack_page(idle) -
395 KERNEL_STACK_OFFSET + THREAD_SIZE;
396 #endif
397 xen_setup_runstate_info(cpu);
398 xen_setup_timer(cpu);
399 xen_init_lock_cpu(cpu);
400
401 per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
402
403 /* make sure interrupts start blocked */
404 per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
405
406 rc = cpu_initialize_context(cpu, idle);
407 if (rc)
408 return rc;
409
410 if (num_online_cpus() == 1)
411 /* Just in case we booted with a single CPU. */
412 alternatives_enable_smp();
413
414 rc = xen_smp_intr_init(cpu);
415 if (rc)
416 return rc;
417
418 rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
419 BUG_ON(rc);
420
421 while(per_cpu(cpu_state, cpu) != CPU_ONLINE) {
422 HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
423 barrier();
424 }
425
426 return 0;
427 }
428
429 static void xen_smp_cpus_done(unsigned int max_cpus)
430 {
431 }
432
433 #ifdef CONFIG_HOTPLUG_CPU
434 static int xen_cpu_disable(void)
435 {
436 unsigned int cpu = smp_processor_id();
437 if (cpu == 0)
438 return -EBUSY;
439
440 cpu_disable_common();
441
442 load_cr3(swapper_pg_dir);
443 return 0;
444 }
445
446 static void xen_cpu_die(unsigned int cpu)
447 {
448 while (xen_pv_domain() && HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
449 current->state = TASK_UNINTERRUPTIBLE;
450 schedule_timeout(HZ/10);
451 }
452 xen_smp_intr_free(cpu);
453 xen_uninit_lock_cpu(cpu);
454 xen_teardown_timer(cpu);
455 }
456
457 static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
458 {
459 play_dead_common();
460 HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
461 cpu_bringup();
462 }
463
464 #else /* !CONFIG_HOTPLUG_CPU */
465 static int xen_cpu_disable(void)
466 {
467 return -ENOSYS;
468 }
469
470 static void xen_cpu_die(unsigned int cpu)
471 {
472 BUG();
473 }
474
475 static void xen_play_dead(void)
476 {
477 BUG();
478 }
479
480 #endif
481 static void stop_self(void *v)
482 {
483 int cpu = smp_processor_id();
484
485 /* make sure we're not pinning something down */
486 load_cr3(swapper_pg_dir);
487 /* should set up a minimal gdt */
488
489 set_cpu_online(cpu, false);
490
491 HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL);
492 BUG();
493 }
494
495 static void xen_stop_other_cpus(int wait)
496 {
497 smp_call_function(stop_self, NULL, wait);
498 }
499
500 static void xen_smp_send_reschedule(int cpu)
501 {
502 xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
503 }
504
505 static void __xen_send_IPI_mask(const struct cpumask *mask,
506 int vector)
507 {
508 unsigned cpu;
509
510 for_each_cpu_and(cpu, mask, cpu_online_mask)
511 xen_send_IPI_one(cpu, vector);
512 }
513
514 static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
515 {
516 int cpu;
517
518 __xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
519
520 /* Make sure other vcpus get a chance to run if they need to. */
521 for_each_cpu(cpu, mask) {
522 if (xen_vcpu_stolen(cpu)) {
523 HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
524 break;
525 }
526 }
527 }
528
529 static void xen_smp_send_call_function_single_ipi(int cpu)
530 {
531 __xen_send_IPI_mask(cpumask_of(cpu),
532 XEN_CALL_FUNCTION_SINGLE_VECTOR);
533 }
534
535 static inline int xen_map_vector(int vector)
536 {
537 int xen_vector;
538
539 switch (vector) {
540 case RESCHEDULE_VECTOR:
541 xen_vector = XEN_RESCHEDULE_VECTOR;
542 break;
543 case CALL_FUNCTION_VECTOR:
544 xen_vector = XEN_CALL_FUNCTION_VECTOR;
545 break;
546 case CALL_FUNCTION_SINGLE_VECTOR:
547 xen_vector = XEN_CALL_FUNCTION_SINGLE_VECTOR;
548 break;
549 case IRQ_WORK_VECTOR:
550 xen_vector = XEN_IRQ_WORK_VECTOR;
551 break;
552 default:
553 xen_vector = -1;
554 printk(KERN_ERR "xen: vector 0x%x is not implemented\n",
555 vector);
556 }
557
558 return xen_vector;
559 }
560
561 void xen_send_IPI_mask(const struct cpumask *mask,
562 int vector)
563 {
564 int xen_vector = xen_map_vector(vector);
565
566 if (xen_vector >= 0)
567 __xen_send_IPI_mask(mask, xen_vector);
568 }
569
570 void xen_send_IPI_all(int vector)
571 {
572 int xen_vector = xen_map_vector(vector);
573
574 if (xen_vector >= 0)
575 __xen_send_IPI_mask(cpu_online_mask, xen_vector);
576 }
577
578 void xen_send_IPI_self(int vector)
579 {
580 int xen_vector = xen_map_vector(vector);
581
582 if (xen_vector >= 0)
583 xen_send_IPI_one(smp_processor_id(), xen_vector);
584 }
585
586 void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
587 int vector)
588 {
589 unsigned cpu;
590 unsigned int this_cpu = smp_processor_id();
591 int xen_vector = xen_map_vector(vector);
592
593 if (!(num_online_cpus() > 1) || (xen_vector < 0))
594 return;
595
596 for_each_cpu_and(cpu, mask, cpu_online_mask) {
597 if (this_cpu == cpu)
598 continue;
599
600 xen_send_IPI_one(cpu, xen_vector);
601 }
602 }
603
604 void xen_send_IPI_allbutself(int vector)
605 {
606 xen_send_IPI_mask_allbutself(cpu_online_mask, vector);
607 }
608
609 static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
610 {
611 irq_enter();
612 generic_smp_call_function_interrupt();
613 inc_irq_stat(irq_call_count);
614 irq_exit();
615
616 return IRQ_HANDLED;
617 }
618
619 static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id)
620 {
621 irq_enter();
622 generic_smp_call_function_single_interrupt();
623 inc_irq_stat(irq_call_count);
624 irq_exit();
625
626 return IRQ_HANDLED;
627 }
628
629 static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id)
630 {
631 irq_enter();
632 irq_work_run();
633 inc_irq_stat(apic_irq_work_irqs);
634 irq_exit();
635
636 return IRQ_HANDLED;
637 }
638
639 static const struct smp_ops xen_smp_ops __initconst = {
640 .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
641 .smp_prepare_cpus = xen_smp_prepare_cpus,
642 .smp_cpus_done = xen_smp_cpus_done,
643
644 .cpu_up = xen_cpu_up,
645 .cpu_die = xen_cpu_die,
646 .cpu_disable = xen_cpu_disable,
647 .play_dead = xen_play_dead,
648
649 .stop_other_cpus = xen_stop_other_cpus,
650 .smp_send_reschedule = xen_smp_send_reschedule,
651
652 .send_call_func_ipi = xen_smp_send_call_function_ipi,
653 .send_call_func_single_ipi = xen_smp_send_call_function_single_ipi,
654 };
655
656 void __init xen_smp_init(void)
657 {
658 smp_ops = xen_smp_ops;
659 xen_fill_possible_map();
660 xen_init_spinlocks();
661 }
662
663 static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
664 {
665 native_smp_prepare_cpus(max_cpus);
666 WARN_ON(xen_smp_intr_init(0));
667
668 xen_init_lock_cpu(0);
669 }
670
671 static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
672 {
673 int rc;
674 rc = native_cpu_up(cpu, tidle);
675 WARN_ON (xen_smp_intr_init(cpu));
676 return rc;
677 }
678
679 static void xen_hvm_cpu_die(unsigned int cpu)
680 {
681 xen_cpu_die(cpu);
682 native_cpu_die(cpu);
683 }
684
685 void __init xen_hvm_smp_init(void)
686 {
687 if (!xen_have_vector_callback)
688 return;
689 smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
690 smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
691 smp_ops.cpu_up = xen_hvm_cpu_up;
692 smp_ops.cpu_die = xen_hvm_cpu_die;
693 smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
694 smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
695 }