aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Ostrovsky <boris.ostrovsky@oracle.com>2017-04-24 15:04:53 -0400
committerJuergen Gross <jgross@suse.com>2017-05-02 05:18:05 -0400
commit84d582d236dc1f9085e741affc72e9ba061a67c2 (patch)
tree7d012e4f1739b44c0bb5373a091a6f195c057d82
parent5f6a1614fab801834e32b420b60acdc27acfcdec (diff)
xen: Revert commits da72ff5bfcb0 and 72a9b186292d
Recent discussion (http://marc.info/?l=xen-devel&m=149192184523741) established that commit 72a9b186292d ("xen: Remove event channel notification through Xen PCI platform device") (and thus commit da72ff5bfcb0 ("partially revert "xen: Remove event channel notification through Xen PCI platform device"")) are unnecessary and, in fact, prevent HVM guests from booting on Xen releases prior to 4.0 Therefore we revert both of those commits. The summary of that discussion is below: Here is the brief summary of the current situation: Before the offending commit (72a9b186292): 1) INTx does not work because of the reset_watches path. 2) The reset_watches path is only taken if you have Xen > 4.0 3) The Linux Kernel by default will use vector inject if the hypervisor support. So even INTx does not work no body running the kernel with Xen > 4.0 would notice. Unless he explicitly disabled this feature either in the kernel or in Xen (and this can only be disabled by modifying the code, not user-supported way to do it). After the offending commit (+ partial revert): 1) INTx is no longer support for HVM (only for PV guests). 2) Any HVM guest The kernel will not boot on Xen < 4.0 which does not have vector injection support. Since the only other mode supported is INTx which. So based on this summary, I think before commit (72a9b186292) we were in much better position from a user point of view. Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Reviewed-by: Juergen Gross <jgross@suse.com> Signed-off-by: Juergen Gross <jgross@suse.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_hvm.c12
-rw-r--r--arch/x86/xen/smp_hvm.c5
-rw-r--r--arch/x86/xen/time.c8
-rw-r--r--drivers/xen/events/events_base.c25
-rw-r--r--drivers/xen/platform-pci.c14
7 files changed, 54 insertions, 23 deletions
diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h
index 608a79d5a466..e6911caf5bbf 100644
--- a/arch/x86/include/asm/xen/events.h
+++ b/arch/x86/include/asm/xen/events.h
@@ -20,4 +20,15 @@ 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
23#endif /* _ASM_X86_XEN_EVENTS_H */ 34#endif /* _ASM_X86_XEN_EVENTS_H */
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 292ab0364a89..c4b3646bd04c 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -447,7 +447,7 @@ void __init xen_msi_init(void)
447 447
448int __init pci_xen_hvm_init(void) 448int __init pci_xen_hvm_init(void)
449{ 449{
450 if (!xen_feature(XENFEAT_hvm_pirqs)) 450 if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs))
451 return 0; 451 return 0;
452 452
453#ifdef CONFIG_ACPI 453#ifdef CONFIG_ACPI
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index 72df54a481d6..078c512b8720 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -18,6 +18,9 @@
18#include "mmu.h" 18#include "mmu.h"
19#include "smp.h" 19#include "smp.h"
20 20
21__read_mostly int xen_have_vector_callback;
22EXPORT_SYMBOL_GPL(xen_have_vector_callback);
23
21void __ref xen_hvm_init_shared_info(void) 24void __ref xen_hvm_init_shared_info(void)
22{ 25{
23 int cpu; 26 int cpu;
@@ -123,7 +126,7 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu)
123 per_cpu(xen_vcpu_id, cpu) = cpu; 126 per_cpu(xen_vcpu_id, cpu) = cpu;
124 xen_vcpu_setup(cpu); 127 xen_vcpu_setup(cpu);
125 128
126 if (xen_feature(XENFEAT_hvm_safe_pvclock)) 129 if (xen_have_vector_callback && xen_feature(XENFEAT_hvm_safe_pvclock))
127 xen_setup_timer(cpu); 130 xen_setup_timer(cpu);
128 131
129 rc = xen_smp_intr_init(cpu); 132 rc = xen_smp_intr_init(cpu);
@@ -139,7 +142,7 @@ static int xen_cpu_dead_hvm(unsigned int cpu)
139{ 142{
140 xen_smp_intr_free(cpu); 143 xen_smp_intr_free(cpu);
141 144
142 if (xen_feature(XENFEAT_hvm_safe_pvclock)) 145 if (xen_have_vector_callback && xen_feature(XENFEAT_hvm_safe_pvclock))
143 xen_teardown_timer(cpu); 146 xen_teardown_timer(cpu);
144 147
145 return 0; 148 return 0;
@@ -156,7 +159,8 @@ static void __init xen_hvm_guest_init(void)
156 159
157 xen_panic_handler_init(); 160 xen_panic_handler_init();
158 161
159 BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector)); 162 if (xen_feature(XENFEAT_hvm_callback_vector))
163 xen_have_vector_callback = 1;
160 164
161 xen_hvm_smp_init(); 165 xen_hvm_smp_init();
162 WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm)); 166 WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm));
@@ -189,7 +193,7 @@ bool xen_hvm_need_lapic(void)
189 return false; 193 return false;
190 if (!xen_hvm_domain()) 194 if (!xen_hvm_domain())
191 return false; 195 return false;
192 if (xen_feature(XENFEAT_hvm_pirqs)) 196 if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback)
193 return false; 197 return false;
194 return true; 198 return true;
195} 199}
diff --git a/arch/x86/xen/smp_hvm.c b/arch/x86/xen/smp_hvm.c
index 8bed434cd7d7..f18561bbf5c9 100644
--- a/arch/x86/xen/smp_hvm.c
+++ b/arch/x86/xen/smp_hvm.c
@@ -1,5 +1,7 @@
1#include <asm/smp.h> 1#include <asm/smp.h>
2 2
3#include <xen/events.h>
4
3#include "xen-ops.h" 5#include "xen-ops.h"
4#include "smp.h" 6#include "smp.h"
5 7
@@ -49,6 +51,9 @@ static void xen_hvm_cpu_die(unsigned int cpu)
49 51
50void __init xen_hvm_smp_init(void) 52void __init xen_hvm_smp_init(void)
51{ 53{
54 if (!xen_have_vector_callback)
55 return;
56
52 smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; 57 smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
53 smp_ops.smp_send_reschedule = xen_smp_send_reschedule; 58 smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
54 smp_ops.cpu_die = xen_hvm_cpu_die; 59 smp_ops.cpu_die = xen_hvm_cpu_die;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 7a3089285c59..090c7eb4dca9 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -436,6 +436,14 @@ static void xen_hvm_setup_cpu_clockevents(void)
436 436
437void __init xen_hvm_init_time_ops(void) 437void __init xen_hvm_init_time_ops(void)
438{ 438{
439 /*
440 * vector callback is needed otherwise we cannot receive interrupts
441 * on cpu > 0 and at this point we don't know how many cpus are
442 * available.
443 */
444 if (!xen_have_vector_callback)
445 return;
446
439 if (!xen_feature(XENFEAT_hvm_safe_pvclock)) { 447 if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
440 printk(KERN_INFO "Xen doesn't support pvclock on HVM," 448 printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
441 "disable pv timer\n"); 449 "disable pv timer\n");
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 6a53577772c9..b52852f38cff 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -1312,6 +1312,9 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
1312 if (!VALID_EVTCHN(evtchn)) 1312 if (!VALID_EVTCHN(evtchn))
1313 return -1; 1313 return -1;
1314 1314
1315 if (!xen_support_evtchn_rebind())
1316 return -1;
1317
1315 /* Send future instances of this interrupt to other vcpu. */ 1318 /* Send future instances of this interrupt to other vcpu. */
1316 bind_vcpu.port = evtchn; 1319 bind_vcpu.port = evtchn;
1317 bind_vcpu.vcpu = xen_vcpu_nr(tcpu); 1320 bind_vcpu.vcpu = xen_vcpu_nr(tcpu);
@@ -1646,14 +1649,20 @@ void xen_callback_vector(void)
1646 int rc; 1649 int rc;
1647 uint64_t callback_via; 1650 uint64_t callback_via;
1648 1651
1649 callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); 1652 if (xen_have_vector_callback) {
1650 rc = xen_set_callback_via(callback_via); 1653 callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
1651 BUG_ON(rc); 1654 rc = xen_set_callback_via(callback_via);
1652 pr_info("Xen HVM callback vector for event delivery is enabled\n"); 1655 if (rc) {
1653 /* in the restore case the vector has already been allocated */ 1656 pr_err("Request for Xen HVM callback vector failed\n");
1654 if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) 1657 xen_have_vector_callback = 0;
1655 alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, 1658 return;
1656 xen_hvm_callback_vector); 1659 }
1660 pr_info("Xen HVM callback vector for event delivery is enabled\n");
1661 /* in the restore case the vector has already been allocated */
1662 if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
1663 alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
1664 xen_hvm_callback_vector);
1665 }
1657} 1666}
1658#else 1667#else
1659void xen_callback_vector(void) {} 1668void xen_callback_vector(void) {}
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index 2a165cc8a43c..1275df83070f 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -90,8 +90,10 @@ static int xen_allocate_irq(struct pci_dev *pdev)
90static int platform_pci_resume(struct pci_dev *pdev) 90static int platform_pci_resume(struct pci_dev *pdev)
91{ 91{
92 int err; 92 int err;
93 if (!xen_pv_domain()) 93
94 if (xen_have_vector_callback)
94 return 0; 95 return 0;
96
95 err = xen_set_callback_via(callback_via); 97 err = xen_set_callback_via(callback_via);
96 if (err) { 98 if (err) {
97 dev_err(&pdev->dev, "platform_pci_resume failure!\n"); 99 dev_err(&pdev->dev, "platform_pci_resume failure!\n");
@@ -137,15 +139,7 @@ static int platform_pci_probe(struct pci_dev *pdev,
137 139
138 platform_mmio = mmio_addr; 140 platform_mmio = mmio_addr;
139 platform_mmiolen = mmio_len; 141 platform_mmiolen = mmio_len;
140 142 if (!xen_have_vector_callback) {
141 /*
142 * Xen HVM guests always use the vector callback mechanism.
143 * L1 Dom0 in a nested Xen environment is a PV guest inside in an
144 * HVM environment. It needs the platform-pci driver to get
145 * notifications from L0 Xen, but it cannot use the vector callback
146 * as it is not exported by L1 Xen.
147 */
148 if (xen_pv_domain()) {
149 ret = xen_allocate_irq(pdev); 143 ret = xen_allocate_irq(pdev);
150 if (ret) { 144 if (ret) {
151 dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); 145 dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);