0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/init.h>
0025 #include <linux/export.h>
0026 #include <asm/processor.h>
0027 #include <asm/hypervisor.h>
0028
0029 static const __initconst struct hypervisor_x86 * const hypervisors[] =
0030 {
0031 #ifdef CONFIG_XEN_PV
0032 &x86_hyper_xen_pv,
0033 #endif
0034 #ifdef CONFIG_XEN_PVHVM
0035 &x86_hyper_xen_hvm,
0036 #endif
0037 &x86_hyper_vmware,
0038 &x86_hyper_ms_hyperv,
0039 #ifdef CONFIG_KVM_GUEST
0040 &x86_hyper_kvm,
0041 #endif
0042 #ifdef CONFIG_JAILHOUSE_GUEST
0043 &x86_hyper_jailhouse,
0044 #endif
0045 #ifdef CONFIG_ACRN_GUEST
0046 &x86_hyper_acrn,
0047 #endif
0048 };
0049
0050 enum x86_hypervisor_type x86_hyper_type;
0051 EXPORT_SYMBOL(x86_hyper_type);
0052
0053 bool __initdata nopv;
0054 static __init int parse_nopv(char *arg)
0055 {
0056 nopv = true;
0057 return 0;
0058 }
0059 early_param("nopv", parse_nopv);
0060
0061 static inline const struct hypervisor_x86 * __init
0062 detect_hypervisor_vendor(void)
0063 {
0064 const struct hypervisor_x86 *h = NULL, * const *p;
0065 uint32_t pri, max_pri = 0;
0066
0067 for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) {
0068 if (unlikely(nopv) && !(*p)->ignore_nopv)
0069 continue;
0070
0071 pri = (*p)->detect();
0072 if (pri > max_pri) {
0073 max_pri = pri;
0074 h = *p;
0075 }
0076 }
0077
0078 if (h)
0079 pr_info("Hypervisor detected: %s\n", h->name);
0080
0081 return h;
0082 }
0083
0084 static void __init copy_array(const void *src, void *target, unsigned int size)
0085 {
0086 unsigned int i, n = size / sizeof(void *);
0087 const void * const *from = (const void * const *)src;
0088 const void **to = (const void **)target;
0089
0090 for (i = 0; i < n; i++)
0091 if (from[i])
0092 to[i] = from[i];
0093 }
0094
0095 void __init init_hypervisor_platform(void)
0096 {
0097 const struct hypervisor_x86 *h;
0098
0099 h = detect_hypervisor_vendor();
0100
0101 if (!h)
0102 return;
0103
0104 copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
0105 copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime));
0106
0107 x86_hyper_type = h->type;
0108 x86_init.hyper.init_platform();
0109 }