aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarimAllah Ahmed <karahmed@amazon.de>2016-08-26 17:55:36 -0400
committerDavid Vrabel <david.vrabel@citrix.com>2016-09-30 06:44:34 -0400
commit72a9b186292d98494f222226cfd24a1621796209 (patch)
tree62bf7896b9e9971a4106adf28dd22b8f3cba4c24
parentc8761e2016aa51a2829563b02a0a55913bdb0be8 (diff)
xen: Remove event channel notification through Xen PCI platform device
Ever since commit 254d1a3f02eb ("xen/pv-on-hvm kexec: shutdown watches from old kernel") using the INTx interrupt from Xen PCI platform device for event channel notification would just lockup the guest during bootup. postcore_initcall now calls xs_reset_watches which will eventually try to read a value from XenStore and will get stuck on read_reply at XenBus forever since the platform driver is not probed yet and its INTx interrupt handler is not registered yet. That means that the guest can not be notified at this moment of any pending event channels and none of the per-event handlers will ever be invoked (including the XenStore one) and the reply will never be picked up by the kernel. The exact stack where things get stuck during xenbus_init: -xenbus_init -xs_init -xs_reset_watches -xenbus_scanf -xenbus_read -xs_single -xs_single -xs_talkv Vector callbacks have always been the favourite event notification mechanism since their introduction in commit 38e20b07efd5 ("x86/xen: event channels delivery on HVM.") and the vector callback feature has always been advertised for quite some time by Xen that's why INTx was broken for several years now without impacting anyone. Luckily this also means that event channel notification through INTx is basically dead-code which can be safely removed without impacting anybody since it has been effectively disabled for more than 4 years with nobody complaining about it (at least as far as I'm aware of). This commit removes event channel notification through Xen PCI platform device. Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Juergen Gross <jgross@suse.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: x86@kernel.org Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Cc: Julien Grall <julien.grall@citrix.com> Cc: Vitaly Kuznetsov <vkuznets@redhat.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Ross Lagerwall <ross.lagerwall@citrix.com> Cc: xen-devel@lists.xenproject.org Cc: linux-kernel@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: Anthony Liguori <aliguori@amazon.com> Signed-off-by: KarimAllah Ahmed <karahmed@amazon.de> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
-rw-r--r--arch/x86/include/asm/xen/events.h11
-rw-r--r--arch/x86/pci/xen.c2
-rw-r--r--arch/x86/xen/enlighten.c21
-rw-r--r--arch/x86/xen/smp.c2
-rw-r--r--arch/x86/xen/time.c5
-rw-r--r--drivers/xen/events/events_base.c26
-rw-r--r--drivers/xen/platform-pci.c64
-rw-r--r--include/xen/xen.h3
8 files changed, 17 insertions, 117 deletions
diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h
index e6911caf5bbf..608a79d5a466 100644
--- a/arch/x86/include/asm/xen/events.h
+++ b/arch/x86/include/asm/xen/events.h
@@ -20,15 +20,4 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
20/* No need for a barrier -- XCHG is a barrier on x86. */ 20/* No need for a barrier -- XCHG is a barrier on x86. */
21#define xchg_xen_ulong(ptr, val) xchg((ptr), (val)) 21#define xchg_xen_ulong(ptr, val) xchg((ptr), (val))
22 22
23extern int xen_have_vector_callback;
24
25/*
26 * Events delivered via platform PCI interrupts are always
27 * routed to vcpu 0 and hence cannot be rebound.
28 */
29static inline bool xen_support_evtchn_rebind(void)
30{
31 return (!xen_hvm_domain() || xen_have_vector_callback);
32}
33
34#endif /* _ASM_X86_XEN_EVENTS_H */ 23#endif /* _ASM_X86_XEN_EVENTS_H */
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 3a483cb5ac81..bedfab98077a 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -456,7 +456,7 @@ void __init xen_msi_init(void)
456 456
457int __init pci_xen_hvm_init(void) 457int __init pci_xen_hvm_init(void)
458{ 458{
459 if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) 459 if (!xen_feature(XENFEAT_hvm_pirqs))
460 return 0; 460 return 0;
461 461
462#ifdef CONFIG_ACPI 462#ifdef CONFIG_ACPI
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index a9ba14ac3aea..366b6aed4a8e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -137,8 +137,6 @@ struct shared_info xen_dummy_shared_info;
137void *xen_initial_gdt; 137void *xen_initial_gdt;
138 138
139RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); 139RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
140__read_mostly int xen_have_vector_callback;
141EXPORT_SYMBOL_GPL(xen_have_vector_callback);
142 140
143static int xen_cpu_up_prepare(unsigned int cpu); 141static int xen_cpu_up_prepare(unsigned int cpu);
144static int xen_cpu_up_online(unsigned int cpu); 142static int xen_cpu_up_online(unsigned int cpu);
@@ -1524,10 +1522,7 @@ static void __init xen_pvh_early_guest_init(void)
1524 if (!xen_feature(XENFEAT_auto_translated_physmap)) 1522 if (!xen_feature(XENFEAT_auto_translated_physmap))
1525 return; 1523 return;
1526 1524
1527 if (!xen_feature(XENFEAT_hvm_callback_vector)) 1525 BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
1528 return;
1529
1530 xen_have_vector_callback = 1;
1531 1526
1532 xen_pvh_early_cpu_init(0, false); 1527 xen_pvh_early_cpu_init(0, false);
1533 xen_pvh_set_cr_flags(0); 1528 xen_pvh_set_cr_flags(0);
@@ -1864,9 +1859,7 @@ static int xen_cpu_up_prepare(unsigned int cpu)
1864 xen_vcpu_setup(cpu); 1859 xen_vcpu_setup(cpu);
1865 } 1860 }
1866 1861
1867 if (xen_pv_domain() || 1862 if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
1868 (xen_have_vector_callback &&
1869 xen_feature(XENFEAT_hvm_safe_pvclock)))
1870 xen_setup_timer(cpu); 1863 xen_setup_timer(cpu);
1871 1864
1872 rc = xen_smp_intr_init(cpu); 1865 rc = xen_smp_intr_init(cpu);
@@ -1882,9 +1875,7 @@ static int xen_cpu_dead(unsigned int cpu)
1882{ 1875{
1883 xen_smp_intr_free(cpu); 1876 xen_smp_intr_free(cpu);
1884 1877
1885 if (xen_pv_domain() || 1878 if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
1886 (xen_have_vector_callback &&
1887 xen_feature(XENFEAT_hvm_safe_pvclock)))
1888 xen_teardown_timer(cpu); 1879 xen_teardown_timer(cpu);
1889 1880
1890 return 0; 1881 return 0;
@@ -1922,8 +1913,8 @@ static void __init xen_hvm_guest_init(void)
1922 1913
1923 xen_panic_handler_init(); 1914 xen_panic_handler_init();
1924 1915
1925 if (xen_feature(XENFEAT_hvm_callback_vector)) 1916 BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
1926 xen_have_vector_callback = 1; 1917
1927 xen_hvm_smp_init(); 1918 xen_hvm_smp_init();
1928 WARN_ON(xen_cpuhp_setup()); 1919 WARN_ON(xen_cpuhp_setup());
1929 xen_unplug_emulated_devices(); 1920 xen_unplug_emulated_devices();
@@ -1961,7 +1952,7 @@ bool xen_hvm_need_lapic(void)
1961 return false; 1952 return false;
1962 if (!xen_hvm_domain()) 1953 if (!xen_hvm_domain())
1963 return false; 1954 return false;
1964 if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback) 1955 if (xen_feature(XENFEAT_hvm_pirqs))
1965 return false; 1956 return false;
1966 return true; 1957 return true;
1967} 1958}
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 137afbbd0590..311acad7dad2 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -765,8 +765,6 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
765 765
766void __init xen_hvm_smp_init(void) 766void __init xen_hvm_smp_init(void)
767{ 767{
768 if (!xen_have_vector_callback)
769 return;
770 smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; 768 smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
771 smp_ops.smp_send_reschedule = xen_smp_send_reschedule; 769 smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
772 smp_ops.cpu_die = xen_cpu_die; 770 smp_ops.cpu_die = xen_cpu_die;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 67356d29d74d..33d8f6a7829d 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -432,11 +432,6 @@ static void xen_hvm_setup_cpu_clockevents(void)
432 432
433void __init xen_hvm_init_time_ops(void) 433void __init xen_hvm_init_time_ops(void)
434{ 434{
435 /* vector callback is needed otherwise we cannot receive interrupts
436 * on cpu > 0 and at this point we don't know how many cpus are
437 * available */
438 if (!xen_have_vector_callback)
439 return;
440 if (!xen_feature(XENFEAT_hvm_safe_pvclock)) { 435 if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
441 printk(KERN_INFO "Xen doesn't support pvclock on HVM," 436 printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
442 "disable pv timer\n"); 437 "disable pv timer\n");
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index d5dbdb9d24d8..9ecfcdcdd6d6 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -1314,9 +1314,6 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
1314 if (!VALID_EVTCHN(evtchn)) 1314 if (!VALID_EVTCHN(evtchn))
1315 return -1; 1315 return -1;
1316 1316
1317 if (!xen_support_evtchn_rebind())
1318 return -1;
1319
1320 /* Send future instances of this interrupt to other vcpu. */ 1317 /* Send future instances of this interrupt to other vcpu. */
1321 bind_vcpu.port = evtchn; 1318 bind_vcpu.port = evtchn;
1322 bind_vcpu.vcpu = xen_vcpu_nr(tcpu); 1319 bind_vcpu.vcpu = xen_vcpu_nr(tcpu);
@@ -1650,20 +1647,15 @@ void xen_callback_vector(void)
1650{ 1647{
1651 int rc; 1648 int rc;
1652 uint64_t callback_via; 1649 uint64_t callback_via;
1653 if (xen_have_vector_callback) { 1650
1654 callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); 1651 callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
1655 rc = xen_set_callback_via(callback_via); 1652 rc = xen_set_callback_via(callback_via);
1656 if (rc) { 1653 BUG_ON(rc);
1657 pr_err("Request for Xen HVM callback vector failed\n"); 1654 pr_info("Xen HVM callback vector for event delivery is enabled\n");
1658 xen_have_vector_callback = 0; 1655 /* in the restore case the vector has already been allocated */
1659 return; 1656 if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
1660 } 1657 alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
1661 pr_info("Xen HVM callback vector for event delivery is enabled\n"); 1658 xen_hvm_callback_vector);
1662 /* in the restore case the vector has already been allocated */
1663 if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
1664 alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
1665 xen_hvm_callback_vector);
1666 }
1667} 1659}
1668#else 1660#else
1669void xen_callback_vector(void) {} 1661void xen_callback_vector(void) {}
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index cf9666680c8c..b59c9455aae1 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -42,7 +42,6 @@
42static unsigned long platform_mmio; 42static unsigned long platform_mmio;
43static unsigned long platform_mmio_alloc; 43static unsigned long platform_mmio_alloc;
44static unsigned long platform_mmiolen; 44static unsigned long platform_mmiolen;
45static uint64_t callback_via;
46 45
47static unsigned long alloc_xen_mmio(unsigned long len) 46static unsigned long alloc_xen_mmio(unsigned long len)
48{ 47{
@@ -55,51 +54,6 @@ static unsigned long alloc_xen_mmio(unsigned long len)
55 return addr; 54 return addr;
56} 55}
57 56
58static uint64_t get_callback_via(struct pci_dev *pdev)
59{
60 u8 pin;
61 int irq;
62
63 irq = pdev->irq;
64 if (irq < 16)
65 return irq; /* ISA IRQ */
66
67 pin = pdev->pin;
68
69 /* We don't know the GSI. Specify the PCI INTx line instead. */
70 return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
71 ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
72 ((uint64_t)pdev->bus->number << 16) |
73 ((uint64_t)(pdev->devfn & 0xff) << 8) |
74 ((uint64_t)(pin - 1) & 3);
75}
76
77static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
78{
79 xen_hvm_evtchn_do_upcall();
80 return IRQ_HANDLED;
81}
82
83static int xen_allocate_irq(struct pci_dev *pdev)
84{
85 return request_irq(pdev->irq, do_hvm_evtchn_intr,
86 IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
87 "xen-platform-pci", pdev);
88}
89
90static int platform_pci_resume(struct pci_dev *pdev)
91{
92 int err;
93 if (xen_have_vector_callback)
94 return 0;
95 err = xen_set_callback_via(callback_via);
96 if (err) {
97 dev_err(&pdev->dev, "platform_pci_resume failure!\n");
98 return err;
99 }
100 return 0;
101}
102
103static int platform_pci_probe(struct pci_dev *pdev, 57static int platform_pci_probe(struct pci_dev *pdev,
104 const struct pci_device_id *ent) 58 const struct pci_device_id *ent)
105{ 59{
@@ -138,21 +92,6 @@ static int platform_pci_probe(struct pci_dev *pdev,
138 platform_mmio = mmio_addr; 92 platform_mmio = mmio_addr;
139 platform_mmiolen = mmio_len; 93 platform_mmiolen = mmio_len;
140 94
141 if (!xen_have_vector_callback) {
142 ret = xen_allocate_irq(pdev);
143 if (ret) {
144 dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
145 goto out;
146 }
147 callback_via = get_callback_via(pdev);
148 ret = xen_set_callback_via(callback_via);
149 if (ret) {
150 dev_warn(&pdev->dev, "Unable to set the evtchn callback "
151 "err=%d\n", ret);
152 goto out;
153 }
154 }
155
156 max_nr_gframes = gnttab_max_grant_frames(); 95 max_nr_gframes = gnttab_max_grant_frames();
157 grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); 96 grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
158 ret = gnttab_setup_auto_xlat_frames(grant_frames); 97 ret = gnttab_setup_auto_xlat_frames(grant_frames);
@@ -184,9 +123,6 @@ static struct pci_driver platform_driver = {
184 .name = DRV_NAME, 123 .name = DRV_NAME,
185 .probe = platform_pci_probe, 124 .probe = platform_pci_probe,
186 .id_table = platform_pci_tbl, 125 .id_table = platform_pci_tbl,
187#ifdef CONFIG_PM
188 .resume_early = platform_pci_resume,
189#endif
190}; 126};
191 127
192static int __init platform_pci_init(void) 128static int __init platform_pci_init(void)
diff --git a/include/xen/xen.h b/include/xen/xen.h
index 0c0e3ef4c45d..f0f0252cff9a 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -38,8 +38,7 @@ extern enum xen_domain_type xen_domain_type;
38 */ 38 */
39#include <xen/features.h> 39#include <xen/features.h>
40#define xen_pvh_domain() (xen_pv_domain() && \ 40#define xen_pvh_domain() (xen_pv_domain() && \
41 xen_feature(XENFEAT_auto_translated_physmap) && \ 41 xen_feature(XENFEAT_auto_translated_physmap))
42 xen_have_vector_callback)
43#else 42#else
44#define xen_pvh_domain() (0) 43#define xen_pvh_domain() (0)
45#endif 44#endif