aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/mshyperv.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-05-07 19:57:28 -0400
committerH. Peter Anvin <hpa@zytor.com>2010-05-07 20:13:04 -0400
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 @@
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <asm/processor.h> 14#include <asm/processor.h>
15#include <asm/hypervisor.h>
15#include <asm/hyperv.h> 16#include <asm/hyperv.h>
16#include <asm/mshyperv.h> 17#include <asm/mshyperv.h>
17 18
19struct ms_hyperv_info ms_hyperv;
18 20
19int ms_hyperv_platform(void) 21static bool __init ms_hyperv_platform(void)
20{ 22{
21 u32 eax, ebx, ecx, edx; 23 u32 eax;
22 char hyp_signature[13]; 24 u32 hyp_signature[3];
23 25
24 cpuid(1, &eax, &ebx, &ecx, &edx); 26 if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
25 if (!(ecx & HYPERV_HYPERVISOR_PRESENT_BIT)) 27 return false;
26 return 0;
27 28
28 cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, &eax, &ebx, &ecx, &edx); 29 cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
29 *(u32 *)(hyp_signature + 0) = ebx; 30 &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
30 *(u32 *)(hyp_signature + 4) = ecx;
31 *(u32 *)(hyp_signature + 8) = edx;
32 31
33 if ((eax < HYPERV_CPUID_MIN) || (memcmp("Microsoft Hv", hyp_signature, 12))) 32 return eax >= HYPERV_CPUID_MIN &&
34 return 0; 33 eax <= HYPERV_CPUID_MAX &&
35 return 1; 34 !memcmp("Microsoft Hv", hyp_signature, 12);
36} 35}
37 36
38void __cpuinit ms_hyperv_set_feature_bits(struct cpuinfo_x86 *c) 37static void __init ms_hyperv_init_platform(void)
39{ 38{
40 u32 eax, ebx, ecx, edx;
41
42 c->x86_hyper_features = 0;
43 /* 39 /*
44 * Extract the features, recommendations etc. 40 * Extract the features and hints
45 * The first 9 bits will be used to track hypervisor features.
46 * The next 6 bits will be used to track the hypervisor
47 * recommendations.
48 */ 41 */
49 cpuid(HYPERV_CPUID_FEATURES, &eax, &ebx, &ecx, &edx); 42 ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
50 c->x86_hyper_features |= (eax & 0x1ff); 43 ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
51 44
52 cpuid(HYPERV_CPUID_ENLIGHTMENT_INFO, &eax, &ebx, &ecx, &edx); 45 printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
53 c->x86_hyper_features |= ((eax & 0x3f) << 9); 46 ms_hyperv.features, ms_hyperv.hints);
54 printk(KERN_INFO "Detected HyperV with features: %x\n",
55 c->x86_hyper_features);
56} 47}
48
49const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
50 .name = "Microsoft HyperV",
51 .detect = ms_hyperv_platform,
52 .init_platform = ms_hyperv_init_platform,
53};