With NUMA config: <devices> ... <memory model='sgx-epc'> <source> <nodemask>0-1</nodemask> </source> <target> <size unit='KiB'>512</size> <node>0</node> </target> </memory> ... </devices> Without NUMA config: <devices> ... <memory model='sgx-epc'> <target> <size unit='KiB'>512</size> </target> </memory> ... </devices> Signed-off-by: Lin Yang <lin.a.yang@xxxxxxxxx> Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> Signed-off-by: Haibin Huang <haibin.huang@xxxxxxxxx> --- docs/formatdomain.rst | 25 +++++++- src/conf/domain_conf.c | 30 +++++++++ src/conf/domain_conf.h | 1 + src/conf/domain_postparse.c | 1 + src/conf/domain_validate.c | 9 +++ src/conf/schemas/domaincommon.rng | 1 + src/qemu/qemu_alias.c | 3 + src/qemu/qemu_command.c | 1 + src/qemu/qemu_domain.c | 48 ++++++++++---- src/qemu/qemu_domain_address.c | 6 ++ src/qemu/qemu_driver.c | 1 + src/qemu/qemu_process.c | 2 + src/qemu/qemu_validate.c | 8 +++ src/security/security_apparmor.c | 1 + src/security/security_dac.c | 2 + src/security/security_selinux.c | 2 + tests/qemuxml2argvdata/sgx-epc.xml | 64 +++++++++++++++++++ .../sgx-epc.x86_64-7.0.0.xml | 1 + tests/qemuxml2xmltest.c | 2 + 19 files changed, 193 insertions(+), 15 deletions(-) create mode 100644 tests/qemuxml2argvdata/sgx-epc.xml create mode 120000 tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 34e4906eb4..728f08158e 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -8001,6 +8001,20 @@ Example: usage of the memory devices <current unit='KiB'>524288</current> </target> </memory> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>16384</size> + <node>0</node> + </target> + </memory> + <memory model='sgx-epc'> + <target> + <size unit='KiB'>16384</size> + </target> + </memory> </devices> ... @@ -8009,7 +8023,9 @@ Example: usage of the memory devices 1.2.14` Provide ``nvdimm`` model that adds a Non-Volatile DIMM module. :since:`Since 3.2.0` Provide ``virtio-pmem`` model to add a paravirtualized persistent memory device. :since:`Since 7.1.0` Provide ``virtio-mem`` model - to add paravirtualized memory device. :since:`Since 7.9.0` + to add paravirtualized memory device. :since:`Since 7.9.0` Provide + ``sgx-epc`` model to add a SGX enclave page cache (EPC) memory to the guest. + :since:`Since 8.9.0 and QEMU 7.0.0` ``access`` An optional attribute ``access`` ( :since:`since 3.2.0` ) that provides @@ -8069,6 +8085,13 @@ Example: usage of the memory devices Represents a path in the host that backs the virtio memory module in the guest. It is mandatory. + For model ``sgx-epc`` this element is optional. The following optional + elements may be used: + + ``nodemask`` + This element can be used to override the default set of NUMA nodes where + the memory would be allocated. :since:`Since 8.9.0 and QEMU 7.0.0` + ``target`` The mandatory ``target`` element configures the placement and sizing of the added memory from the perspective of the guest. diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7dba65cfeb..e260632616 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1443,6 +1443,7 @@ VIR_ENUM_IMPL(virDomainMemoryModel, "nvdimm", "virtio-pmem", "virtio-mem", + "sgx-epc", ); VIR_ENUM_IMPL(virDomainShmemModel, @@ -13154,6 +13155,20 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node, def->nvdimmPath = virXPathString("string(./path)", ctxt); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if ((nodemask = virXPathString("string(./nodemask)", ctxt))) { + if (virBitmapParse(nodemask, &def->sourceNodes, + VIR_DOMAIN_CPUMASK_LEN) < 0) + return -1; + + if (virBitmapIsAllClear(def->sourceNodes)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Invalid value of 'nodemask': %s"), nodemask); + return -1; + } + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -13222,6 +13237,7 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -15020,6 +15036,11 @@ virDomainMemoryFindByDefInternal(virDomainDef *def, continue; break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (!virBitmapEqual(tmp->sourceNodes, mem->sourceNodes)) + continue; + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -24608,6 +24629,15 @@ virDomainMemorySourceDefFormat(virBuffer *buf, virBufferEscapeString(&childBuf, "<path>%s</path>\n", def->nvdimmPath); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (def->sourceNodes) { + if (!(bitmap = virBitmapFormat(def->sourceNodes))) + return -1; + + virBufferAsprintf(&childBuf, "<nodemask>%s</nodemask>\n", bitmap); + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 8f8a54bc41..0471d636d9 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2582,6 +2582,7 @@ typedef enum { VIR_DOMAIN_MEMORY_MODEL_NVDIMM, /* nvdimm memory device */ VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM, /* virtio-pmem memory device */ VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM, /* virtio-mem memory device */ + VIR_DOMAIN_MEMORY_MODEL_SGX_EPC, /* SGX enclave page cache */ VIR_DOMAIN_MEMORY_MODEL_LAST } virDomainMemoryModel; diff --git a/src/conf/domain_postparse.c b/src/conf/domain_postparse.c index df59de2d0d..9a3e8f494c 100644 --- a/src/conf/domain_postparse.c +++ b/src/conf/domain_postparse.c @@ -645,6 +645,7 @@ virDomainMemoryDefPostParse(virDomainMemoryDef *mem, break; case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 81f6d5dbd5..5bc7ea10aa 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2360,6 +2360,15 @@ virDomainMemoryDefValidate(const virDomainMemoryDef *mem, case VIR_DOMAIN_MEMORY_MODEL_DIMM: break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("memory device address is not supported for model '%s'"), + virDomainMemoryModelTypeToString(mem->model)); + return -1; + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 5ff15e8787..b541277ec0 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6880,6 +6880,7 @@ <value>nvdimm</value> <value>virtio-pmem</value> <value>virtio-mem</value> + <value>sgx-epc</value> </choice> </attribute> <optional> diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 835401dc07..6061dd3f02 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -513,6 +513,9 @@ qemuAssignDeviceMemoryAlias(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: prefix = "virtiomem"; break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + prefix = "epc"; + break; case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7ec44736d3..df6ce58e23 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3597,6 +3597,7 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg, return NULL; break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: default: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4c14fc2aef..d4c7f971c6 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8302,6 +8302,7 @@ qemuDomainUpdateMemoryDeviceInfo(virDomainObj *vm, break; case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -8983,6 +8984,12 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem, } break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("hotplug is not supported for the %s device"), + virDomainMemoryModelTypeToString(mem->model)); + return -1; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: return -1; @@ -9018,7 +9025,7 @@ int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, const virDomainMemoryDef *mem) { - unsigned int nmems = def->nmems; + unsigned int hotplugNum = 0; unsigned long long hotplugSpace; unsigned long long hotplugMemory = 0; size_t i; @@ -9026,15 +9033,37 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, hotplugSpace = def->mem.max_memory - virDomainDefGetMemoryInitial(def); if (mem) { - nmems++; + hotplugNum++; hotplugMemory = mem->size; if (qemuDomainDefValidateMemoryHotplugDevice(mem, def) < 0) return -1; } + for (i = 0; i < def->nmems; i++) { + switch (def->mems[i]->model) { + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + hotplugMemory += def->mems[i]->size; + hotplugNum++; + /* already existing devices don't need to be checked on hotplug */ + if (!mem && + qemuDomainDefValidateMemoryHotplugDevice(def->mems[i], def) < 0) + return -1; + break; + + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + /* sgx epc memory does not support hotplug */ + case VIR_DOMAIN_MEMORY_MODEL_LAST: + case VIR_DOMAIN_MEMORY_MODEL_NONE: + break; + } + } + if (!virDomainDefHasMemoryHotplug(def)) { - if (nmems) { + if (hotplugNum) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("cannot use/hotplug a memory device when domain " "'maxMemory' is not defined")); @@ -9057,22 +9086,13 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, } } - if (nmems > def->mem.memory_slots) { + if (hotplugNum > def->mem.memory_slots) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("memory device count '%u' exceeds slots count '%u'"), - nmems, def->mem.memory_slots); + hotplugNum, def->mem.memory_slots); return -1; } - for (i = 0; i < def->nmems; i++) { - hotplugMemory += def->mems[i]->size; - - /* already existing devices don't need to be checked on hotplug */ - if (!mem && - qemuDomainDefValidateMemoryHotplugDevice(def->mems[i], def) < 0) - return -1; - } - if (hotplugMemory > hotplugSpace) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("memory device total size exceeds hotplug space")); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index d8ec6ec71c..b8d1969fbe 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -389,6 +389,7 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -1038,6 +1039,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: return 0; } @@ -2420,6 +2422,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -3080,6 +3083,7 @@ qemuDomainAssignMemoryDeviceSlot(virDomainObj *vm, return qemuDomainEnsurePCIAddress(vm, &dev); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3106,6 +3110,7 @@ qemuDomainReleaseMemoryDeviceSlot(virDomainObj *vm, qemuDomainReleaseDeviceAddress(vm, &mem->info); break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; @@ -3139,6 +3144,7 @@ qemuDomainAssignMemorySlots(virDomainDef *def) case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: /* handled in qemuDomainAssignPCIAddresses() */ break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: 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 40d23b5723..92ef1907ba 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7100,6 +7100,7 @@ qemuDomainChangeMemoryLiveValidateChange(const virDomainMemoryDef *oldDef, case VIR_DOMAIN_MEMORY_MODEL_DIMM: 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_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot modify memory of model '%s'"), diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index cec4a64526..7b35593598 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3864,6 +3864,7 @@ qemuProcessDomainMemoryDefNeedHugepagesPath(const virDomainMemoryDef *mem, case VIR_DOMAIN_MEMORY_MODEL_NONE: 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_LAST: /* None of these can be backed by hugepages. */ return false; @@ -3948,6 +3949,7 @@ qemuProcessNeedMemoryBackingPath(virDomainDef *def, case VIR_DOMAIN_MEMORY_MODEL_NONE: 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_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 cb4e32c0ff..9b2b23fecf 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5093,6 +5093,14 @@ qemuValidateDomainDeviceDefMemory(virDomainMemoryDef *mem, } break; + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SGX_EPC)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("sgx epc isn't supported by this QEMU binary")); + return -1; + } + break; + case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 008384dee8..36e8ce42b5 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -687,6 +687,7 @@ AppArmorSetMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 21cebae694..d94995c9cf 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1853,6 +1853,7 @@ virSecurityDACRestoreMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: ret = 0; @@ -2040,6 +2041,7 @@ virSecurityDACSetMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: case VIR_DOMAIN_MEMORY_MODEL_NONE: ret = 0; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index a296cb7613..1f72f61cac 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1580,6 +1580,7 @@ virSecuritySELinuxSetMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_LAST: break; } @@ -1608,6 +1609,7 @@ virSecuritySELinuxRestoreMemoryLabel(virSecurityManager *mgr, case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: case VIR_DOMAIN_MEMORY_MODEL_NONE: case VIR_DOMAIN_MEMORY_MODEL_LAST: ret = 0; diff --git a/tests/qemuxml2argvdata/sgx-epc.xml b/tests/qemuxml2argvdata/sgx-epc.xml new file mode 100644 index 0000000000..62212f3401 --- /dev/null +++ b/tests/qemuxml2argvdata/sgx-epc.xml @@ -0,0 +1,64 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='pc-q35-7.0'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <numa> + <cell id='0' cpus='0' memory='109550' unit='KiB'/> + <cell id='1' cpus='1' memory='109550' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </memballoon> + <memory model='sgx-epc'> + <source> + <nodemask>0-1</nodemask> + </source> + <target> + <size unit='KiB'>65536</size> + <node>0</node> + </target> + </memory> + <memory model='sgx-epc'> + <source> + <nodemask>2-3</nodemask> + </source> + <target> + <size unit='KiB'>16384</size> + <node>1</node> + </target> + </memory> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml b/tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml new file mode 120000 index 0000000000..cc2263ac99 --- /dev/null +++ b/tests/qemuxml2xmloutdata/sgx-epc.x86_64-7.0.0.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/sgx-epc.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 3a2d029c4f..301406fc1d 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1312,6 +1312,8 @@ mymain(void) DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features"); + DO_TEST_CAPS_VER("sgx-epc", "7.0.0"); + cleanup: if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); -- 2.25.1