1 | /* |
2 | * Common hypervisor code |
3 | * |
4 | * Copyright (C) 2008, VMware, Inc. |
5 | * Author : Alok N Kataria <akataria@vmware.com> |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, but |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or |
15 | * NON INFRINGEMENT. See the GNU General Public License for more |
16 | * details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
21 | * |
22 | */ |
23 | |
24 | #include <linux/init.h> |
25 | #include <linux/export.h> |
26 | #include <asm/processor.h> |
27 | #include <asm/hypervisor.h> |
28 | |
29 | static const __initconst struct hypervisor_x86 * const hypervisors[] = |
30 | { |
31 | #ifdef CONFIG_XEN_PV |
32 | &x86_hyper_xen_pv, |
33 | #endif |
34 | #ifdef CONFIG_XEN_PVHVM |
35 | &x86_hyper_xen_hvm, |
36 | #endif |
37 | &x86_hyper_vmware, |
38 | &x86_hyper_ms_hyperv, |
39 | #ifdef CONFIG_KVM_GUEST |
40 | &x86_hyper_kvm, |
41 | #endif |
42 | #ifdef CONFIG_JAILHOUSE_GUEST |
43 | &x86_hyper_jailhouse, |
44 | #endif |
45 | #ifdef CONFIG_ACRN_GUEST |
46 | &x86_hyper_acrn, |
47 | #endif |
48 | }; |
49 | |
50 | enum x86_hypervisor_type x86_hyper_type; |
51 | EXPORT_SYMBOL(x86_hyper_type); |
52 | |
53 | bool __initdata nopv; |
54 | static __init int parse_nopv(char *arg) |
55 | { |
56 | nopv = true; |
57 | return 0; |
58 | } |
59 | early_param("nopv" , parse_nopv); |
60 | |
61 | static inline const struct hypervisor_x86 * __init |
62 | detect_hypervisor_vendor(void) |
63 | { |
64 | const struct hypervisor_x86 *h = NULL, * const *p; |
65 | uint32_t pri, max_pri = 0; |
66 | |
67 | for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) { |
68 | if (unlikely(nopv) && !(*p)->ignore_nopv) |
69 | continue; |
70 | |
71 | pri = (*p)->detect(); |
72 | if (pri > max_pri) { |
73 | max_pri = pri; |
74 | h = *p; |
75 | } |
76 | } |
77 | |
78 | if (h) |
79 | pr_info("Hypervisor detected: %s\n" , h->name); |
80 | |
81 | return h; |
82 | } |
83 | |
84 | static void __init copy_array(const void *src, void *target, unsigned int size) |
85 | { |
86 | unsigned int i, n = size / sizeof(void *); |
87 | const void * const *from = (const void * const *)src; |
88 | const void **to = (const void **)target; |
89 | |
90 | for (i = 0; i < n; i++) |
91 | if (from[i]) |
92 | to[i] = from[i]; |
93 | } |
94 | |
95 | void __init init_hypervisor_platform(void) |
96 | { |
97 | const struct hypervisor_x86 *h; |
98 | |
99 | h = detect_hypervisor_vendor(); |
100 | |
101 | if (!h) |
102 | return; |
103 | |
104 | copy_array(src: &h->init, target: &x86_init.hyper, size: sizeof(h->init)); |
105 | copy_array(src: &h->runtime, target: &x86_platform.hyper, size: sizeof(h->runtime)); |
106 | |
107 | x86_hyper_type = h->type; |
108 | x86_init.hyper.init_platform(); |
109 | } |
110 | |