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