diff options
-rw-r--r-- | arch/x86/pci/xen.c | 6 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 57 | ||||
-rw-r--r-- | arch/x86/xen/smp.c | 21 | ||||
-rw-r--r-- | arch/x86/xen/spinlock.c | 25 | ||||
-rw-r--r-- | arch/x86/xen/time.c | 13 | ||||
-rw-r--r-- | drivers/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/xen/events.c | 33 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-processor.c | 82 | ||||
-rw-r--r-- | include/xen/events.h | 3 |
9 files changed, 188 insertions, 54 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 94e76620460f..4a9be6ddf054 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -177,7 +177,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
177 | goto error; | 177 | goto error; |
178 | i = 0; | 178 | i = 0; |
179 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 179 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
180 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, | 180 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], |
181 | (type == PCI_CAP_ID_MSIX) ? | 181 | (type == PCI_CAP_ID_MSIX) ? |
182 | "pcifront-msi-x" : | 182 | "pcifront-msi-x" : |
183 | "pcifront-msi", | 183 | "pcifront-msi", |
@@ -244,7 +244,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
244 | dev_dbg(&dev->dev, | 244 | dev_dbg(&dev->dev, |
245 | "xen: msi already bound to pirq=%d\n", pirq); | 245 | "xen: msi already bound to pirq=%d\n", pirq); |
246 | } | 246 | } |
247 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, | 247 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, |
248 | (type == PCI_CAP_ID_MSIX) ? | 248 | (type == PCI_CAP_ID_MSIX) ? |
249 | "msi-x" : "msi", | 249 | "msi-x" : "msi", |
250 | DOMID_SELF); | 250 | DOMID_SELF); |
@@ -326,7 +326,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
326 | } | 326 | } |
327 | 327 | ||
328 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | 328 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, |
329 | map_irq.pirq, map_irq.index, | 329 | map_irq.pirq, |
330 | (type == PCI_CAP_ID_MSIX) ? | 330 | (type == PCI_CAP_ID_MSIX) ? |
331 | "msi-x" : "msi", | 331 | "msi-x" : "msi", |
332 | domid); | 332 | domid); |
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 | ||
1310 | static 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 | ||
419 | static void xen_cpu_die(unsigned int cpu) | 429 | static 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 | ||
658 | static void xen_hvm_cpu_die(unsigned int cpu) | 669 | static 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 | ||
383 | void xen_uninit_lock_cpu(int cpu) | 393 | void 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 | ||
388 | void __init xen_init_spinlocks(void) | 406 | void __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 | ||
378 | static const struct clock_event_device *xen_clockevent = | 378 | static const struct clock_event_device *xen_clockevent = |
379 | &xen_timerop_clockevent; | 379 | &xen_timerop_clockevent; |
380 | static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events); | 380 | static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events) = { .irq = -1 }; |
381 | 381 | ||
382 | static irqreturn_t xen_timer_interrupt(int irq, void *dev_id) | 382 | static 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 | ||
431 | void xen_setup_cpu_clockevents(void) | 434 | void 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 | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4c1546f71d56..09394657926e 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -2277,7 +2277,7 @@ config XEN_FBDEV_FRONTEND | |||
2277 | select FB_SYS_IMAGEBLIT | 2277 | select FB_SYS_IMAGEBLIT |
2278 | select FB_SYS_FOPS | 2278 | select FB_SYS_FOPS |
2279 | select FB_DEFERRED_IO | 2279 | select FB_DEFERRED_IO |
2280 | select INPUT_XEN_KBDDEV_FRONTEND | 2280 | select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC |
2281 | select XEN_XENBUS_FRONTEND | 2281 | select XEN_XENBUS_FRONTEND |
2282 | default y | 2282 | default y |
2283 | help | 2283 | help |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 2647ad8e1f19..d8cc8127f19c 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -85,8 +85,7 @@ enum xen_irq_type { | |||
85 | * event channel - irq->event channel mapping | 85 | * event channel - irq->event channel mapping |
86 | * cpu - cpu this event channel is bound to | 86 | * cpu - cpu this event channel is bound to |
87 | * index - type-specific information: | 87 | * index - type-specific information: |
88 | * PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM | 88 | * PIRQ - physical IRQ, GSI, flags, and owner domain |
89 | * guest, or GSI (real passthrough IRQ) of the device. | ||
90 | * VIRQ - virq number | 89 | * VIRQ - virq number |
91 | * IPI - IPI vector | 90 | * IPI - IPI vector |
92 | * EVTCHN - | 91 | * EVTCHN - |
@@ -105,7 +104,6 @@ struct irq_info { | |||
105 | struct { | 104 | struct { |
106 | unsigned short pirq; | 105 | unsigned short pirq; |
107 | unsigned short gsi; | 106 | unsigned short gsi; |
108 | unsigned char vector; | ||
109 | unsigned char flags; | 107 | unsigned char flags; |
110 | uint16_t domid; | 108 | uint16_t domid; |
111 | } pirq; | 109 | } pirq; |
@@ -211,7 +209,6 @@ static void xen_irq_info_pirq_init(unsigned irq, | |||
211 | unsigned short evtchn, | 209 | unsigned short evtchn, |
212 | unsigned short pirq, | 210 | unsigned short pirq, |
213 | unsigned short gsi, | 211 | unsigned short gsi, |
214 | unsigned short vector, | ||
215 | uint16_t domid, | 212 | uint16_t domid, |
216 | unsigned char flags) | 213 | unsigned char flags) |
217 | { | 214 | { |
@@ -221,7 +218,6 @@ static void xen_irq_info_pirq_init(unsigned irq, | |||
221 | 218 | ||
222 | info->u.pirq.pirq = pirq; | 219 | info->u.pirq.pirq = pirq; |
223 | info->u.pirq.gsi = gsi; | 220 | info->u.pirq.gsi = gsi; |
224 | info->u.pirq.vector = vector; | ||
225 | info->u.pirq.domid = domid; | 221 | info->u.pirq.domid = domid; |
226 | info->u.pirq.flags = flags; | 222 | info->u.pirq.flags = flags; |
227 | } | 223 | } |
@@ -519,6 +515,9 @@ static void xen_free_irq(unsigned irq) | |||
519 | { | 515 | { |
520 | struct irq_info *info = irq_get_handler_data(irq); | 516 | struct irq_info *info = irq_get_handler_data(irq); |
521 | 517 | ||
518 | if (WARN_ON(!info)) | ||
519 | return; | ||
520 | |||
522 | list_del(&info->list); | 521 | list_del(&info->list); |
523 | 522 | ||
524 | irq_set_handler_data(irq, NULL); | 523 | irq_set_handler_data(irq, NULL); |
@@ -714,7 +713,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
714 | goto out; | 713 | goto out; |
715 | } | 714 | } |
716 | 715 | ||
717 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF, | 716 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, DOMID_SELF, |
718 | shareable ? PIRQ_SHAREABLE : 0); | 717 | shareable ? PIRQ_SHAREABLE : 0); |
719 | 718 | ||
720 | pirq_query_unmask(irq); | 719 | pirq_query_unmask(irq); |
@@ -762,8 +761,7 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) | |||
762 | } | 761 | } |
763 | 762 | ||
764 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 763 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
765 | int pirq, int vector, const char *name, | 764 | int pirq, const char *name, domid_t domid) |
766 | domid_t domid) | ||
767 | { | 765 | { |
768 | int irq, ret; | 766 | int irq, ret; |
769 | 767 | ||
@@ -776,7 +774,7 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | |||
776 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, | 774 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, |
777 | name); | 775 | name); |
778 | 776 | ||
779 | xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0); | 777 | xen_irq_info_pirq_init(irq, 0, pirq, 0, domid, 0); |
780 | ret = irq_set_msi_desc(irq, msidesc); | 778 | ret = irq_set_msi_desc(irq, msidesc); |
781 | if (ret < 0) | 779 | if (ret < 0) |
782 | goto error_irq; | 780 | goto error_irq; |
@@ -1008,6 +1006,9 @@ static void unbind_from_irq(unsigned int irq) | |||
1008 | int evtchn = evtchn_from_irq(irq); | 1006 | int evtchn = evtchn_from_irq(irq); |
1009 | struct irq_info *info = irq_get_handler_data(irq); | 1007 | struct irq_info *info = irq_get_handler_data(irq); |
1010 | 1008 | ||
1009 | if (WARN_ON(!info)) | ||
1010 | return; | ||
1011 | |||
1011 | mutex_lock(&irq_mapping_update_lock); | 1012 | mutex_lock(&irq_mapping_update_lock); |
1012 | 1013 | ||
1013 | if (info->refcnt > 0) { | 1014 | if (info->refcnt > 0) { |
@@ -1135,6 +1136,10 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, | |||
1135 | 1136 | ||
1136 | void unbind_from_irqhandler(unsigned int irq, void *dev_id) | 1137 | void unbind_from_irqhandler(unsigned int irq, void *dev_id) |
1137 | { | 1138 | { |
1139 | struct irq_info *info = irq_get_handler_data(irq); | ||
1140 | |||
1141 | if (WARN_ON(!info)) | ||
1142 | return; | ||
1138 | free_irq(irq, dev_id); | 1143 | free_irq(irq, dev_id); |
1139 | unbind_from_irq(irq); | 1144 | unbind_from_irq(irq); |
1140 | } | 1145 | } |
@@ -1457,6 +1462,9 @@ void rebind_evtchn_irq(int evtchn, int irq) | |||
1457 | { | 1462 | { |
1458 | struct irq_info *info = info_for_irq(irq); | 1463 | struct irq_info *info = info_for_irq(irq); |
1459 | 1464 | ||
1465 | if (WARN_ON(!info)) | ||
1466 | return; | ||
1467 | |||
1460 | /* Make sure the irq is masked, since the new event channel | 1468 | /* Make sure the irq is masked, since the new event channel |
1461 | will also be masked. */ | 1469 | will also be masked. */ |
1462 | disable_irq(irq); | 1470 | disable_irq(irq); |
@@ -1730,7 +1738,12 @@ void xen_poll_irq(int irq) | |||
1730 | int xen_test_irq_shared(int irq) | 1738 | int xen_test_irq_shared(int irq) |
1731 | { | 1739 | { |
1732 | struct irq_info *info = info_for_irq(irq); | 1740 | struct irq_info *info = info_for_irq(irq); |
1733 | struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq }; | 1741 | struct physdev_irq_status_query irq_status; |
1742 | |||
1743 | if (WARN_ON(!info)) | ||
1744 | return -ENOENT; | ||
1745 | |||
1746 | irq_status.irq = info->u.pirq.pirq; | ||
1734 | 1747 | ||
1735 | if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status)) | 1748 | if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status)) |
1736 | return 0; | 1749 | return 0; |
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 90e34ac7e522..8abd7d579037 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/syscore_ops.h> | ||
28 | #include <acpi/acpi_bus.h> | 29 | #include <acpi/acpi_bus.h> |
29 | #include <acpi/acpi_drivers.h> | 30 | #include <acpi/acpi_drivers.h> |
30 | #include <acpi/processor.h> | 31 | #include <acpi/processor.h> |
@@ -51,9 +52,9 @@ static DEFINE_MUTEX(acpi_ids_mutex); | |||
51 | /* Which ACPI ID we have processed from 'struct acpi_processor'. */ | 52 | /* Which ACPI ID we have processed from 'struct acpi_processor'. */ |
52 | static unsigned long *acpi_ids_done; | 53 | static unsigned long *acpi_ids_done; |
53 | /* Which ACPI ID exist in the SSDT/DSDT processor definitions. */ | 54 | /* Which ACPI ID exist in the SSDT/DSDT processor definitions. */ |
54 | static unsigned long __initdata *acpi_id_present; | 55 | static unsigned long *acpi_id_present; |
55 | /* And if there is an _CST definition (or a PBLK) for the ACPI IDs */ | 56 | /* And if there is an _CST definition (or a PBLK) for the ACPI IDs */ |
56 | static unsigned long __initdata *acpi_id_cst_present; | 57 | static unsigned long *acpi_id_cst_present; |
57 | 58 | ||
58 | static int push_cxx_to_hypervisor(struct acpi_processor *_pr) | 59 | static int push_cxx_to_hypervisor(struct acpi_processor *_pr) |
59 | { | 60 | { |
@@ -329,7 +330,7 @@ static unsigned int __init get_max_acpi_id(void) | |||
329 | * for_each_[present|online]_cpu macros which are banded to the virtual | 330 | * for_each_[present|online]_cpu macros which are banded to the virtual |
330 | * CPU amount. | 331 | * CPU amount. |
331 | */ | 332 | */ |
332 | static acpi_status __init | 333 | static acpi_status |
333 | read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv) | 334 | read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv) |
334 | { | 335 | { |
335 | u32 acpi_id; | 336 | u32 acpi_id; |
@@ -384,12 +385,16 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
384 | 385 | ||
385 | return AE_OK; | 386 | return AE_OK; |
386 | } | 387 | } |
387 | static int __init check_acpi_ids(struct acpi_processor *pr_backup) | 388 | static int check_acpi_ids(struct acpi_processor *pr_backup) |
388 | { | 389 | { |
389 | 390 | ||
390 | if (!pr_backup) | 391 | if (!pr_backup) |
391 | return -ENODEV; | 392 | return -ENODEV; |
392 | 393 | ||
394 | if (acpi_id_present && acpi_id_cst_present) | ||
395 | /* OK, done this once .. skip to uploading */ | ||
396 | goto upload; | ||
397 | |||
393 | /* All online CPUs have been processed at this stage. Now verify | 398 | /* All online CPUs have been processed at this stage. Now verify |
394 | * whether in fact "online CPUs" == physical CPUs. | 399 | * whether in fact "online CPUs" == physical CPUs. |
395 | */ | 400 | */ |
@@ -408,6 +413,7 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup) | |||
408 | read_acpi_id, NULL, NULL, NULL); | 413 | read_acpi_id, NULL, NULL, NULL); |
409 | acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL); | 414 | acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL); |
410 | 415 | ||
416 | upload: | ||
411 | if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) { | 417 | if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) { |
412 | unsigned int i; | 418 | unsigned int i; |
413 | for_each_set_bit(i, acpi_id_present, nr_acpi_bits) { | 419 | for_each_set_bit(i, acpi_id_present, nr_acpi_bits) { |
@@ -417,10 +423,7 @@ static int __init check_acpi_ids(struct acpi_processor *pr_backup) | |||
417 | (void)upload_pm_data(pr_backup); | 423 | (void)upload_pm_data(pr_backup); |
418 | } | 424 | } |
419 | } | 425 | } |
420 | kfree(acpi_id_present); | 426 | |
421 | acpi_id_present = NULL; | ||
422 | kfree(acpi_id_cst_present); | ||
423 | acpi_id_cst_present = NULL; | ||
424 | return 0; | 427 | return 0; |
425 | } | 428 | } |
426 | static int __init check_prereq(void) | 429 | static int __init check_prereq(void) |
@@ -467,10 +470,47 @@ static void free_acpi_perf_data(void) | |||
467 | free_percpu(acpi_perf_data); | 470 | free_percpu(acpi_perf_data); |
468 | } | 471 | } |
469 | 472 | ||
470 | static int __init xen_acpi_processor_init(void) | 473 | static int xen_upload_processor_pm_data(void) |
471 | { | 474 | { |
472 | struct acpi_processor *pr_backup = NULL; | 475 | struct acpi_processor *pr_backup = NULL; |
473 | unsigned int i; | 476 | unsigned int i; |
477 | int rc = 0; | ||
478 | |||
479 | pr_info(DRV_NAME "Uploading Xen processor PM info\n"); | ||
480 | |||
481 | for_each_possible_cpu(i) { | ||
482 | struct acpi_processor *_pr; | ||
483 | _pr = per_cpu(processors, i /* APIC ID */); | ||
484 | if (!_pr) | ||
485 | continue; | ||
486 | |||
487 | if (!pr_backup) { | ||
488 | pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); | ||
489 | if (pr_backup) | ||
490 | memcpy(pr_backup, _pr, sizeof(struct acpi_processor)); | ||
491 | } | ||
492 | (void)upload_pm_data(_pr); | ||
493 | } | ||
494 | |||
495 | rc = check_acpi_ids(pr_backup); | ||
496 | kfree(pr_backup); | ||
497 | |||
498 | return rc; | ||
499 | } | ||
500 | |||
501 | static void xen_acpi_processor_resume(void) | ||
502 | { | ||
503 | bitmap_zero(acpi_ids_done, nr_acpi_bits); | ||
504 | xen_upload_processor_pm_data(); | ||
505 | } | ||
506 | |||
507 | static struct syscore_ops xap_syscore_ops = { | ||
508 | .resume = xen_acpi_processor_resume, | ||
509 | }; | ||
510 | |||
511 | static int __init xen_acpi_processor_init(void) | ||
512 | { | ||
513 | unsigned int i; | ||
474 | int rc = check_prereq(); | 514 | int rc = check_prereq(); |
475 | 515 | ||
476 | if (rc) | 516 | if (rc) |
@@ -514,27 +554,12 @@ static int __init xen_acpi_processor_init(void) | |||
514 | goto err_out; | 554 | goto err_out; |
515 | } | 555 | } |
516 | 556 | ||
517 | for_each_possible_cpu(i) { | 557 | rc = xen_upload_processor_pm_data(); |
518 | struct acpi_processor *_pr; | ||
519 | _pr = per_cpu(processors, i /* APIC ID */); | ||
520 | if (!_pr) | ||
521 | continue; | ||
522 | |||
523 | if (!pr_backup) { | ||
524 | pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); | ||
525 | if (pr_backup) | ||
526 | memcpy(pr_backup, _pr, sizeof(struct acpi_processor)); | ||
527 | } | ||
528 | (void)upload_pm_data(_pr); | ||
529 | } | ||
530 | rc = check_acpi_ids(pr_backup); | ||
531 | |||
532 | kfree(pr_backup); | ||
533 | pr_backup = NULL; | ||
534 | |||
535 | if (rc) | 558 | if (rc) |
536 | goto err_unregister; | 559 | goto err_unregister; |
537 | 560 | ||
561 | register_syscore_ops(&xap_syscore_ops); | ||
562 | |||
538 | return 0; | 563 | return 0; |
539 | err_unregister: | 564 | err_unregister: |
540 | for_each_possible_cpu(i) { | 565 | for_each_possible_cpu(i) { |
@@ -552,7 +577,10 @@ static void __exit xen_acpi_processor_exit(void) | |||
552 | { | 577 | { |
553 | int i; | 578 | int i; |
554 | 579 | ||
580 | unregister_syscore_ops(&xap_syscore_ops); | ||
555 | kfree(acpi_ids_done); | 581 | kfree(acpi_ids_done); |
582 | kfree(acpi_id_present); | ||
583 | kfree(acpi_id_cst_present); | ||
556 | for_each_possible_cpu(i) { | 584 | for_each_possible_cpu(i) { |
557 | struct acpi_processor_performance *perf; | 585 | struct acpi_processor_performance *perf; |
558 | perf = per_cpu_ptr(acpi_perf_data, i); | 586 | perf = per_cpu_ptr(acpi_perf_data, i); |
diff --git a/include/xen/events.h b/include/xen/events.h index c6bfe01acf6b..b2b27c6a0f7b 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
@@ -90,8 +90,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
90 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); | 90 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); |
91 | /* Bind an PSI pirq to an irq. */ | 91 | /* Bind an PSI pirq to an irq. */ |
92 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 92 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
93 | int pirq, int vector, const char *name, | 93 | int pirq, const char *name, domid_t domid); |
94 | domid_t domid); | ||
95 | #endif | 94 | #endif |
96 | 95 | ||
97 | /* De-allocates the above mentioned physical interrupt. */ | 96 | /* De-allocates the above mentioned physical interrupt. */ |