Commit 4cca6ea0 authored by Alok N Kataria's avatar Alok N Kataria Committed by Ingo Molnar

x86/apic: Allow x2apic without IR on VMware platform

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: default avatarAlok N Kataria <akataria@vmware.com>
Reviewed-by: default avatarDoug Covelli <dcovelli@vmware.com>
Reviewed-by: default avatarDan Hecht <dhecht@vmware.com>
Acked-by: default avatarH. 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.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent e3f0f36d
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
extern void init_hypervisor(struct cpuinfo_x86 *c); extern void init_hypervisor(struct cpuinfo_x86 *c);
extern void init_hypervisor_platform(void); extern void init_hypervisor_platform(void);
extern bool hypervisor_x2apic_available(void);
/* /*
* x86 hypervisor information * x86 hypervisor information
...@@ -41,6 +42,9 @@ struct hypervisor_x86 { ...@@ -41,6 +42,9 @@ struct hypervisor_x86 {
/* Platform setup (run once per boot) */ /* Platform setup (run once per boot) */
void (*init_platform)(void); void (*init_platform)(void);
/* X2APIC detection (run once per boot) */
bool (*x2apic_available)(void);
}; };
extern const struct hypervisor_x86 *x86_hyper; extern const struct hypervisor_x86 *x86_hyper;
...@@ -51,13 +55,4 @@ extern const struct hypervisor_x86 x86_hyper_ms_hyperv; ...@@ -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_xen_hvm;
extern const struct hypervisor_x86 x86_hyper_kvm; 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 #endif
...@@ -79,3 +79,10 @@ void __init init_hypervisor_platform(void) ...@@ -79,3 +79,10 @@ void __init init_hypervisor_platform(void)
if (x86_hyper->init_platform) if (x86_hyper->init_platform)
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();
}
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#define VMWARE_PORT_CMD_GETVERSION 10 #define VMWARE_PORT_CMD_GETVERSION 10
#define VMWARE_PORT_CMD_GETHZ 45 #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) \ #define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \
__asm__("inl (%%dx)" : \ __asm__("inl (%%dx)" : \
...@@ -125,10 +128,20 @@ static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c) ...@@ -125,10 +128,20 @@ static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); 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 = { const __refconst struct hypervisor_x86 x86_hyper_vmware = {
.name = "VMware", .name = "VMware",
.detect = vmware_platform, .detect = vmware_platform,
.set_cpu_features = vmware_set_cpu_features, .set_cpu_features = vmware_set_cpu_features,
.init_platform = vmware_platform_setup, .init_platform = vmware_platform_setup,
.x2apic_available = vmware_legacy_x2apic_available,
}; };
EXPORT_SYMBOL(x86_hyper_vmware); EXPORT_SYMBOL(x86_hyper_vmware);
...@@ -505,6 +505,7 @@ static bool __init kvm_detect(void) ...@@ -505,6 +505,7 @@ static bool __init kvm_detect(void)
const struct hypervisor_x86 x86_hyper_kvm __refconst = { const struct hypervisor_x86 x86_hyper_kvm __refconst = {
.name = "KVM", .name = "KVM",
.detect = kvm_detect, .detect = kvm_detect,
.x2apic_available = kvm_para_available,
}; };
EXPORT_SYMBOL_GPL(x86_hyper_kvm); EXPORT_SYMBOL_GPL(x86_hyper_kvm);
......
...@@ -1668,6 +1668,7 @@ const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = { ...@@ -1668,6 +1668,7 @@ const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
.name = "Xen HVM", .name = "Xen HVM",
.detect = xen_hvm_platform, .detect = xen_hvm_platform,
.init_platform = xen_hvm_guest_init, .init_platform = xen_hvm_guest_init,
.x2apic_available = xen_x2apic_para_available,
}; };
EXPORT_SYMBOL(x86_hyper_xen_hvm); EXPORT_SYMBOL(x86_hyper_xen_hvm);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment