aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/enlighten.c57
-rw-r--r--arch/x86/xen/smp.c21
-rw-r--r--arch/x86/xen/spinlock.c25
-rw-r--r--arch/x86/xen/time.c13
4 files changed, 105 insertions, 11 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c8e1c7b95c3b..ddbd54a9b845 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -31,6 +31,7 @@
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/gfp.h> 32#include <linux/gfp.h>
33#include <linux/memblock.h> 33#include <linux/memblock.h>
34#include <linux/edd.h>
34 35
35#include <xen/xen.h> 36#include <xen/xen.h>
36#include <xen/events.h> 37#include <xen/events.h>
@@ -1306,6 +1307,55 @@ static const struct machine_ops xen_machine_ops __initconst = {
1306 .emergency_restart = xen_emergency_restart, 1307 .emergency_restart = xen_emergency_restart,
1307}; 1308};
1308 1309
1310static void __init xen_boot_params_init_edd(void)
1311{
1312#if IS_ENABLED(CONFIG_EDD)
1313 struct xen_platform_op op;
1314 struct edd_info *edd_info;
1315 u32 *mbr_signature;
1316 unsigned nr;
1317 int ret;
1318
1319 edd_info = boot_params.eddbuf;
1320 mbr_signature = boot_params.edd_mbr_sig_buffer;
1321
1322 op.cmd = XENPF_firmware_info;
1323
1324 op.u.firmware_info.type = XEN_FW_DISK_INFO;
1325 for (nr = 0; nr < EDDMAXNR; nr++) {
1326 struct edd_info *info = edd_info + nr;
1327
1328 op.u.firmware_info.index = nr;
1329 info->params.length = sizeof(info->params);
1330 set_xen_guest_handle(op.u.firmware_info.u.disk_info.edd_params,
1331 &info->params);
1332 ret = HYPERVISOR_dom0_op(&op);
1333 if (ret)
1334 break;
1335
1336#define C(x) info->x = op.u.firmware_info.u.disk_info.x
1337 C(device);
1338 C(version);
1339 C(interface_support);
1340 C(legacy_max_cylinder);
1341 C(legacy_max_head);
1342 C(legacy_sectors_per_track);
1343#undef C
1344 }
1345 boot_params.eddbuf_entries = nr;
1346
1347 op.u.firmware_info.type = XEN_FW_DISK_MBR_SIGNATURE;
1348 for (nr = 0; nr < EDD_MBR_SIG_MAX; nr++) {
1349 op.u.firmware_info.index = nr;
1350 ret = HYPERVISOR_dom0_op(&op);
1351 if (ret)
1352 break;
1353 mbr_signature[nr] = op.u.firmware_info.u.disk_mbr_signature.mbr_signature;
1354 }
1355 boot_params.edd_mbr_sig_buf_entries = nr;
1356#endif
1357}
1358
1309/* 1359/*
1310 * Set up the GDT and segment registers for -fstack-protector. Until 1360 * Set up the GDT and segment registers for -fstack-protector. Until
1311 * we do this, we have to be careful not to call any stack-protected 1361 * we do this, we have to be careful not to call any stack-protected
@@ -1508,6 +1558,8 @@ asmlinkage void __init xen_start_kernel(void)
1508 /* Avoid searching for BIOS MP tables */ 1558 /* Avoid searching for BIOS MP tables */
1509 x86_init.mpparse.find_smp_config = x86_init_noop; 1559 x86_init.mpparse.find_smp_config = x86_init_noop;
1510 x86_init.mpparse.get_smp_config = x86_init_uint_noop; 1560 x86_init.mpparse.get_smp_config = x86_init_uint_noop;
1561
1562 xen_boot_params_init_edd();
1511 } 1563 }
1512#ifdef CONFIG_PCI 1564#ifdef CONFIG_PCI
1513 /* PCI BIOS service won't work from a PV guest. */ 1565 /* PCI BIOS service won't work from a PV guest. */
@@ -1589,8 +1641,11 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
1589 switch (action) { 1641 switch (action) {
1590 case CPU_UP_PREPARE: 1642 case CPU_UP_PREPARE:
1591 xen_vcpu_setup(cpu); 1643 xen_vcpu_setup(cpu);
1592 if (xen_have_vector_callback) 1644 if (xen_have_vector_callback) {
1593 xen_init_lock_cpu(cpu); 1645 xen_init_lock_cpu(cpu);
1646 if (xen_feature(XENFEAT_hvm_safe_pvclock))
1647 xen_setup_timer(cpu);
1648 }
1594 break; 1649 break;
1595 default: 1650 default:
1596 break; 1651 break;
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 09ea61d2e02f..0d466d7c7175 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -144,6 +144,13 @@ static int xen_smp_intr_init(unsigned int cpu)
144 goto fail; 144 goto fail;
145 per_cpu(xen_callfuncsingle_irq, cpu) = rc; 145 per_cpu(xen_callfuncsingle_irq, cpu) = rc;
146 146
147 /*
148 * The IRQ worker on PVHVM goes through the native path and uses the
149 * IPI mechanism.
150 */
151 if (xen_hvm_domain())
152 return 0;
153
147 callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu); 154 callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
148 rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, 155 rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
149 cpu, 156 cpu,
@@ -167,6 +174,9 @@ static int xen_smp_intr_init(unsigned int cpu)
167 if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0) 174 if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
168 unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), 175 unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
169 NULL); 176 NULL);
177 if (xen_hvm_domain())
178 return rc;
179
170 if (per_cpu(xen_irq_work, cpu) >= 0) 180 if (per_cpu(xen_irq_work, cpu) >= 0)
171 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); 181 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
172 182
@@ -418,7 +428,7 @@ static int xen_cpu_disable(void)
418 428
419static void xen_cpu_die(unsigned int cpu) 429static void xen_cpu_die(unsigned int cpu)
420{ 430{
421 while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) { 431 while (xen_pv_domain() && HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
422 current->state = TASK_UNINTERRUPTIBLE; 432 current->state = TASK_UNINTERRUPTIBLE;
423 schedule_timeout(HZ/10); 433 schedule_timeout(HZ/10);
424 } 434 }
@@ -426,7 +436,8 @@ static void xen_cpu_die(unsigned int cpu)
426 unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); 436 unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
427 unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); 437 unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
428 unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL); 438 unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
429 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); 439 if (!xen_hvm_domain())
440 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
430 xen_uninit_lock_cpu(cpu); 441 xen_uninit_lock_cpu(cpu);
431 xen_teardown_timer(cpu); 442 xen_teardown_timer(cpu);
432} 443}
@@ -657,11 +668,7 @@ static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
657 668
658static void xen_hvm_cpu_die(unsigned int cpu) 669static void xen_hvm_cpu_die(unsigned int cpu)
659{ 670{
660 unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL); 671 xen_cpu_die(cpu);
661 unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
662 unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
663 unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
664 unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
665 native_cpu_die(cpu); 672 native_cpu_die(cpu);
666} 673}
667 674
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index f7a080ef0354..8b54603ce816 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -364,6 +364,16 @@ void __cpuinit xen_init_lock_cpu(int cpu)
364 int irq; 364 int irq;
365 const char *name; 365 const char *name;
366 366
367 WARN(per_cpu(lock_kicker_irq, cpu) > 0, "spinlock on CPU%d exists on IRQ%d!\n",
368 cpu, per_cpu(lock_kicker_irq, cpu));
369
370 /*
371 * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
372 * (xen: disable PV spinlocks on HVM)
373 */
374 if (xen_hvm_domain())
375 return;
376
367 name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); 377 name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
368 irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, 378 irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
369 cpu, 379 cpu,
@@ -382,11 +392,26 @@ void __cpuinit xen_init_lock_cpu(int cpu)
382 392
383void xen_uninit_lock_cpu(int cpu) 393void xen_uninit_lock_cpu(int cpu)
384{ 394{
395 /*
396 * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
397 * (xen: disable PV spinlocks on HVM)
398 */
399 if (xen_hvm_domain())
400 return;
401
385 unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); 402 unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL);
403 per_cpu(lock_kicker_irq, cpu) = -1;
386} 404}
387 405
388void __init xen_init_spinlocks(void) 406void __init xen_init_spinlocks(void)
389{ 407{
408 /*
409 * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
410 * (xen: disable PV spinlocks on HVM)
411 */
412 if (xen_hvm_domain())
413 return;
414
390 BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t)); 415 BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t));
391 416
392 pv_lock_ops.spin_is_locked = xen_spin_is_locked; 417 pv_lock_ops.spin_is_locked = xen_spin_is_locked;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 0296a9522501..3d88bfdf9e1c 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -377,7 +377,7 @@ static const struct clock_event_device xen_vcpuop_clockevent = {
377 377
378static const struct clock_event_device *xen_clockevent = 378static const struct clock_event_device *xen_clockevent =
379 &xen_timerop_clockevent; 379 &xen_timerop_clockevent;
380static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events); 380static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events) = { .irq = -1 };
381 381
382static irqreturn_t xen_timer_interrupt(int irq, void *dev_id) 382static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
383{ 383{
@@ -401,6 +401,9 @@ void xen_setup_timer(int cpu)
401 struct clock_event_device *evt; 401 struct clock_event_device *evt;
402 int irq; 402 int irq;
403 403
404 evt = &per_cpu(xen_clock_events, cpu);
405 WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu);
406
404 printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu); 407 printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);
405 408
406 name = kasprintf(GFP_KERNEL, "timer%d", cpu); 409 name = kasprintf(GFP_KERNEL, "timer%d", cpu);
@@ -413,7 +416,6 @@ void xen_setup_timer(int cpu)
413 IRQF_FORCE_RESUME, 416 IRQF_FORCE_RESUME,
414 name, NULL); 417 name, NULL);
415 418
416 evt = &per_cpu(xen_clock_events, cpu);
417 memcpy(evt, xen_clockevent, sizeof(*evt)); 419 memcpy(evt, xen_clockevent, sizeof(*evt));
418 420
419 evt->cpumask = cpumask_of(cpu); 421 evt->cpumask = cpumask_of(cpu);
@@ -426,6 +428,7 @@ void xen_teardown_timer(int cpu)
426 BUG_ON(cpu == 0); 428 BUG_ON(cpu == 0);
427 evt = &per_cpu(xen_clock_events, cpu); 429 evt = &per_cpu(xen_clock_events, cpu);
428 unbind_from_irqhandler(evt->irq, NULL); 430 unbind_from_irqhandler(evt->irq, NULL);
431 evt->irq = -1;
429} 432}
430 433
431void xen_setup_cpu_clockevents(void) 434void xen_setup_cpu_clockevents(void)
@@ -497,7 +500,11 @@ static void xen_hvm_setup_cpu_clockevents(void)
497{ 500{
498 int cpu = smp_processor_id(); 501 int cpu = smp_processor_id();
499 xen_setup_runstate_info(cpu); 502 xen_setup_runstate_info(cpu);
500 xen_setup_timer(cpu); 503 /*
504 * xen_setup_timer(cpu) - snprintf is bad in atomic context. Hence
505 * doing it xen_hvm_cpu_notify (which gets called by smp_init during
506 * early bootup and also during CPU hotplug events).
507 */
501 xen_setup_cpu_clockevents(); 508 xen_setup_cpu_clockevents();
502} 509}
503 510