aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/s390x/s390-virtio-ccw.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 466e45343c..35df7e19c5 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -152,14 +152,38 @@ static void virtio_ccw_register_hcalls(void)
virtio_ccw_hcall_early_printk);
}
+/*
+ * KVM does only support memory slots up to KVM_MEM_MAX_NR_PAGES pages
+ * as the dirty bitmap must be managed by bitops that take an int as
+ * position indicator. If we have a guest beyond that we will split off
+ * new subregions. The split must happen on a segment boundary (1MB).
+ */
+#define KVM_MEM_MAX_NR_PAGES ((1ULL << 31) - 1)
+#define SEG_MSK (~0xfffffULL)
+#define KVM_SLOT_MAX_BYTES ((KVM_MEM_MAX_NR_PAGES * TARGET_PAGE_SIZE) & SEG_MSK)
static void s390_memory_init(ram_addr_t mem_size)
{
MemoryRegion *sysmem = get_system_memory();
- MemoryRegion *ram = g_new(MemoryRegion, 1);
+ ram_addr_t chunk, offset = 0;
+ unsigned int number = 0;
+ gchar *name;
/* allocate RAM for core */
- memory_region_allocate_system_memory(ram, NULL, "s390.ram", mem_size);
- memory_region_add_subregion(sysmem, 0, ram);
+ name = g_strdup_printf("s390.ram");
+ while (mem_size) {
+ MemoryRegion *ram = g_new(MemoryRegion, 1);
+ uint64_t size = mem_size;
+
+ /* KVM does not allow memslots >= 8 TB */
+ chunk = MIN(size, KVM_SLOT_MAX_BYTES);
+ memory_region_allocate_system_memory(ram, NULL, name, chunk);
+ memory_region_add_subregion(sysmem, offset, ram);
+ mem_size -= chunk;
+ offset += chunk;
+ g_free(name);
+ name = g_strdup_printf("s390.ram.%u", ++number);
+ }
+ g_free(name);
/* Initialize storage key device */
s390_skeys_init();