Browse Source

hw/xen: xenpvh: Add prop to enable/disable the mapcache

Add a machine property to enable/disable the mapcache.
Default it to enabled for backwards compatibility.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
master
Edgar E. Iglesias 8 months ago
parent
commit
83d1d9a49e
  1. 133
      hw/xen/xen-pvh-common.c
  2. 2
      include/hw/xen/xen-pvh-common.h

133
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,
};

2
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;
};

Loading…
Cancel
Save