From: "Edgar E. Iglesias" <[email protected]> Add a machine property to enable/disable the mapcache. Default it to enabled for backwards compatibility.
Signed-off-by: Edgar E. Iglesias <[email protected]> --- hw/xen/xen-pvh-common.c | 133 +++++++++++++++++++++++++++++--- include/hw/xen/xen-pvh-common.h | 2 + 2 files changed, 124 insertions(+), 11 deletions(-) diff --git a/hw/xen/xen-pvh-common.c b/hw/xen/xen-pvh-common.c index 4fade017bb..cca37202ff 100644 --- a/hw/xen/xen-pvh-common.c +++ b/hw/xen/xen-pvh-common.c @@ -29,6 +29,69 @@ static const MemoryListener xen_memory_listener = { .priority = MEMORY_LISTENER_PRIORITY_ACCEL, }; +/* + * Map foreign RAM in bounded chunks so we don't build a PFN array for the + * entire guest size (which can be huge for large guests). We reserve a VA + * range once and then MAP_FIXED each chunk into place. + */ +#define XEN_PVH_MAP_CHUNK_PAGES 65535 + +static void *xen_map_guest_ram(XenPVHMachineState *s, + uint64_t addr, uint64_t size) +{ + size_t total_pages = size >> XC_PAGE_SHIFT; + size_t chunk_pages = MIN(XEN_PVH_MAP_CHUNK_PAGES, total_pages); + g_autofree xen_pfn_t *pfns = NULL; + void *base = NULL; + size_t offset; + + if (!total_pages) { + goto done; + } + + base = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (base == MAP_FAILED) { + base = NULL; + goto done; + } + + pfns = g_new0(xen_pfn_t, chunk_pages); + if (!pfns) { + munmap(base, size); + base = NULL; + goto done; + } + + for (offset = 0; offset < total_pages; offset += chunk_pages) { + size_t num_pages = MIN(chunk_pages, total_pages - offset); + void *mapped; + size_t i; + + for (i = 0; i < num_pages; i++) { + pfns[i] = (addr >> XC_PAGE_SHIFT) + offset + i; + } + + mapped = xenforeignmemory_map2( + xen_fmem, xen_domid, + (uint8_t *)base + (offset << XC_PAGE_SHIFT), + PROT_READ | PROT_WRITE, MAP_FIXED, + num_pages, pfns, NULL); + if (!mapped) { + munmap(base, size); + base = NULL; + goto done; + } + } +done: + if (!base) { + /* We can't recover from this. */ + error_report("FATAL: Failed to foreign-map %" PRIx64 " - %" PRIx64, + addr, addr + size); + exit(EXIT_FAILURE); + } + return base; +} + static void xen_pvh_init_ram(XenPVHMachineState *s, MemoryRegion *sysmem) { @@ -45,22 +108,42 @@ static void xen_pvh_init_ram(XenPVHMachineState *s, block_len = s->cfg.ram_high.base + ram_size[1]; } - memory_region_init_ram(&xen_memory, NULL, "xen.ram", block_len, - &error_fatal); + if (s->cfg.mapcache) { + memory_region_init_ram(&xen_memory, NULL, "xen.ram", + block_len, &error_fatal); + memory_region_init_alias(&s->ram.low, NULL, "xen.ram.lo", &xen_memory, + s->cfg.ram_low.base, ram_size[0]); + if (ram_size[1] > 0) { + memory_region_init_alias(&s->ram.high, NULL, "xen.ram.hi", + &xen_memory, + s->cfg.ram_high.base, ram_size[1]); + } + } else { + void *p; + + p = xen_map_guest_ram(s, s->cfg.ram_low.base, ram_size[0]); + memory_region_init_ram_ptr(&s->ram.low, NULL, "xen.ram.lo", + ram_size[0], p); + if (ram_size[1] > 0) { + p = xen_map_guest_ram(s, s->cfg.ram_high.base, ram_size[1]); + memory_region_init_ram_ptr(&s->ram.high, NULL, "xen.ram.hi", + ram_size[1], p); + } + } - memory_region_init_alias(&s->ram.low, NULL, "xen.ram.lo", &xen_memory, - s->cfg.ram_low.base, ram_size[0]); + /* Map them onto QEMU's address-space. */ memory_region_add_subregion(sysmem, s->cfg.ram_low.base, &s->ram.low); if (ram_size[1] > 0) { - memory_region_init_alias(&s->ram.high, NULL, "xen.ram.hi", &xen_memory, - s->cfg.ram_high.base, ram_size[1]); memory_region_add_subregion(sysmem, s->cfg.ram_high.base, &s->ram.high); } - /* Setup support for grants. */ - memory_region_init_ram(&xen_grants, NULL, "xen.grants", block_len, - &error_fatal); - memory_region_add_subregion(sysmem, XEN_GRANT_ADDR_OFF, &xen_grants); + /* Grants are only supported when the mapcache is on. */ + if (s->cfg.mapcache) { + /* Setup support for grants. */ + memory_region_init_ram(&xen_grants, NULL, "xen.grants", block_len, + &error_fatal); + memory_region_add_subregion(sysmem, XEN_GRANT_ADDR_OFF, &xen_grants); + } } static void xen_set_irq(void *opaque, int irq, int level) @@ -203,7 +286,7 @@ static void xen_pvh_init(MachineState *ms) xen_register_ioreq(&s->ioreq, ms->smp.max_cpus, xpc->handle_bufioreq, &xen_memory_listener, - true); + s->cfg.mapcache); if (s->cfg.virtio_mmio_num) { xen_create_virtio_mmio_devices(s); @@ -285,6 +368,20 @@ XEN_PVH_PROP_MEMMAP(pci_ecam) XEN_PVH_PROP_MEMMAP(pci_mmio) XEN_PVH_PROP_MEMMAP(pci_mmio_high) +static void xen_pvh_set_mapcache(Object *obj, bool value, Error **errp) +{ + XenPVHMachineState *xp = XEN_PVH_MACHINE(obj); + + xp->cfg.mapcache = value; +} + +static bool xen_pvh_get_mapcache(Object *obj, Error **errp) +{ + XenPVHMachineState *xp = XEN_PVH_MACHINE(obj); + + return xp->cfg.mapcache; +} + static void xen_pvh_set_pci_intx_irq_base(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -338,6 +435,12 @@ do { \ OC_MEMMAP_PROP_SIZE(c, prop_name, name); \ } while (0) + object_class_property_add_bool(oc, "mapcache", xen_pvh_get_mapcache, + xen_pvh_set_mapcache); + object_class_property_set_description(oc, "mapcache", + "Set on/off to enable/disable the " + "mapcache"); + /* * We provide memmap properties to allow Xen to move things to other * addresses for example when users need to accomodate the memory-map @@ -377,6 +480,13 @@ do { \ #endif } +static void xen_pvh_instance_init(Object *obj) +{ + XenPVHMachineState *xp = XEN_PVH_MACHINE(obj); + + xp->cfg.mapcache = true; +} + static void xen_pvh_class_init(ObjectClass *oc, const void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -395,6 +505,7 @@ static const TypeInfo xen_pvh_info = { .parent = TYPE_MACHINE, .abstract = true, .instance_size = sizeof(XenPVHMachineState), + .instance_init = xen_pvh_instance_init, .class_size = sizeof(XenPVHMachineClass), .class_init = xen_pvh_class_init, }; diff --git a/include/hw/xen/xen-pvh-common.h b/include/hw/xen/xen-pvh-common.h index 0ed07c5694..0209b798f3 100644 --- a/include/hw/xen/xen-pvh-common.h +++ b/include/hw/xen/xen-pvh-common.h @@ -84,6 +84,8 @@ struct XenPVHMachineState { /* PCI */ MemMapEntry pci_ecam, pci_mmio, pci_mmio_high; uint32_t pci_intx_irq_base; + + bool mapcache; } cfg; }; -- 2.43.0
