From nobody Thu Oct 30 01:40:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15264842692491018.1076365052555; Wed, 16 May 2018 08:24:29 -0700 (PDT) Received: from localhost ([::1]:51238 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fIyI0-0000nT-Du for importer@patchew.org; Wed, 16 May 2018 11:24:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54319) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fIyGE-0008BU-28 for qemu-devel@nongnu.org; Wed, 16 May 2018 11:22:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fIyG9-0005yW-7C for qemu-devel@nongnu.org; Wed, 16 May 2018 11:22:38 -0400 Received: from szxga05-in.huawei.com ([45.249.212.191]:2098 helo=huawei.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fIyFz-0005sv-0U; Wed, 16 May 2018 11:22:24 -0400 Received: from DGGEMS404-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 36BEBE5CA1DC9; Wed, 16 May 2018 23:22:06 +0800 (CST) Received: from S00345302A-PC.china.huawei.com (10.202.227.237) by DGGEMS404-HUB.china.huawei.com (10.3.19.204) with Microsoft SMTP Server id 14.3.361.1; Wed, 16 May 2018 23:22:01 +0800 From: Shameer Kolothum To: , Date: Wed, 16 May 2018 16:20:26 +0100 Message-ID: <20180516152026.2920-7-shameerali.kolothum.thodi@huawei.com> X-Mailer: git-send-email 2.12.0.windows.1 In-Reply-To: <20180516152026.2920-1-shameerali.kolothum.thodi@huawei.com> References: <20180516152026.2920-1-shameerali.kolothum.thodi@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.202.227.237] X-CFilter-Loop: Reflected X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 45.249.212.191 Subject: [Qemu-devel] [RFC v2 6/6] hw/arm: Populate non-contiguous memory regions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, drjones@redhat.com, jonathan.cameron@huawei.com, linuxarm@huawei.com, Shameer Kolothum , eric.auger@redhat.com, alex.williamson@redhat.com, zhaoshenglong@huawei.com, imammedo@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In case valid iova regions are non-contiguous, split the RAM mem into a 1GB non-pluggable dimm and remaining as a single pc-dimm mem. Signed-off-by: Shameer Kolothum --- hw/arm/virt.c | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 256 insertions(+), 5 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index be3ad14..562e389 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -58,6 +58,12 @@ #include "hw/smbios/smbios.h" #include "qapi/visitor.h" #include "standard-headers/linux/input.h" +#include "hw/vfio/vfio-common.h" +#include "qemu/config-file.h" +#include "monitor/qdev.h" +#include "qom/object_interfaces.h" +#include "qapi/qmp/qdict.h" +#include "qemu/option.h" =20 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -110,7 +116,10 @@ static ARMPlatformBusSystemParams platform_bus_params; * terabyte of physical address space.) */ #define RAMLIMIT_GB 255 -#define RAMLIMIT_BYTES (RAMLIMIT_GB * 1024ULL * 1024 * 1024) +#define SZ_1G (1024ULL * 1024 * 1024) +#define RAMLIMIT_BYTES (RAMLIMIT_GB * SZ_1G) + +#define ALIGN_1G (1ULL << 30) =20 /* Addresses and sizes of our components. * 0..128MB is space for a flash device so we can run bootrom code such as= UEFI. @@ -1171,6 +1180,236 @@ void virt_machine_done(Notifier *notifier, void *da= ta) virt_build_smbios(vms); } =20 +static void free_iova_copy(struct vfio_iova_head *iova_copy) +{ + VFIOIovaRange *iova, *tmp; + + QLIST_FOREACH_SAFE(iova, iova_copy, next, tmp) { + QLIST_REMOVE(iova, next); + g_free(iova); + } +} + +static void get_iova_copy(struct vfio_iova_head *iova_copy) +{ + VFIOIovaRange *iova, *new, *prev_iova =3D NULL; + + QLIST_FOREACH(iova, &vfio_iova_regions, next) { + new =3D g_malloc0(sizeof(*iova)); + new->start =3D iova->start; + new->end =3D iova->end; + + if (prev_iova) { + QLIST_INSERT_AFTER(prev_iova, new, next); + } else { + QLIST_INSERT_HEAD(iova_copy, new, next); + } + prev_iova =3D new; + } +} + +static hwaddr find_memory_chunk(VirtMachineState *vms, + struct vfio_iova_head *iova_copy, + hwaddr req_size, bool pcdimm) +{ + VFIOIovaRange *iova, *tmp; + hwaddr new_start, new_size, sz_align; + hwaddr virt_start =3D vms->memmap[VIRT_MEM].base; + hwaddr addr_align =3D ALIGN_1G; /* Set to max ARM64 hugepage size */ + + /* Size alignment */ + sz_align =3D (pcdimm) ? MAX(TARGET_PAGE_SIZE, QEMU_VMALLOC_ALIGN) : + TARGET_PAGE_SIZE; + + QLIST_FOREACH_SAFE(iova, iova_copy, next, tmp) { + if (virt_start >=3D iova->end) { + continue; + } + + /* Align addr */ + new_start =3D ROUND_UP(MAX(virt_start, iova->start), addr_align); + if (new_start >=3D iova->end) { + continue; + } + + if (req_size > iova->end - new_start + 1) { + continue; + } + + /* + * Check the region can hold any size alignment requirement. + */ + new_size =3D QEMU_ALIGN_UP(req_size, sz_align); + + if ((new_start + new_size - 1 > iova->end) || + (new_start + new_size >=3D virt_start + RAMLIMIT_BYTES)) { + continue; + } + + /* + * Modify the iova list entry for non pc-dimm case so that it + * is not used again for pc-dimm allocation. + */ + if (!pcdimm) { + if (new_size - req_size) { + iova->start =3D new_start + new_size; + } else { + QLIST_REMOVE(iova, next); + } + } + return new_start; + } + + return -1; +} + +static void update_memory_regions(VirtMachineState *vms) +{ + hwaddr addr; + VFIOIovaRange *iova; + MachineState *machine =3D MACHINE(vms); + hwaddr virt_start =3D vms->memmap[VIRT_MEM].base; + hwaddr req_size, ram_size =3D machine->ram_size; + struct vfio_iova_head iova_copy =3D QLIST_HEAD_INITIALIZER(iova_copy); + + /* No valid iova regions, use default */ + if (QLIST_EMPTY(&vfio_iova_regions)) { + vms->bootinfo.loader_start =3D vms->memmap[VIRT_MEM].base; + vms->bootinfo.ram_size =3D ram_size; + return; + } + + /* + * If valid iovas has only one entry, check the req size fits in + * and can have the loader start < 4GB. This will make sure platforms + * with no holes in mem will have the same mem model as before. + */ + req_size =3D ram_size; + iova =3D QLIST_NEXT(QLIST_FIRST(&vfio_iova_regions), next); + if (!iova) { + iova =3D QLIST_FIRST(&vfio_iova_regions); + addr =3D ROUND_UP(MAX(virt_start, iova->start), ALIGN_1G); + if ((addr < 4 * SZ_1G) && (ram_size <=3D iova->end - addr + 1) && + (addr + ram_size < virt_start + RAMLIMIT_BYTES)) { + vms->bootinfo.loader_start =3D addr; + vms->bootinfo.ram_size =3D ram_size; + return; + } + } + + /* Get a copy of valid iovas and work on it */ + get_iova_copy(&iova_copy); + + /* Split the mem as first 1GB non-pluggable and rest as pc-dimm */ + req_size =3D MIN(ram_size, SZ_1G); + addr =3D find_memory_chunk(vms, &iova_copy, req_size, false); + if (addr =3D=3D -1 || addr >=3D 4 * SZ_1G) { + goto out; + } + + /*Update non-pluggable mem details */ + machine->ram_size =3D req_size; + vms->bootinfo.loader_start =3D addr; + vms->bootinfo.ram_size =3D machine->ram_size; + + req_size =3D ram_size - req_size; + if (!req_size) { + goto done; + } + + /* Remaining memory is modeled as a pc-dimm. */ + addr =3D find_memory_chunk(vms, &iova_copy, req_size, true); + if (addr =3D=3D -1) { + goto out; + } + + /*Update pc-dimm mem details */ + vms->bootinfo.dimm_mem =3D g_new(struct dimm_mem_info, 1); + vms->bootinfo.dimm_mem->base =3D addr; + vms->bootinfo.dimm_mem->size =3D req_size; + machine->maxram_size =3D machine->ram_size + req_size; + machine->ram_slots +=3D 1; + +done: + free_iova_copy(&iova_copy); + return; + +out: + free_iova_copy(&iova_copy); + error_report("mach-virt: Not enough contiguous memory to model ram"); + exit(1); +} + +static void create_pcdimms(VirtMachineState *vms, + MemoryRegion *sysmem, + MemoryRegion *ram) +{ + hwaddr addr, size; + Error *local_err =3D NULL; + QDict *qdict; + QemuOpts *opts; + char *tmp; + + if (!vms->bootinfo.dimm_mem) { + return; + } + + addr =3D vms->bootinfo.dimm_mem->base; + size =3D vms->bootinfo.dimm_mem->size; + + /*Create hotplug address space */ + vms->hotplug_memory.base =3D ROUND_UP(addr, ALIGN_1G); + size =3D ROUND_UP(size, MAX(TARGET_PAGE_SIZE, QEMU_VMALLOC_ALIGN)); + + memory_region_init(&vms->hotplug_memory.mr, OBJECT(vms), + "hotplug-memory", size); + memory_region_add_subregion(sysmem, vms->hotplug_memory.base, + &vms->hotplug_memory.mr); + /* Create backend mem object */ + qdict =3D qdict_new(); + qdict_put_str(qdict, "qom-type", "memory-backend-ram"); + qdict_put_str(qdict, "id", "mem1"); + tmp =3D g_strdup_printf("%"PRIu64 "M", size / (1024 * 1024)); + qdict_put_str(qdict, "size", tmp); + g_free(tmp); + + opts =3D qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &local_= err); + if (local_err) { + goto err; + } + + user_creatable_add_opts(opts, &local_err); + qemu_opts_del(opts); + QDECREF(qdict); + if (local_err) { + goto err; + } + + /* Create pc-dimm dev*/ + qdict =3D qdict_new(); + qdict_put_str(qdict, "driver", "pc-dimm"); + qdict_put_str(qdict, "id", "dimm1"); + qdict_put_str(qdict, "memdev", "mem1"); + + opts =3D qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_= err); + if (local_err) { + goto err; + } + + qdev_device_add(opts, &local_err); + qemu_opts_del(opts); + QDECREF(qdict); + if (local_err) { + goto err; + } + + return; + +err: + error_report_err(local_err); + exit(1); +} + static void virt_ram_memory_region_init(Notifier *notifier, void *data) { MemoryRegion *sysmem =3D get_system_memory(); @@ -1179,9 +1418,14 @@ static void virt_ram_memory_region_init(Notifier *no= tifier, void *data) ram_memory_region_init); MachineState *machine =3D MACHINE(vms); =20 + update_memory_regions(vms); memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram", machine->ram_size); - memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram); + memory_region_add_subregion(sysmem, vms->bootinfo.loader_start, ram); + + if (vms->bootinfo.dimm_mem) { + create_pcdimms(vms, sysmem, ram); + } } =20 static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx) @@ -1404,13 +1648,11 @@ static void machvirt_init(MachineState *machine) vms->machine_done.notify =3D virt_machine_done; qemu_add_machine_init_done_notifier(&vms->machine_done); =20 - vms->bootinfo.ram_size =3D machine->ram_size; vms->bootinfo.kernel_filename =3D machine->kernel_filename; vms->bootinfo.kernel_cmdline =3D machine->kernel_cmdline; vms->bootinfo.initrd_filename =3D machine->initrd_filename; vms->bootinfo.nb_cpus =3D smp_cpus; vms->bootinfo.board_id =3D -1; - vms->bootinfo.loader_start =3D vms->memmap[VIRT_MEM].base; vms->bootinfo.get_dtb =3D machvirt_dtb; vms->bootinfo.firmware_loaded =3D firmware_loaded; =20 @@ -1559,7 +1801,7 @@ static void virt_dimm_plug(HotplugHandler *hotplug_de= v, PCDIMMDevice *dimm =3D PC_DIMM(dev); PCDIMMDeviceClass *ddc =3D PC_DIMM_GET_CLASS(dimm); MemoryRegion *mr; - uint64_t align; + uint64_t align, addr; Error *local_err =3D NULL; =20 mr =3D ddc->get_memory_region(dimm, &local_err); @@ -1573,6 +1815,15 @@ static void virt_dimm_plug(HotplugHandler *hotplug_d= ev, goto out; } =20 + addr =3D object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, + &error_fatal); + /* Assign the node for pc-dimm initial ram */ + if (vms->bootinfo.dimm_mem && (addr =3D=3D vms->bootinfo.dimm_mem->bas= e) + && (nb_numa_nodes > 0)) { + vms->bootinfo.dimm_mem->node =3D object_property_get_uint(OBJECT(d= ev), + PC_DIMM_NODE_PROP, &error_fatal= ); + } + out: error_propagate(errp, local_err); } --=20 2.7.4