diff options
Diffstat (limited to 'arch/x86/kernel/cpu/hypervisor.c')
-rw-r--r-- | arch/x86/kernel/cpu/hypervisor.c | 56 |
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 | ||
29 | static inline void __cpuinit | 27 | /* |
30 | detect_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 | */ | ||
32 | static 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 | ||
40 | static inline void __cpuinit | 38 | const struct hypervisor_x86 *x86_hyper; |
41 | hypervisor_set_feature_bits(struct cpuinfo_x86 *c) | 39 | |
40 | static inline void __init | ||
41 | detect_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 | ||
50 | void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) | 55 | void __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 | ||
56 | void __init init_hypervisor_platform(void) | 61 | void __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 | } |