blob: 553bfbfc3a1b5ae28ac688afb646296d9dcff7e7 [file] [log] [blame]
Alok Kataria88b094f2008-10-27 10:41:46 -07001/*
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
Paul Gortmaker186f4362016-07-13 20:18:56 -040024#include <linux/init.h>
25#include <linux/export.h>
Alok Kataria88b094f2008-10-27 10:41:46 -070026#include <asm/processor.h>
Hannes Eder4e42ebd2008-11-21 22:56:17 +010027#include <asm/hypervisor.h>
Alok Kataria88b094f2008-10-27 10:41:46 -070028
H. Peter Anvine08cae42010-05-07 16:57:28 -070029static const __initconst struct hypervisor_x86 * const hypervisors[] =
Alok Kataria88b094f2008-10-27 10:41:46 -070030{
Vitaly Kuznetsov5e57f1d2017-03-14 18:35:38 +010031#ifdef CONFIG_XEN_PV
Vitaly Kuznetsov0991d222017-03-14 18:35:36 +010032 &x86_hyper_xen_pv,
Vitaly Kuznetsov5e57f1d2017-03-14 18:35:38 +010033#endif
34#ifdef CONFIG_XEN_PVHVM
Vitaly Kuznetsov0991d222017-03-14 18:35:36 +010035 &x86_hyper_xen_hvm,
Jeremy Fitzhardingeb43275d2010-07-26 10:38:45 -070036#endif
Anupam Chanda24a42ba2011-07-08 11:42:50 -070037 &x86_hyper_vmware,
38 &x86_hyper_ms_hyperv,
Avi Kivityd63d3e62012-07-18 11:48:50 +030039#ifdef CONFIG_KVM_GUEST
Prarit Bhargavafc733732012-07-06 13:47:39 -040040 &x86_hyper_kvm,
Avi Kivityd63d3e62012-07-18 11:48:50 +030041#endif
Jan Kiszka4a362602017-11-27 09:11:46 +010042#ifdef CONFIG_JAILHOUSE_GUEST
43 &x86_hyper_jailhouse,
44#endif
Zhao Yakuiec7972c2019-04-30 11:45:24 +080045#ifdef CONFIG_ACRN_GUEST
46 &x86_hyper_acrn,
47#endif
H. Peter Anvine08cae42010-05-07 16:57:28 -070048};
Alok Kataria88b094f2008-10-27 10:41:46 -070049
Juergen Gross03b2a322017-11-09 14:27:36 +010050enum x86_hypervisor_type x86_hyper_type;
51EXPORT_SYMBOL(x86_hyper_type);
H. Peter Anvine08cae42010-05-07 16:57:28 -070052
Zhenzhong Duan30978342019-07-11 20:02:09 +080053bool __initdata nopv;
54static __init int parse_nopv(char *arg)
55{
56 nopv = true;
57 return 0;
58}
59early_param("nopv", parse_nopv);
60
Juergen Grossf72e38e2017-11-09 14:27:35 +010061static inline const struct hypervisor_x86 * __init
H. Peter Anvine08cae42010-05-07 16:57:28 -070062detect_hypervisor_vendor(void)
Alok Katariaeca0cd02008-10-31 12:01:58 -070063{
Juergen Grossf72e38e2017-11-09 14:27:35 +010064 const struct hypervisor_x86 *h = NULL, * const *p;
Jason Wang9df56f12013-07-25 16:54:35 +080065 uint32_t pri, max_pri = 0;
H. Peter Anvine08cae42010-05-07 16:57:28 -070066
67 for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) {
Zhenzhong Duan30978342019-07-11 20:02:09 +080068 if (unlikely(nopv) && !(*p)->ignore_nopv)
69 continue;
70
Juergen Grossf72e38e2017-11-09 14:27:35 +010071 pri = (*p)->detect();
72 if (pri > max_pri) {
Jason Wang9df56f12013-07-25 16:54:35 +080073 max_pri = pri;
Juergen Grossf72e38e2017-11-09 14:27:35 +010074 h = *p;
H. Peter Anvine08cae42010-05-07 16:57:28 -070075 }
76 }
Jason Wang9df56f12013-07-25 16:54:35 +080077
Juergen Grossf72e38e2017-11-09 14:27:35 +010078 if (h)
79 pr_info("Hypervisor detected: %s\n", h->name);
80
81 return h;
82}
83
84static 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];
Alok Katariaeca0cd02008-10-31 12:01:58 -070093}
94
Thomas Gleixner2d826402009-08-20 17:06:25 +020095void __init init_hypervisor_platform(void)
96{
Juergen Grossf72e38e2017-11-09 14:27:35 +010097 const struct hypervisor_x86 *h;
H. Peter Anvine08cae42010-05-07 16:57:28 -070098
Juergen Grossf72e38e2017-11-09 14:27:35 +010099 h = detect_hypervisor_vendor();
H. Peter Anvine08cae42010-05-07 16:57:28 -0700100
Juergen Grossf72e38e2017-11-09 14:27:35 +0100101 if (!h)
H. Peter Anvine08cae42010-05-07 16:57:28 -0700102 return;
103
Juergen Grossf72e38e2017-11-09 14:27:35 +0100104 copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
105 copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime));
Alok N Kataria4cca6ea2013-01-17 15:44:42 -0800106
Juergen Gross03b2a322017-11-09 14:27:36 +0100107 x86_hyper_type = h->type;
Juergen Grossf72e38e2017-11-09 14:27:35 +0100108 x86_init.hyper.init_platform();
Juergen Gross47ae4b02016-08-29 08:48:43 +0200109}