1 /* 2 * QEMU Xen emulation: Shared/overlay pages support 3 * 4 * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 * 6 * Authors: David Woodhouse <dwmw2@infradead.org> 7 * 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. 10 */ 11 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" 21 22 #include "hw/sysbus.h" 23 #include "hw/xen/xen.h" 24 #include "xen_overlay.h" 25 26 #include "sysemu/kvm.h" 27 #include "sysemu/kvm_xen.h" 28 #include <linux/kvm.h> 29 30 #include "hw/xen/interface/memory.h" 31 32 33 #define TYPE_XEN_OVERLAY "xen-overlay" 34 OBJECT_DECLARE_SIMPLE_TYPE(XenOverlayState, XEN_OVERLAY) 35 36 #define XEN_PAGE_SHIFT 12 37 #define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT) 38 39 struct XenOverlayState { 40 /*< private >*/ 41 SysBusDevice busdev; 42 /*< public >*/ 43 44 MemoryRegion shinfo_mem; 45 void *shinfo_ptr; 46 uint64_t shinfo_gpa; 47 bool long_mode; 48 }; 49 50 struct XenOverlayState *xen_overlay_singleton; 51 52 void xen_overlay_do_map_page(MemoryRegion *page, uint64_t gpa) 53 { 54 /* 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. 60 */ 61 if (memory_region_is_mapped(page)) { 62 if (gpa == INVALID_GPA) { 63 memory_region_del_subregion(get_system_memory(), page); 64 } else { 65 /* Just move it */ 66 memory_region_set_address(page, gpa); 67 } 68 } else if (gpa != INVALID_GPA) { 69 memory_region_add_subregion_overlap(get_system_memory(), gpa, page, 0); 70 } 71 } 72 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) 75 { 76 struct kvm_xen_hvm_attr xa = { 77 .type = KVM_XEN_ATTR_TYPE_SHARED_INFO, 78 .u.shared_info.gfn = gfn, 79 }; 80 81 return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa); 82 } 83 84 85 static void xen_overlay_realize(DeviceState *dev, Error **errp) 86 { 87 XenOverlayState *s = XEN_OVERLAY(dev); 88 89 if (xen_mode != XEN_EMULATE) { 90 error_setg(errp, "Xen overlay page support is for Xen emulation"); 91 return; 92 } 93 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); 97 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); 102 } 103 104 static int xen_overlay_pre_save(void *opaque) 105 { 106 /* 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. 111 */ 112 return xen_sync_long_mode(); 113 } 114 115 static int xen_overlay_post_load(void *opaque, int version_id) 116 { 117 XenOverlayState *s = opaque; 118 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); 122 } 123 if (s->long_mode) { 124 xen_set_long_mode(true); 125 } 126 127 return 0; 128 } 129 130 static bool xen_overlay_is_needed(void *opaque) 131 { 132 return xen_mode == XEN_EMULATE; 133 } 134 135 static const VMStateDescription xen_overlay_vmstate = { 136 .name = "xen_overlay", 137 .version_id = 1, 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() 146 } 147 }; 148 149 static void xen_overlay_reset(DeviceState *dev) 150 { 151 kvm_xen_soft_reset(); 152 } 153 154 static void xen_overlay_class_init(ObjectClass *klass, void *data) 155 { 156 DeviceClass *dc = DEVICE_CLASS(klass); 157 158 device_class_set_legacy_reset(dc, xen_overlay_reset); 159 dc->realize = xen_overlay_realize; 160 dc->vmsd = &xen_overlay_vmstate; 161 } 162 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, 168 }; 169 170 void xen_overlay_create(void) 171 { 172 xen_overlay_singleton = XEN_OVERLAY(sysbus_create_simple(TYPE_XEN_OVERLAY, 173 -1, NULL)); 174 175 /* If xen_domid wasn't explicitly set, at least make sure it isn't zero. */ 176 if (xen_domid == DOMID_QEMU) { 177 xen_domid = 1; 178 }; 179 } 180 181 static void xen_overlay_register_types(void) 182 { 183 type_register_static(&xen_overlay_info); 184 } 185 186 type_init(xen_overlay_register_types) 187 188 int xen_overlay_map_shinfo_page(uint64_t gpa) 189 { 190 XenOverlayState *s = xen_overlay_singleton; 191 int ret; 192 193 if (!s) { 194 return -ENOENT; 195 } 196 197 assert(bql_locked()); 198 199 if (s->shinfo_gpa) { 200 /* If removing shinfo page, turn the kernel magic off first */ 201 ret = xen_overlay_set_be_shinfo(INVALID_GFN); 202 if (ret) { 203 return ret; 204 } 205 } 206 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); 210 if (ret) { 211 return ret; 212 } 213 } 214 s->shinfo_gpa = gpa; 215 216 return 0; 217 } 218 219 void *xen_overlay_get_shinfo_ptr(void) 220 { 221 XenOverlayState *s = xen_overlay_singleton; 222 223 if (!s) { 224 return NULL; 225 } 226 227 return s->shinfo_ptr; 228 } 229 230 int xen_sync_long_mode(void) 231 { 232 int ret; 233 struct kvm_xen_hvm_attr xa = { 234 .type = KVM_XEN_ATTR_TYPE_LONG_MODE, 235 }; 236 237 if (!xen_overlay_singleton) { 238 return -ENOENT; 239 } 240 241 ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_GET_ATTR, &xa); 242 if (!ret) { 243 xen_overlay_singleton->long_mode = xa.u.long_mode; 244 } 245 246 return ret; 247 } 248 249 int xen_set_long_mode(bool long_mode) 250 { 251 int ret; 252 struct kvm_xen_hvm_attr xa = { 253 .type = KVM_XEN_ATTR_TYPE_LONG_MODE, 254 .u.long_mode = long_mode, 255 }; 256 257 if (!xen_overlay_singleton) { 258 return -ENOENT; 259 } 260 261 ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa); 262 if (!ret) { 263 xen_overlay_singleton->long_mode = xa.u.long_mode; 264 } 265 266 return ret; 267 } 268 269 bool xen_is_long_mode(void) 270 { 271 return xen_overlay_singleton && xen_overlay_singleton->long_mode; 272 } 273