x86/apic: Allow x2apic without IR on VMware platform
authorAlok N Kataria <akataria@vmware.com>
Thu, 17 Jan 2013 23:44:42 +0000 (15:44 -0800)
committerIngo Molnar <mingo@kernel.org>
Thu, 24 Jan 2013 12:11:18 +0000 (13:11 +0100)
This patch updates x2apic initializaition code to allow x2apic
on VMware platform even without interrupt remapping support.
The hypervisor_x2apic_available hook was added in x2apic
initialization code and used by KVM and XEN, before this.
I have also cleaned up that code to export this hook through the
hypervisor_x86 structure.

Compile tested for KVM and XEN configs, this patch doesn't have
any functional effect on those two platforms.

On VMware platform, verified that x2apic is used in physical
mode on products that support this.

Signed-off-by: Alok N Kataria <akataria@vmware.com>
Reviewed-by: Doug Covelli <dcovelli@vmware.com>
Reviewed-by: Dan Hecht <dhecht@vmware.com>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Avi Kivity <avi@redhat.com>
Link: http://lkml.kernel.org/r/1358466282.423.60.camel@akataria-dtop.eng.vmware.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/hypervisor.h
arch/x86/kernel/cpu/hypervisor.c
arch/x86/kernel/cpu/vmware.c
arch/x86/kernel/kvm.c
arch/x86/xen/enlighten.c

index b518c7509933337225756646fcbd73a6882c2990..86095ed141356f3210fee6954f80a763df4a5bea 100644 (file)
@@ -25,6 +25,7 @@
 
 extern void init_hypervisor(struct cpuinfo_x86 *c);
 extern void init_hypervisor_platform(void);
+extern bool hypervisor_x2apic_available(void);
 
 /*
  * x86 hypervisor information
@@ -41,6 +42,9 @@ struct hypervisor_x86 {
 
        /* Platform setup (run once per boot) */
        void            (*init_platform)(void);
+
+       /* X2APIC detection (run once per boot) */
+       bool            (*x2apic_available)(void);
 };
 
 extern const struct hypervisor_x86 *x86_hyper;
@@ -51,13 +55,4 @@ extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
 extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 extern const struct hypervisor_x86 x86_hyper_kvm;
 
-static inline bool hypervisor_x2apic_available(void)
-{
-       if (kvm_para_available())
-               return true;
-       if (xen_x2apic_para_available())
-               return true;
-       return false;
-}
-
 #endif
index a8f8fa9769d680869d1f9e533f79608baa181ca7..1e7e84a02ebaf4924702019c18cc5d1101609c30 100644 (file)
@@ -79,3 +79,10 @@ void __init init_hypervisor_platform(void)
        if (x86_hyper->init_platform)
                x86_hyper->init_platform();
 }
+
+bool __init hypervisor_x2apic_available(void)
+{
+       return x86_hyper                   &&
+              x86_hyper->x2apic_available &&
+              x86_hyper->x2apic_available();
+}
index d22d0c4edcfd0ab0ef81322fbfe0ffd7e81a5d32..03a36321ec54428b098a3a874f7db83e4daafcfd 100644 (file)
@@ -33,6 +33,9 @@
 
 #define VMWARE_PORT_CMD_GETVERSION     10
 #define VMWARE_PORT_CMD_GETHZ          45
+#define VMWARE_PORT_CMD_GETVCPU_INFO   68
+#define VMWARE_PORT_CMD_LEGACY_X2APIC  3
+#define VMWARE_PORT_CMD_VCPU_RESERVED  31
 
 #define VMWARE_PORT(cmd, eax, ebx, ecx, edx)                           \
        __asm__("inl (%%dx)" :                                          \
@@ -125,10 +128,20 @@ static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c)
        set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
 }
 
+/* Checks if hypervisor supports x2apic without VT-D interrupt remapping. */
+static bool __init vmware_legacy_x2apic_available(void)
+{
+       uint32_t eax, ebx, ecx, edx;
+       VMWARE_PORT(GETVCPU_INFO, eax, ebx, ecx, edx);
+       return (eax & (1 << VMWARE_PORT_CMD_VCPU_RESERVED)) == 0 &&
+              (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
+}
+
 const __refconst struct hypervisor_x86 x86_hyper_vmware = {
        .name                   = "VMware",
        .detect                 = vmware_platform,
        .set_cpu_features       = vmware_set_cpu_features,
        .init_platform          = vmware_platform_setup,
+       .x2apic_available       = vmware_legacy_x2apic_available,
 };
 EXPORT_SYMBOL(x86_hyper_vmware);
index 9c2bd8bd4b4c1f3cbeb7965b04bb57c3239e41a2..2b44ea5f269dbb3b22b649b5461163195653da80 100644 (file)
@@ -505,6 +505,7 @@ static bool __init kvm_detect(void)
 const struct hypervisor_x86 x86_hyper_kvm __refconst = {
        .name                   = "KVM",
        .detect                 = kvm_detect,
+       .x2apic_available       = kvm_para_available,
 };
 EXPORT_SYMBOL_GPL(x86_hyper_kvm);
 
index 138e5667409a3415492e860c8cfa708028d6d467..8b4c56d85ca06092f504f803e5b241c31906dc47 100644 (file)
@@ -1668,6 +1668,7 @@ const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
        .name                   = "Xen HVM",
        .detect                 = xen_hvm_platform,
        .init_platform          = xen_hvm_guest_init,
+       .x2apic_available       = xen_x2apic_para_available,
 };
 EXPORT_SYMBOL(x86_hyper_xen_hvm);
 #endif