x86: Clean up the hypervisor layer

Clean up the hypervisor layer and the hypervisor drivers, using an ops
structure instead of an enumeration with if statements.

The identity of the hypervisor, if needed, can be tested by testing
the pointer value in x86_hyper.

The MS-HyperV private state is moved into a normal global variable
(it's per-system state, not per-CPU state).  Being a normal bss
variable, it will be left at all zero on non-HyperV platforms, and so
can generally be tested for HyperV-specific features without
additional qualification.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Acked-by: Greg KH <greg@kroah.com>
Cc: Hank Janssen <hjanssen@microsoft.com>
Cc: Alok Kataria <akataria@vmware.com>
Cc: Ky Srinivasan <ksrinivasan@novell.com>
LKML-Reference: <4BE49778.6060800@zytor.com>
This commit is contained in:
H. Peter Anvin
2010-05-07 16:57:28 -07:00
parent 9fa0231742
commit e08cae4181
8 changed files with 116 additions and 106 deletions

View File

@@ -22,40 +22,52 @@
*/
#include <asm/processor.h>
#include <asm/vmware.h>
#include <asm/mshyperv.h>
#include <asm/hypervisor.h>
static inline void __cpuinit
detect_hypervisor_vendor(struct cpuinfo_x86 *c)
/*
* Hypervisor detect order. This is specified explicitly here because
* some hypervisors might implement compatibility modes for other
* hypervisors and therefore need to be detected in specific sequence.
*/
static const __initconst struct hypervisor_x86 * const hypervisors[] =
{
if (vmware_platform())
c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE;
else if (ms_hyperv_platform())
c->x86_hyper_vendor = X86_HYPER_VENDOR_MSFT;
else
c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE;
}
&x86_hyper_vmware,
&x86_hyper_ms_hyperv,
};
static inline void __cpuinit
hypervisor_set_feature_bits(struct cpuinfo_x86 *c)
const struct hypervisor_x86 *x86_hyper;
static inline void __init
detect_hypervisor_vendor(void)
{
if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE)
vmware_set_feature_bits(c);
else if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_MSFT)
ms_hyperv_set_feature_bits(c);
return;
const struct hypervisor_x86 *h, * const *p;
for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) {
h = *p;
if (h->detect()) {
x86_hyper = h;
printk(KERN_INFO "Hypervisor detected: %s\n", h->name);
break;
}
}
}
void __cpuinit init_hypervisor(struct cpuinfo_x86 *c)
{
detect_hypervisor_vendor(c);
hypervisor_set_feature_bits(c);
if (x86_hyper && x86_hyper->set_cpu_features)
x86_hyper->set_cpu_features(c);
}
void __init init_hypervisor_platform(void)
{
detect_hypervisor_vendor();
if (!x86_hyper)
return;
init_hypervisor(&boot_cpu_data);
if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE)
vmware_platform_setup();
if (x86_hyper->init_platform)
x86_hyper->init_platform();
}