diff options
Diffstat (limited to 'arch/x86/kernel/cpu/hypervisor.c')
-rw-r--r-- | arch/x86/kernel/cpu/hypervisor.c | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 4fa90006ac68..bea8d3e24f50 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c | |||
@@ -26,6 +26,12 @@ | |||
26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
27 | #include <asm/hypervisor.h> | 27 | #include <asm/hypervisor.h> |
28 | 28 | ||
29 | extern const struct hypervisor_x86 x86_hyper_vmware; | ||
30 | extern const struct hypervisor_x86 x86_hyper_ms_hyperv; | ||
31 | extern const struct hypervisor_x86 x86_hyper_xen_pv; | ||
32 | extern const struct hypervisor_x86 x86_hyper_xen_hvm; | ||
33 | extern const struct hypervisor_x86 x86_hyper_kvm; | ||
34 | |||
29 | static const __initconst struct hypervisor_x86 * const hypervisors[] = | 35 | static const __initconst struct hypervisor_x86 * const hypervisors[] = |
30 | { | 36 | { |
31 | #ifdef CONFIG_XEN_PV | 37 | #ifdef CONFIG_XEN_PV |
@@ -41,54 +47,52 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] = | |||
41 | #endif | 47 | #endif |
42 | }; | 48 | }; |
43 | 49 | ||
44 | const struct hypervisor_x86 *x86_hyper; | 50 | enum x86_hypervisor_type x86_hyper_type; |
45 | EXPORT_SYMBOL(x86_hyper); | 51 | EXPORT_SYMBOL(x86_hyper_type); |
46 | 52 | ||
47 | static inline void __init | 53 | static inline const struct hypervisor_x86 * __init |
48 | detect_hypervisor_vendor(void) | 54 | detect_hypervisor_vendor(void) |
49 | { | 55 | { |
50 | const struct hypervisor_x86 *h, * const *p; | 56 | const struct hypervisor_x86 *h = NULL, * const *p; |
51 | uint32_t pri, max_pri = 0; | 57 | uint32_t pri, max_pri = 0; |
52 | 58 | ||
53 | for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) { | 59 | for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) { |
54 | h = *p; | 60 | pri = (*p)->detect(); |
55 | pri = h->detect(); | 61 | if (pri > max_pri) { |
56 | if (pri != 0 && pri > max_pri) { | ||
57 | max_pri = pri; | 62 | max_pri = pri; |
58 | x86_hyper = h; | 63 | h = *p; |
59 | } | 64 | } |
60 | } | 65 | } |
61 | 66 | ||
62 | if (max_pri) | 67 | if (h) |
63 | pr_info("Hypervisor detected: %s\n", x86_hyper->name); | 68 | pr_info("Hypervisor detected: %s\n", h->name); |
69 | |||
70 | return h; | ||
64 | } | 71 | } |
65 | 72 | ||
66 | void __init init_hypervisor_platform(void) | 73 | static void __init copy_array(const void *src, void *target, unsigned int size) |
67 | { | 74 | { |
75 | unsigned int i, n = size / sizeof(void *); | ||
76 | const void * const *from = (const void * const *)src; | ||
77 | const void **to = (const void **)target; | ||
68 | 78 | ||
69 | detect_hypervisor_vendor(); | 79 | for (i = 0; i < n; i++) |
70 | 80 | if (from[i]) | |
71 | if (!x86_hyper) | 81 | to[i] = from[i]; |
72 | return; | ||
73 | |||
74 | if (x86_hyper->init_platform) | ||
75 | x86_hyper->init_platform(); | ||
76 | } | 82 | } |
77 | 83 | ||
78 | bool __init hypervisor_x2apic_available(void) | 84 | void __init init_hypervisor_platform(void) |
79 | { | 85 | { |
80 | return x86_hyper && | 86 | const struct hypervisor_x86 *h; |
81 | x86_hyper->x2apic_available && | ||
82 | x86_hyper->x2apic_available(); | ||
83 | } | ||
84 | 87 | ||
85 | void hypervisor_pin_vcpu(int cpu) | 88 | h = detect_hypervisor_vendor(); |
86 | { | 89 | |
87 | if (!x86_hyper) | 90 | if (!h) |
88 | return; | 91 | return; |
89 | 92 | ||
90 | if (x86_hyper->pin_vcpu) | 93 | copy_array(&h->init, &x86_init.hyper, sizeof(h->init)); |
91 | x86_hyper->pin_vcpu(cpu); | 94 | copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime)); |
92 | else | 95 | |
93 | WARN_ONCE(1, "vcpu pinning requested but not supported!\n"); | 96 | x86_hyper_type = h->type; |
97 | x86_init.hyper.init_platform(); | ||
94 | } | 98 | } |