Add qemu CLI support for EGM memory device model: - Specify EGM device path to memory-backend-file object - Support acpi-egm-memory object with id, pci-dev, and node attributes
Signed-off-by: Ian May <[email protected]> Signed-off-by: Nathan Chen <[email protected]> --- src/qemu/qemu_alias.c | 17 +++++++++ src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 66 ++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.c | 13 ++++++- src/qemu/qemu_domain_address.c | 6 ++++ src/qemu/qemu_driver.c | 1 + src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_monitor_json.c | 1 + src/qemu/qemu_postparse.c | 1 + src/qemu/qemu_process.c | 2 ++ src/qemu/qemu_validate.c | 6 ++++ 12 files changed, 114 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index b0bc057bd1..0e87968bf6 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -553,6 +553,23 @@ qemuAssignDeviceMemoryAlias(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: prefix = "epc"; break; + case VIR_DOMAIN_MEMORY_MODEL_EGM: { + const char *egm_devname = NULL; + + if (mem->source.egm.path) { + egm_devname = strrchr(mem->source.egm.path, '/'); + if (egm_devname) + egm_devname++; + else + egm_devname = mem->source.egm.path; + + mem->info.alias = g_strdup(egm_devname); + return 0; + } + + prefix = "egm"; + break; + } case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 83946123be..1344519074 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -746,6 +746,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 485 */ "acpi-generic-initiator", /* QEMU_CAPS_ACPI_GENERIC_INITIATOR */ + "acpi-egm-memory", /* QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY */ ); @@ -1440,6 +1441,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "tpm-emulator", QEMU_CAPS_DEVICE_TPM_EMULATOR }, { "tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH }, { "acpi-generic-initiator", QEMU_CAPS_ACPI_GENERIC_INITIATOR }, + { "acpi-egm-memory", QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 2b454e0352..61ffd7a8a8 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -727,6 +727,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 485 */ QEMU_CAPS_ACPI_GENERIC_INITIATOR, /* -object acpi-generic-initiator */ + QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY, /* For using extended GPU memory */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fcf5fc1935..d4e2fc8d7a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -990,6 +990,7 @@ qemuBuildVirtioDevGetConfigDev(const virDomainDeviceDef *device, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3144,6 +3145,7 @@ qemuBuildMemoryGetPagesize(virQEMUDriverConfig *cfg, nvdimmPath = mem->source.virtio_pmem.path; break; case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3344,6 +3346,9 @@ qemuBuildMemoryBackendProps(virJSONValue **backendProps, case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: nvdimmPath = mem->source.virtio_pmem.path; break; + case VIR_DOMAIN_MEMORY_MODEL_EGM: + nvdimmPath = mem->source.egm.path; + break; case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3559,6 +3564,7 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd, { g_autoptr(virJSONValue) props = NULL; g_autoptr(virJSONValue) tcProps = NULL; + g_autoptr(virJSONValue) egmProps = NULL; virBitmap *nodemask = NULL; g_autofree char *alias = NULL; @@ -3584,6 +3590,33 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd, if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0) return -1; + if (mem->model == VIR_DOMAIN_MEMORY_MODEL_EGM) { + g_autofree char *egmId = NULL; + g_autofree char *egmObjStr = NULL; + g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + const char *basename = NULL; + + /* Extract basename from host path under /dev/ */ + basename = strrchr(mem->source.egm.path, '/'); + if (basename && *(basename + 1)) { + egmId = g_strdup(basename + 1); + } else { + egmId = g_strdup(mem->source.egm.path); + } + + virBufferAsprintf(&buf, "acpi-egm-memory,id=%s", egmId); + + if (mem->target.egm.pciDev) + virBufferAsprintf(&buf, ",pci-dev=%s", mem->target.egm.pciDev); + + if (mem->targetNode >= 0) + virBufferAsprintf(&buf, ",node=%d", mem->targetNode); + + egmObjStr = virBufferContentAndReset(&buf); + + virCommandAddArgList(cmd, "-object", egmObjStr, NULL); + } + return 0; } @@ -3653,6 +3686,7 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg, dynamicMemslots = mem->target.virtio_mem.dynamicMemslots; break; + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: @@ -7053,6 +7087,7 @@ qemuAppendDomainMemoryMachineParams(virBuffer *buf, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -7781,6 +7816,13 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg, hmat = true; } + for (i = 0; i < def->nmems; i++) { + if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM) { + if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv) < 0) + goto cleanup; + } + } + nodeBackends = g_new0(virJSONValue *, ncells); nodemask = g_new0(virBitmap *, ncells); @@ -7816,8 +7858,18 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg, for (i = 0; i < ncells; i++) { ssize_t initiator = virDomainNumaGetNodeInitiator(def->numa, i); unsigned long long memSize = virDomainNumaGetNodeMemorySize(def->numa, i); + bool egmBacked = false; + size_t k; + + for (k = 0; k < def->nmems; k++) { + if (def->mems[k]->model == VIR_DOMAIN_MEMORY_MODEL_EGM && + def->mems[k]->targetNode == (int)i) { + egmBacked = true; + break; + } + } - if (needBackend && memSize > 0) { + if (needBackend && memSize > 0 && !egmBacked) { g_autoptr(virJSONValue) tcProps = NULL; if (qemuBuildThreadContextProps(&tcProps, &nodeBackends[i], @@ -7847,7 +7899,11 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg, if (memSize > 0) { if (needBackend) { - virBufferAsprintf(&buf, ",memdev=ram-node%zu", i); + if (egmBacked) { + virBufferAsprintf(&buf, ",memdev=mem%s", def->mems[k]->info.alias); + } else { + virBufferAsprintf(&buf, ",memdev=ram-node%zu", i); + } } else { virBufferAsprintf(&buf, ",mem=%llu", memSize / 1024); } @@ -7911,6 +7967,9 @@ qemuBuildMemoryDeviceCommandLine(virCommand *cmd, for (i = 0; i < def->nmems; i++) { g_autoptr(virJSONValue) props = NULL; + if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_EGM) + continue; + if (qemuBuildMemoryDimmBackendStr(cmd, def->mems[i], def, cfg, priv) < 0) return -1; @@ -7931,6 +7990,9 @@ qemuBuildMemoryDeviceCommandLine(virCommand *cmd, case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: break; + /* EGM memory backing is via memory-backend-file object */ + case VIR_DOMAIN_MEMORY_MODEL_EGM: + break; case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 375e0e441a..75095b4de8 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -7220,6 +7220,7 @@ qemuDomainUpdateMemoryDeviceInfo(virDomainObj *vm, break; case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -7454,7 +7455,8 @@ qemuDomainAlignMemorySizes(virDomainDef *def) def->mems[i]->size = VIR_ROUND_UP(def->mems[i]->size, align); } - hotplugmem += def->mems[i]->size; + if (def->mems[i]->model != VIR_DOMAIN_MEMORY_MODEL_EGM) + hotplugmem += def->mems[i]->size; if (def->mems[i]->size > maxmemkb) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -7942,6 +7944,12 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem, virDomainMemoryModelTypeToString(mem->model)); return -1; + case VIR_DOMAIN_MEMORY_MODEL_EGM: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hotplug is not supported for the %1$s device"), + virDomainMemoryModelTypeToString(mem->model)); + return -1; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: return -1; @@ -8000,6 +8008,7 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: break; @@ -8047,6 +8056,8 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: /* sgx epc memory does not support hotplug, skip this check */ + case VIR_DOMAIN_MEMORY_MODEL_EGM: + /* egm memory does not support hotplug, skip this check */ case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: break; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 774541ca06..0d9f2b5649 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -303,6 +303,7 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -1033,6 +1034,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: return 0; } @@ -2455,6 +2457,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -3151,6 +3154,7 @@ qemuDomainAssignMemoryDeviceSlot(virDomainObj *vm, return qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev); case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3178,6 +3182,7 @@ qemuDomainReleaseMemoryDeviceSlot(virDomainObj *vm, break; case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3212,6 +3217,7 @@ qemuDomainAssignMemorySlots(virDomainDef *def) /* handled in qemuDomainAssignPCIAddresses() */ break; case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b0eff443aa..9d17c159e4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6704,6 +6704,7 @@ qemuDomainAttachMemoryConfig(virDomainDef *vmdef, case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: break; case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index fb426deb1a..890bb052b6 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -7348,6 +7348,7 @@ qemuDomainChangeMemoryLiveValidateChange(const virDomainMemoryDef *oldDef, case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot modify memory of model '%1$s'"), diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c121c05ffd..2c2273d927 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7088,6 +7088,7 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitor *mon, switch ((virDomainMemoryModel) model) { case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: /* While 'id' attribute is marked as optional in QEMU's QAPI diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c index fd27f8be27..b23dd94d2c 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -1838,6 +1838,7 @@ qemuDomainDefNumaAutoAdd(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9926998f85..e41767a70f 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4066,6 +4066,7 @@ qemuProcessDomainMemoryDefNeedHugepagesPath(const virDomainMemoryDef *mem, case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: pagesize = mem->source.virtio_mem.pagesize; break; + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: @@ -4155,6 +4156,7 @@ qemuProcessNeedMemoryBackingPath(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_EGM: case VIR_DOMAIN_MEMORY_MODEL_LAST: /* Backed by user provided path. Not stored in memory * backing dir anyway. */ diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 3e8fdb2268..e8d6fe21cb 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5812,6 +5812,12 @@ qemuValidateDomainDeviceDefMemory(const virDomainMemoryDef *mem, break; + case VIR_DOMAIN_MEMORY_MODEL_EGM: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ACPI_EGM_MEMORY)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("ACPI EGM memory device is not supported with this QEMU binary")); + return -1; + } case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; -- 2.43.0
