aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/hypervisor.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/hypervisor.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/hypervisor.c')
-rw-r--r--arch/x86/kernel/cpu/hypervisor.c56
1 files changed, 34 insertions, 22 deletions
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index de3f4e0ce8eb..87381759d3cb 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -22,40 +22,52 @@
22 */ 22 */
23 23
24#include <asm/processor.h> 24#include <asm/processor.h>
25#include <asm/vmware.h>
26#include <asm/mshyperv.h>
27#include <asm/hypervisor.h> 25#include <asm/hypervisor.h>
28 26
29static inline void __cpuinit 27/*
30detect_hypervisor_vendor(struct cpuinfo_x86 *c) 28 * Hypervisor detect order. This is specified explicitly here because
29 * some hypervisors might implement compatibility modes for other
30 * hypervisors and therefore need to be detected in specific sequence.
31 */
32static const __initconst struct hypervisor_x86 * const hypervisors[] =
31{ 33{
32 if (vmware_platform()) 34 &x86_hyper_vmware,
33 c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE; 35 &x86_hyper_ms_hyperv,
34 else if (ms_hyperv_platform()) 36};
35 c->x86_hyper_vendor = X86_HYPER_VENDOR_MSFT;
36 else
37 c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE;
38}
39 37
40static inline void __cpuinit 38const struct hypervisor_x86 *x86_hyper;
41hypervisor_set_feature_bits(struct cpuinfo_x86 *c) 39
40static inline void __init
41detect_hypervisor_vendor(void)
42{ 42{
43 if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) 43 const struct hypervisor_x86 *h, * const *p;
44 vmware_set_feature_bits(c); 44
45 else if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_MSFT) 45 for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) {
46 ms_hyperv_set_feature_bits(c); 46 h = *p;
47 return; 47 if (h->detect()) {
48 x86_hyper = h;
49 printk(KERN_INFO "Hypervisor detected: %s\n", h->name);
50 break;
51 }
52 }
48} 53}
49 54
50void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) 55void __cpuinit init_hypervisor(struct cpuinfo_x86 *c)
51{ 56{
52 detect_hypervisor_vendor(c); 57 if (x86_hyper && x86_hyper->set_cpu_features)
53 hypervisor_set_feature_bits(c); 58 x86_hyper->set_cpu_features(c);
54} 59}
55 60
56void __init init_hypervisor_platform(void) 61void __init init_hypervisor_platform(void)
57{ 62{
63
64 detect_hypervisor_vendor();
65
66 if (!x86_hyper)
67 return;
68
58 init_hypervisor(&boot_cpu_data); 69 init_hypervisor(&boot_cpu_data);
59 if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) 70
60 vmware_platform_setup(); 71 if (x86_hyper->init_platform)
72 x86_hyper->init_platform();
61} 73}