aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2015-12-11 09:07:53 -0500
committerThomas Gleixner <tglx@linutronix.de>2015-12-19 15:35:13 -0500
commitd8c98a1d1488747625ad6044d423406e17e99b7a (patch)
treeeb3da23aa3de0360995dd16779a74df328284227
parent91e2eea98f94a2ebb143d4c4cdeaa4573d62dc17 (diff)
x86/paravirt: Prevent rtc_cmos platform device init on PV guests
Adding the rtc platform device in non-privileged Xen PV guests causes an IRQ conflict because these guests do not have legacy PIC and may allocate irqs in the legacy range. In a single VCPU Xen PV guest we should have: /proc/interrupts: CPU0 0: 4934 xen-percpu-virq timer0 1: 0 xen-percpu-ipi spinlock0 2: 0 xen-percpu-ipi resched0 3: 0 xen-percpu-ipi callfunc0 4: 0 xen-percpu-virq debug0 5: 0 xen-percpu-ipi callfuncsingle0 6: 0 xen-percpu-ipi irqwork0 7: 321 xen-dyn-event xenbus 8: 90 xen-dyn-event hvc_console ... But hvc_console cannot get its interrupt because it is already in use by rtc0 and the console does not work. genirq: Flags mismatch irq 8. 00000000 (hvc_console) vs. 00000000 (rtc0) We can avoid this problem by realizing that unprivileged PV guests (both Xen and lguests) are not supposed to have rtc_cmos device and so adding it is not necessary. Privileged guests (i.e. Xen's dom0) do use it but they should not have irq conflicts since they allocate irqs above legacy range (above gsi_top, in fact). Instead of explicitly testing whether the guest is privileged we can extend pv_info structure to include information about guest's RTC support. Reported-and-tested-by: Sander Eikelenboom <linux@eikelenboom.it> Signed-off-by: David Vrabel <david.vrabel@citrix.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: vkuznets@redhat.com Cc: xen-devel@lists.xenproject.org Cc: konrad.wilk@oracle.com Cc: stable@vger.kernel.org # 4.2+ Link: http://lkml.kernel.org/r/1449842873-2613-1-git-send-email-boris.ostrovsky@oracle.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/include/asm/paravirt.h6
-rw-r--r--arch/x86/include/asm/paravirt_types.h5
-rw-r--r--arch/x86/include/asm/processor.h1
-rw-r--r--arch/x86/kernel/rtc.c3
-rw-r--r--arch/x86/lguest/boot.c1
-rw-r--r--arch/x86/xen/enlighten.c4
6 files changed, 19 insertions, 1 deletions
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 10d0596433f8..c759b3cca663 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -19,6 +19,12 @@ static inline int paravirt_enabled(void)
19 return pv_info.paravirt_enabled; 19 return pv_info.paravirt_enabled;
20} 20}
21 21
22static inline int paravirt_has_feature(unsigned int feature)
23{
24 WARN_ON_ONCE(!pv_info.paravirt_enabled);
25 return (pv_info.features & feature);
26}
27
22static inline void load_sp0(struct tss_struct *tss, 28static inline void load_sp0(struct tss_struct *tss,
23 struct thread_struct *thread) 29 struct thread_struct *thread)
24{ 30{
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 31247b5bff7c..3d44191185f8 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -70,9 +70,14 @@ struct pv_info {
70#endif 70#endif
71 71
72 int paravirt_enabled; 72 int paravirt_enabled;
73 unsigned int features; /* valid only if paravirt_enabled is set */
73 const char *name; 74 const char *name;
74}; 75};
75 76
77#define paravirt_has(x) paravirt_has_feature(PV_SUPPORTED_##x)
78/* Supported features */
79#define PV_SUPPORTED_RTC (1<<0)
80
76struct pv_init_ops { 81struct pv_init_ops {
77 /* 82 /*
78 * Patch may replace one of the defined code sequences with 83 * Patch may replace one of the defined code sequences with
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 67522256c7ff..2d5a50cb61a2 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -472,6 +472,7 @@ static inline unsigned long current_top_of_stack(void)
472#else 472#else
473#define __cpuid native_cpuid 473#define __cpuid native_cpuid
474#define paravirt_enabled() 0 474#define paravirt_enabled() 0
475#define paravirt_has(x) 0
475 476
476static inline void load_sp0(struct tss_struct *tss, 477static inline void load_sp0(struct tss_struct *tss,
477 struct thread_struct *thread) 478 struct thread_struct *thread)
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index cd9685235df9..4af8d063fb36 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -200,6 +200,9 @@ static __init int add_rtc_cmos(void)
200 } 200 }
201#endif 201#endif
202 202
203 if (paravirt_enabled() && !paravirt_has(RTC))
204 return -ENODEV;
205
203 platform_device_register(&rtc_device); 206 platform_device_register(&rtc_device);
204 dev_info(&rtc_device.dev, 207 dev_info(&rtc_device.dev,
205 "registered platform RTC device (no PNP device found)\n"); 208 "registered platform RTC device (no PNP device found)\n");
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index a0d09f6c6533..a43b2eafc466 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1414,6 +1414,7 @@ __init void lguest_init(void)
1414 pv_info.kernel_rpl = 1; 1414 pv_info.kernel_rpl = 1;
1415 /* Everyone except Xen runs with this set. */ 1415 /* Everyone except Xen runs with this set. */
1416 pv_info.shared_kernel_pmd = 1; 1416 pv_info.shared_kernel_pmd = 1;
1417 pv_info.features = 0;
1417 1418
1418 /* 1419 /*
1419 * We set up all the lguest overrides for sensitive operations. These 1420 * We set up all the lguest overrides for sensitive operations. These
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index d315151411e5..b7de78bdc09c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1192,7 +1192,7 @@ static const struct pv_info xen_info __initconst = {
1192#ifdef CONFIG_X86_64 1192#ifdef CONFIG_X86_64
1193 .extra_user_64bit_cs = FLAT_USER_CS64, 1193 .extra_user_64bit_cs = FLAT_USER_CS64,
1194#endif 1194#endif
1195 1195 .features = 0,
1196 .name = "Xen", 1196 .name = "Xen",
1197}; 1197};
1198 1198
@@ -1535,6 +1535,8 @@ asmlinkage __visible void __init xen_start_kernel(void)
1535 1535
1536 /* Install Xen paravirt ops */ 1536 /* Install Xen paravirt ops */
1537 pv_info = xen_info; 1537 pv_info = xen_info;
1538 if (xen_initial_domain())
1539 pv_info.features |= PV_SUPPORTED_RTC;
1538 pv_init_ops = xen_init_ops; 1540 pv_init_ops = xen_init_ops;
1539 pv_apic_ops = xen_apic_ops; 1541 pv_apic_ops = xen_apic_ops;
1540 if (!xen_pvh_domain()) { 1542 if (!xen_pvh_domain()) {