aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaran Wilson <maran.wilson@oracle.com>2018-12-10 14:09:35 -0500
committerBoris Ostrovsky <boris.ostrovsky@oracle.com>2018-12-13 13:41:49 -0500
commit716ff017a39e552f47de7667ba934d0547ba7535 (patch)
tree8f9e1f7165dde6f8db3f4f5358c5296d94eeee44
parentd907be2b5b042536d15687ac0a86f27c8c9aebd4 (diff)
KVM: x86: Allow Qemu/KVM to use PVH entry point
For certain applications it is desirable to rapidly boot a KVM virtual machine. In cases where legacy hardware and software support within the guest is not needed, Qemu should be able to boot directly into the uncompressed Linux kernel binary without the need to run firmware. There already exists an ABI to allow this for Xen PVH guests and the ABI is supported by Linux and FreeBSD: https://xenbits.xen.org/docs/unstable/misc/pvh.html This patch enables Qemu to use that same entry point for booting KVM guests. Signed-off-by: Maran Wilson <maran.wilson@oracle.com> Suggested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Suggested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Reviewed-by: Juergen Gross <jgross@suse.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-rw-r--r--arch/x86/Kbuild2
-rw-r--r--arch/x86/platform/pvh/Makefile4
-rw-r--r--arch/x86/platform/pvh/enlighten.c42
3 files changed, 34 insertions, 14 deletions
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
index 2089e4414300..c625f57472f7 100644
--- a/arch/x86/Kbuild
+++ b/arch/x86/Kbuild
@@ -7,7 +7,7 @@ obj-$(CONFIG_KVM) += kvm/
7# Xen paravirtualization support 7# Xen paravirtualization support
8obj-$(CONFIG_XEN) += xen/ 8obj-$(CONFIG_XEN) += xen/
9 9
10obj-$(CONFIG_XEN_PVH) += platform/pvh/ 10obj-$(CONFIG_PVH) += platform/pvh/
11 11
12# Hyper-V paravirtualization support 12# Hyper-V paravirtualization support
13obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/ 13obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/
diff --git a/arch/x86/platform/pvh/Makefile b/arch/x86/platform/pvh/Makefile
index 9fd25efcd2a3..5dec5067c9fb 100644
--- a/arch/x86/platform/pvh/Makefile
+++ b/arch/x86/platform/pvh/Makefile
@@ -1,5 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2OBJECT_FILES_NON_STANDARD_head.o := y 2OBJECT_FILES_NON_STANDARD_head.o := y
3 3
4obj-$(CONFIG_XEN_PVH) += enlighten.o 4obj-$(CONFIG_PVH) += enlighten.o
5obj-$(CONFIG_XEN_PVH) += head.o 5obj-$(CONFIG_PVH) += head.o
diff --git a/arch/x86/platform/pvh/enlighten.c b/arch/x86/platform/pvh/enlighten.c
index 8040b3fbf545..62f5c7045944 100644
--- a/arch/x86/platform/pvh/enlighten.c
+++ b/arch/x86/platform/pvh/enlighten.c
@@ -8,6 +8,8 @@
8#include <asm/e820/api.h> 8#include <asm/e820/api.h>
9#include <asm/x86_init.h> 9#include <asm/x86_init.h>
10 10
11#include <asm/xen/interface.h>
12
11#include <xen/xen.h> 13#include <xen/xen.h>
12#include <xen/interface/hvm/start_info.h> 14#include <xen/interface/hvm/start_info.h>
13 15
@@ -40,11 +42,28 @@ void __init __weak mem_map_via_hcall(struct boot_params *ptr __maybe_unused)
40 BUG(); 42 BUG();
41} 43}
42 44
43static void __init init_pvh_bootparams(void) 45static void __init init_pvh_bootparams(bool xen_guest)
44{ 46{
45 memset(&pvh_bootparams, 0, sizeof(pvh_bootparams)); 47 memset(&pvh_bootparams, 0, sizeof(pvh_bootparams));
46 48
47 mem_map_via_hcall(&pvh_bootparams); 49 if ((pvh_start_info.version > 0) && (pvh_start_info.memmap_entries)) {
50 struct hvm_memmap_table_entry *ep;
51 int i;
52
53 ep = __va(pvh_start_info.memmap_paddr);
54 pvh_bootparams.e820_entries = pvh_start_info.memmap_entries;
55
56 for (i = 0; i < pvh_bootparams.e820_entries ; i++, ep++) {
57 pvh_bootparams.e820_table[i].addr = ep->addr;
58 pvh_bootparams.e820_table[i].size = ep->size;
59 pvh_bootparams.e820_table[i].type = ep->type;
60 }
61 } else if (xen_guest) {
62 mem_map_via_hcall(&pvh_bootparams);
63 } else {
64 /* Non-xen guests are not supported by version 0 */
65 BUG();
66 }
48 67
49 if (pvh_bootparams.e820_entries < E820_MAX_ENTRIES_ZEROPAGE - 1) { 68 if (pvh_bootparams.e820_entries < E820_MAX_ENTRIES_ZEROPAGE - 1) {
50 pvh_bootparams.e820_table[pvh_bootparams.e820_entries].addr = 69 pvh_bootparams.e820_table[pvh_bootparams.e820_entries].addr =
@@ -75,7 +94,7 @@ static void __init init_pvh_bootparams(void)
75 * environment (i.e. hardware_subarch 0). 94 * environment (i.e. hardware_subarch 0).
76 */ 95 */
77 pvh_bootparams.hdr.version = (2 << 8) | 12; 96 pvh_bootparams.hdr.version = (2 << 8) | 12;
78 pvh_bootparams.hdr.type_of_loader = (9 << 4) | 0; /* Xen loader */ 97 pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0;
79 98
80 x86_init.acpi.get_root_pointer = pvh_get_root_pointer; 99 x86_init.acpi.get_root_pointer = pvh_get_root_pointer;
81} 100}
@@ -90,13 +109,10 @@ void __init __weak xen_pvh_init(void)
90 BUG(); 109 BUG();
91} 110}
92 111
93/* 112static void hypervisor_specific_init(bool xen_guest)
94 * When we add support for other hypervisors like Qemu/KVM, this routine can
95 * selectively invoke the appropriate initialization based on guest type.
96 */
97static void hypervisor_specific_init(void)
98{ 113{
99 xen_pvh_init(); 114 if (xen_guest)
115 xen_pvh_init();
100} 116}
101 117
102/* 118/*
@@ -105,13 +121,17 @@ static void hypervisor_specific_init(void)
105 */ 121 */
106void __init xen_prepare_pvh(void) 122void __init xen_prepare_pvh(void)
107{ 123{
124
125 u32 msr = xen_cpuid_base();
126 bool xen_guest = !!msr;
127
108 if (pvh_start_info.magic != XEN_HVM_START_MAGIC_VALUE) { 128 if (pvh_start_info.magic != XEN_HVM_START_MAGIC_VALUE) {
109 xen_raw_printk("Error: Unexpected magic value (0x%08x)\n", 129 xen_raw_printk("Error: Unexpected magic value (0x%08x)\n",
110 pvh_start_info.magic); 130 pvh_start_info.magic);
111 BUG(); 131 BUG();
112 } 132 }
113 133
114 hypervisor_specific_init(); 134 hypervisor_specific_init(xen_guest);
115 135
116 init_pvh_bootparams(); 136 init_pvh_bootparams(xen_guest);
117} 137}