2 * QEMU Xen emulation: Shared/overlay pages support
4 * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 * Authors: David Woodhouse <dwmw2@infradead.org>
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
12 #include "qemu/osdep.h"
13 #include "qemu/host-utils.h"
14 #include "qemu/module.h"
15 #include "qemu/main-loop.h"
16 #include "qapi/error.h"
17 #include "qom/object.h"
18 #include "exec/target_page.h"
19 #include "exec/address-spaces.h"
20 #include "migration/vmstate.h"
22 #include "hw/sysbus.h"
23 #include "hw/xen/xen.h"
24 #include "xen_overlay.h"
26 #include "sysemu/kvm.h"
27 #include "sysemu/kvm_xen.h"
28 #include <linux/kvm.h>
30 #include "hw/xen/interface/memory.h"
33 #define TYPE_XEN_OVERLAY "xen-overlay"
34 OBJECT_DECLARE_SIMPLE_TYPE(XenOverlayState
, XEN_OVERLAY
)
36 #define XEN_PAGE_SHIFT 12
37 #define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT)
39 struct XenOverlayState
{
44 MemoryRegion shinfo_mem
;
50 struct XenOverlayState
*xen_overlay_singleton
;
52 void xen_overlay_do_map_page(MemoryRegion
*page
, uint64_t gpa
)
55 * Xen allows guests to map the same page as many times as it likes
56 * into guest physical frames. We don't, because it would be hard
57 * to track and restore them all. One mapping of each page is
58 * perfectly sufficient for all known guests... and we've tested
59 * that theory on a few now in other implementations. dwmw2.
61 if (memory_region_is_mapped(page
)) {
62 if (gpa
== INVALID_GPA
) {
63 memory_region_del_subregion(get_system_memory(), page
);
66 memory_region_set_address(page
, gpa
);
68 } else if (gpa
!= INVALID_GPA
) {
69 memory_region_add_subregion_overlap(get_system_memory(), gpa
, page
, 0);
73 /* KVM is the only existing back end for now. Let's not overengineer it yet. */
74 static int xen_overlay_set_be_shinfo(uint64_t gfn
)
76 struct kvm_xen_hvm_attr xa
= {
77 .type
= KVM_XEN_ATTR_TYPE_SHARED_INFO
,
78 .u
.shared_info
.gfn
= gfn
,
81 return kvm_vm_ioctl(kvm_state
, KVM_XEN_HVM_SET_ATTR
, &xa
);
85 static void xen_overlay_realize(DeviceState
*dev
, Error
**errp
)
87 XenOverlayState
*s
= XEN_OVERLAY(dev
);
89 if (xen_mode
!= XEN_EMULATE
) {
90 error_setg(errp
, "Xen overlay page support is for Xen emulation");
94 memory_region_init_ram(&s
->shinfo_mem
, OBJECT(dev
), "xen:shared_info",
95 XEN_PAGE_SIZE
, &error_abort
);
96 memory_region_set_enabled(&s
->shinfo_mem
, true);
98 s
->shinfo_ptr
= memory_region_get_ram_ptr(&s
->shinfo_mem
);
99 s
->shinfo_gpa
= INVALID_GPA
;
100 s
->long_mode
= false;
101 memset(s
->shinfo_ptr
, 0, XEN_PAGE_SIZE
);
104 static int xen_overlay_pre_save(void *opaque
)
107 * Fetch the kernel's idea of long_mode to avoid the race condition
108 * where the guest has set the hypercall page up in 64-bit mode but
109 * not yet made a hypercall by the time migration happens, so qemu
110 * hasn't yet noticed.
112 return xen_sync_long_mode();
115 static int xen_overlay_post_load(void *opaque
, int version_id
)
117 XenOverlayState
*s
= opaque
;
119 if (s
->shinfo_gpa
!= INVALID_GPA
) {
120 xen_overlay_do_map_page(&s
->shinfo_mem
, s
->shinfo_gpa
);
121 xen_overlay_set_be_shinfo(s
->shinfo_gpa
>> XEN_PAGE_SHIFT
);
124 xen_set_long_mode(true);
130 static bool xen_overlay_is_needed(void *opaque
)
132 return xen_mode
== XEN_EMULATE
;
135 static const VMStateDescription xen_overlay_vmstate
= {
136 .name
= "xen_overlay",
138 .minimum_version_id
= 1,
139 .needed
= xen_overlay_is_needed
,
140 .pre_save
= xen_overlay_pre_save
,
141 .post_load
= xen_overlay_post_load
,
142 .fields
= (const VMStateField
[]) {
143 VMSTATE_UINT64(shinfo_gpa
, XenOverlayState
),
144 VMSTATE_BOOL(long_mode
, XenOverlayState
),
145 VMSTATE_END_OF_LIST()
149 static void xen_overlay_reset(DeviceState
*dev
)
151 kvm_xen_soft_reset();
154 static void xen_overlay_class_init(ObjectClass
*klass
, void *data
)
156 DeviceClass
*dc
= DEVICE_CLASS(klass
);
158 device_class_set_legacy_reset(dc
, xen_overlay_reset
);
159 dc
->realize
= xen_overlay_realize
;
160 dc
->vmsd
= &xen_overlay_vmstate
;
163 static const TypeInfo xen_overlay_info
= {
164 .name
= TYPE_XEN_OVERLAY
,
165 .parent
= TYPE_SYS_BUS_DEVICE
,
166 .instance_size
= sizeof(XenOverlayState
),
167 .class_init
= xen_overlay_class_init
,
170 void xen_overlay_create(void)
172 xen_overlay_singleton
= XEN_OVERLAY(sysbus_create_simple(TYPE_XEN_OVERLAY
,
175 /* If xen_domid wasn't explicitly set, at least make sure it isn't zero. */
176 if (xen_domid
== DOMID_QEMU
) {
181 static void xen_overlay_register_types(void)
183 type_register_static(&xen_overlay_info
);
186 type_init(xen_overlay_register_types
)
188 int xen_overlay_map_shinfo_page(uint64_t gpa
)
190 XenOverlayState
*s
= xen_overlay_singleton
;
197 assert(bql_locked());
200 /* If removing shinfo page, turn the kernel magic off first */
201 ret
= xen_overlay_set_be_shinfo(INVALID_GFN
);
207 xen_overlay_do_map_page(&s
->shinfo_mem
, gpa
);
208 if (gpa
!= INVALID_GPA
) {
209 ret
= xen_overlay_set_be_shinfo(gpa
>> XEN_PAGE_SHIFT
);
219 void *xen_overlay_get_shinfo_ptr(void)
221 XenOverlayState
*s
= xen_overlay_singleton
;
227 return s
->shinfo_ptr
;
230 int xen_sync_long_mode(void)
233 struct kvm_xen_hvm_attr xa
= {
234 .type
= KVM_XEN_ATTR_TYPE_LONG_MODE
,
237 if (!xen_overlay_singleton
) {
241 ret
= kvm_vm_ioctl(kvm_state
, KVM_XEN_HVM_GET_ATTR
, &xa
);
243 xen_overlay_singleton
->long_mode
= xa
.u
.long_mode
;
249 int xen_set_long_mode(bool long_mode
)
252 struct kvm_xen_hvm_attr xa
= {
253 .type
= KVM_XEN_ATTR_TYPE_LONG_MODE
,
254 .u
.long_mode
= long_mode
,
257 if (!xen_overlay_singleton
) {
261 ret
= kvm_vm_ioctl(kvm_state
, KVM_XEN_HVM_SET_ATTR
, &xa
);
263 xen_overlay_singleton
->long_mode
= xa
.u
.long_mode
;
269 bool xen_is_long_mode(void)
271 return xen_overlay_singleton
&& xen_overlay_singleton
->long_mode
;