summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/cpu/mshyperv.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-05-07 16:57:28 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-05-07 17:13:04 -0700
commite08cae4181af9483b04ecfac48f01c8e5a5f27bf (patch)
tree2cab8da747a6524694cc19f247d8bc4f157a601c /arch/x86/kernel/cpu/mshyperv.c
parent9fa02317429449e8176c9bb6da3ac00eb14d52d3 (diff)
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>
Diffstat (limited to 'arch/x86/kernel/cpu/mshyperv.c')
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c51
1 files changed, 24 insertions, 27 deletions
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index a58d8e64fc7c..5969c3ee3186 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -12,45 +12,42 @@
#include <linux/types.h>
#include <asm/processor.h>
+#include <asm/hypervisor.h>
#include <asm/hyperv.h>
#include <asm/mshyperv.h>
+struct ms_hyperv_info ms_hyperv;
-int ms_hyperv_platform(void)
+static bool __init ms_hyperv_platform(void)
{
- u32 eax, ebx, ecx, edx;
- char hyp_signature[13];
+ u32 eax;
+ u32 hyp_signature[3];
- cpuid(1, &eax, &ebx, &ecx, &edx);
- if (!(ecx & HYPERV_HYPERVISOR_PRESENT_BIT))
- return 0;
+ if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
+ return false;
- cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, &eax, &ebx, &ecx, &edx);
- *(u32 *)(hyp_signature + 0) = ebx;
- *(u32 *)(hyp_signature + 4) = ecx;
- *(u32 *)(hyp_signature + 8) = edx;
+ cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
+ &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
- if ((eax < HYPERV_CPUID_MIN) || (memcmp("Microsoft Hv", hyp_signature, 12)))
- return 0;
- return 1;
+ return eax >= HYPERV_CPUID_MIN &&
+ eax <= HYPERV_CPUID_MAX &&
+ !memcmp("Microsoft Hv", hyp_signature, 12);
}
-void __cpuinit ms_hyperv_set_feature_bits(struct cpuinfo_x86 *c)
+static void __init ms_hyperv_init_platform(void)
{
- u32 eax, ebx, ecx, edx;
-
- c->x86_hyper_features = 0;
/*
- * Extract the features, recommendations etc.
- * The first 9 bits will be used to track hypervisor features.
- * The next 6 bits will be used to track the hypervisor
- * recommendations.
+ * Extract the features and hints
*/
- cpuid(HYPERV_CPUID_FEATURES, &eax, &ebx, &ecx, &edx);
- c->x86_hyper_features |= (eax & 0x1ff);
+ ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
+ ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
- cpuid(HYPERV_CPUID_ENLIGHTMENT_INFO, &eax, &ebx, &ecx, &edx);
- c->x86_hyper_features |= ((eax & 0x3f) << 9);
- printk(KERN_INFO "Detected HyperV with features: %x\n",
- c->x86_hyper_features);
+ printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
+ ms_hyperv.features, ms_hyperv.hints);
}
+
+const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
+ .name = "Microsoft HyperV",
+ .detect = ms_hyperv_platform,
+ .init_platform = ms_hyperv_init_platform,
+};