From 92a37a04d6e034b73ea1ba4825ba4d5860f0a810 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 31 Oct 2014 16:38:36 +0000 Subject: pc: limit DIMM address and size to page aligned values When running in KVM mode, kvm_set_phys_mem() will silently fail if registered MemoryRegion address/size is not page aligned. Causing memory hotplug failure in guest. Mapping non aligned MemoryRegion in TCG mode 'works', but sane guest OS still expects page aligned memory module and fails to initialize it if it's not aligned. So do not allow non aligned (i.e. valid) address/size values for DIMM to avoid either KVM failure or guest issues caused by it. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/mem/pc-dimm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'hw/mem/pc-dimm.c') diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index a800ea7a9f..4944f0faf9 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -139,7 +139,7 @@ static int pc_dimm_built_list(Object *obj, void *opaque) uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, uint64_t address_space_size, - uint64_t *hint, uint64_t size, + uint64_t *hint, uint64_t align, uint64_t size, Error **errp) { GSList *list = NULL, *item; @@ -152,6 +152,18 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, goto out; } + if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) { + error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes", + align); + goto out; + } + + if (QEMU_ALIGN_UP(size, align) != size) { + error_setg(errp, "backend memory size must be multiple of 0x%" + PRIx64, align); + goto out; + } + assert(address_space_end > address_space_start); object_child_foreach(qdev_get_machine(), pc_dimm_built_list, &list); -- cgit v1.2.1 From 0c0de1b681bc11a8ebc94bd45e99d6f4e8fafd80 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 31 Oct 2014 16:38:40 +0000 Subject: pc: pc-dimm: use backend alignment during address auto allocation Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/mem/pc-dimm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'hw/mem/pc-dimm.c') diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index 4944f0faf9..d431834030 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -146,6 +146,9 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, uint64_t new_addr, ret = 0; uint64_t address_space_end = address_space_start + address_space_size; + g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start); + g_assert(QEMU_ALIGN_UP(address_space_size, align) == address_space_size); + if (!address_space_size) { error_setg(errp, "memory hotplug is not enabled, " "please add maxmem option"); @@ -189,7 +192,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, error_setg(errp, "address range conflicts with '%s'", d->id); goto out; } - new_addr = dimm->addr + dimm_size; + new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size, align); } } ret = new_addr; -- cgit v1.2.1