From: Lin Yang <lin.a.yang@intel.com>
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@intel.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
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-numa.xml | 64 +++++++++++++++++++
tests/qemuxml2argvdata/sgx-epc.xml | 52 +++++++++++++++
.../sgx-epc-numa.x86_64-latest.xml | 1 +
.../sgx-epc.x86_64-6.2.0.xml | 1 +
tests/qemuxml2xmltest.c | 3 +
21 files changed, 247 insertions(+), 15 deletions(-)
create mode 100644 tests/qemuxml2argvdata/sgx-epc-numa.xml
create mode 100644 tests/qemuxml2argvdata/sgx-epc.xml
create mode 120000 tests/qemuxml2xmloutdata/sgx-epc-numa.x86_64-latest.xml
create mode 120000 tests/qemuxml2xmloutdata/sgx-epc.x86_64-6.2.0.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 1ed969ac3e..bdd0fcea8e 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -7940,6 +7940,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>
...
@@ -7948,7 +7962,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.7.0 and QEMU 6.2.0`
``access``
An optional attribute ``access`` ( :since:`since 3.2.0` ) that provides
@@ -8008,6 +8024,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.7.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 e85cc1f809..a1f64b4fcb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1440,6 +1440,7 @@ VIR_ENUM_IMPL(virDomainMemoryModel,
"nvdimm",
"virtio-pmem",
"virtio-mem",
+ "sgx-epc",
);
VIR_ENUM_IMPL(virDomainShmemModel,
@@ -13303,6 +13304,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;
@@ -13371,6 +13386,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;
}
@@ -15167,6 +15183,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;
@@ -24778,6 +24799,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 060c395943..4fda47118f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2573,6 +2573,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 e673e4b81a..bc24c68a05 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -2334,6 +2334,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 c4f293a4c3..ca779ba66b 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6838,6 +6838,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 7b91fe3141..e7f76068cb 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -515,6 +515,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 8699b88220..f3f6870c58 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4001,6 +4001,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 b02ffc9a2e..fb287a9623 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8449,6 +8449,7 @@ qemuDomainUpdateMemoryDeviceInfo(virQEMUDriver *driver,
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;
@@ -9130,6 +9131,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;
@@ -9165,7 +9172,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;
@@ -9173,15 +9180,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"));
@@ -9204,22 +9233,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 026be99ba9..08cc995bfa 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;
}
@@ -1039,6 +1040,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;
}
@@ -2421,6 +2423,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;
}
@@ -3081,6 +3084,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;
@@ -3107,6 +3111,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;
@@ -3140,6 +3145,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 9013e6fb8d..530011fe4a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7170,6 +7170,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 d42333195a..554eb482fb 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3936,6 +3936,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;
@@ -4010,6 +4011,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 764d5b029e..259636f7e7 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -5181,6 +5181,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 9f2872decc..98044d1847 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-numa.xml b/tests/qemuxml2argvdata/sgx-epc-numa.xml
new file mode 100644
index 0000000000..9029977f20
--- /dev/null
+++ b/tests/qemuxml2argvdata/sgx-epc-numa.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='q35'>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/qemuxml2argvdata/sgx-epc.xml b/tests/qemuxml2argvdata/sgx-epc.xml
new file mode 100644
index 0000000000..8b46a799dc
--- /dev/null
+++ b/tests/qemuxml2argvdata/sgx-epc.xml
@@ -0,0 +1,52 @@
+<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'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-q35-6.2'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </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'>
+ <target>
+ <size unit='KiB'>65536</size>
+ </target>
+ </memory>
+ <memory model='sgx-epc'>
+ <target>
+ <size unit='KiB'>16384</size>
+ </target>
+ </memory>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/sgx-epc-numa.x86_64-latest.xml b/tests/qemuxml2xmloutdata/sgx-epc-numa.x86_64-latest.xml
new file mode 120000
index 0000000000..fa27d9b2a2
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/sgx-epc-numa.x86_64-latest.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/sgx-epc-numa.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmloutdata/sgx-epc.x86_64-6.2.0.xml b/tests/qemuxml2xmloutdata/sgx-epc.x86_64-6.2.0.xml
new file mode 120000
index 0000000000..cc2263ac99
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/sgx-epc.x86_64-6.2.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 4cbf380e44..033efad646 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1462,6 +1462,9 @@ mymain(void)
DO_TEST_CAPS_LATEST("channel-qemu-vdagent");
DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features");
+ DO_TEST_CAPS_VER("sgx-epc", "6.2.0");
+ DO_TEST_CAPS_LATEST("sgx-epc-numa");
+
cleanup:
if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
virFileDeleteTree(fakerootdir);
--
2.35.1
On Wed, Jul 27, 2022 at 12:34:57 +0200, Michal Privoznik wrote: > From: Lin Yang <lin.a.yang@intel.com> > > 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@intel.com> > Signed-off-by: Michal Privoznik <mprivozn@redhat.com> > --- [...] > diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst > index 1ed969ac3e..bdd0fcea8e 100644 > --- a/docs/formatdomain.rst > +++ b/docs/formatdomain.rst > @@ -7940,6 +7940,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> > ... > > @@ -7948,7 +7962,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.7.0 and QEMU 6.2.0` I don't quite understand from this description whether this is real memory usable by the guest OS or something for internal use by the hypervisor. Specifically which leads me to questioning this is that the example sizes are very tiny compared to real memory sizing. Additionally in qemuDomainDefValidateMemoryHotplug you are changing the code to specifically exclude the sizing of the 'sgx-epc' memory devices from the total size of the memory, but this contrasts with the memory _not_ being excluded from the initial memory calculation in virDomainDefGetMemoryInitial which is used to format the initial memory argument ('-m size=...'). Thus at least one of them is wrong. If this is not guest usable memory, then the <memory> element should not be used to bolt this on, but rather add a new element similarly to what we have when AMD SEV is in use. > > ``access`` > An optional attribute ``access`` ( :since:`since 3.2.0` ) that provides > @@ -8008,6 +8024,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.7.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 e85cc1f809..a1f64b4fcb 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -1440,6 +1440,7 @@ VIR_ENUM_IMPL(virDomainMemoryModel, > "nvdimm", > "virtio-pmem", > "virtio-mem", > + "sgx-epc", > ); > > VIR_ENUM_IMPL(virDomainShmemModel, > @@ -13303,6 +13304,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, A more appropriate error code would be VIR_ERR_XML_DETAIL or VIR_ERR_INVALID_ARG > + _("Invalid value of 'nodemask': %s"), nodemask); > + return -1; > + } > + } > + break; > + > case VIR_DOMAIN_MEMORY_MODEL_NONE: > case VIR_DOMAIN_MEMORY_MODEL_LAST: > break; > @@ -13371,6 +13386,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; > } > @@ -15167,6 +15183,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; > @@ -24778,6 +24799,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/qemu/qemu_validate.c b/src/qemu/qemu_validate.c > index 764d5b029e..259636f7e7 100644 > --- a/src/qemu/qemu_validate.c > +++ b/src/qemu/qemu_validate.c > @@ -5181,6 +5181,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 9f2872decc..98044d1847 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-numa.xml b/tests/qemuxml2argvdata/sgx-epc-numa.xml > new file mode 100644 > index 0000000000..9029977f20 > --- /dev/null > +++ b/tests/qemuxml2argvdata/sgx-epc-numa.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='q35'>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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c > index 4cbf380e44..033efad646 100644 > --- a/tests/qemuxml2xmltest.c > +++ b/tests/qemuxml2xmltest.c > @@ -1462,6 +1462,9 @@ mymain(void) > DO_TEST_CAPS_LATEST("channel-qemu-vdagent"); > DO_TEST_CAPS_LATEST("channel-qemu-vdagent-features"); > > + DO_TEST_CAPS_VER("sgx-epc", "6.2.0"); > + DO_TEST_CAPS_LATEST("sgx-epc-numa"); This test will break once I re-generate latest caps. Please pin it to qemu-7.0.
On 7/28/22 14:41, Peter Krempa wrote: > On Wed, Jul 27, 2022 at 12:34:57 +0200, Michal Privoznik wrote: >> From: Lin Yang <lin.a.yang@intel.com> >> >> 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@intel.com> >> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> >> --- > > [...] > >> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst >> index 1ed969ac3e..bdd0fcea8e 100644 >> --- a/docs/formatdomain.rst >> +++ b/docs/formatdomain.rst >> @@ -7940,6 +7940,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> >> ... >> >> @@ -7948,7 +7962,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.7.0 and QEMU 6.2.0` > > I don't quite understand from this description whether this is real > memory usable by the guest OS or something for internal use by the > hypervisor. > > Specifically which leads me to questioning this is that the example > sizes are very tiny compared to real memory sizing. I admit that I don't know all the details and let somebody from Intel to provide them. But basically, SGX works by reserving a chunk of RAM (on each NUMA node) which is then encrypted and the processor controls access to it. This chunk is referred to as Processor Reserved Memory and to my understanding is the maximum size of an enclave. Thus I can understand why new <memory/> model was used. But I'm not sure how QEMU accounts for this memory, whether say 16KiB worth of SGX is added to whatever current guest has OR it's taken from an existing memory. > > Additionally in qemuDomainDefValidateMemoryHotplug you are changing the > code to specifically exclude the sizing of the 'sgx-epc' memory devices > from the total size of the memory, but this contrasts with the memory > _not_ being excluded from the initial memory calculation in > virDomainDefGetMemoryInitial which is used to format the initial memory > argument ('-m size=...'). Thus at least one of them is wrong. > > If this is not guest usable memory, then the <memory> element should not > be used to bolt this on, but rather add a new element similarly to what > we have when AMD SEV is in use. > Alright, I'm hold off reworking these patches per your review until we are clear on this. Michal
On Fri, Jul 29, 2022 at 09:38:35 +0200, Michal Prívozník wrote: > On 7/28/22 14:41, Peter Krempa wrote: > > On Wed, Jul 27, 2022 at 12:34:57 +0200, Michal Privoznik wrote: > >> From: Lin Yang <lin.a.yang@intel.com> > >> > >> 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@intel.com> > >> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> > >> --- > > > > [...] > > > >> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst > >> index 1ed969ac3e..bdd0fcea8e 100644 > >> --- a/docs/formatdomain.rst > >> +++ b/docs/formatdomain.rst > >> @@ -7940,6 +7940,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> > >> ... > >> > >> @@ -7948,7 +7962,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.7.0 and QEMU 6.2.0` > > > > I don't quite understand from this description whether this is real > > memory usable by the guest OS or something for internal use by the > > hypervisor. > > > > Specifically which leads me to questioning this is that the example > > sizes are very tiny compared to real memory sizing. > > I admit that I don't know all the details and let somebody from Intel to > provide them. But basically, SGX works by reserving a chunk of RAM (on > each NUMA node) which is then encrypted and the processor controls > access to it. This chunk is referred to as Processor Reserved Memory and > to my understanding is the maximum size of an enclave. Thus I can > understand why new <memory/> model was used. Even this interpretation would not sit well with the semantics of the <memory> element. > But I'm not sure how QEMU > accounts for this memory, whether say 16KiB worth of SGX is added to > whatever current guest has OR it's taken from an existing memory. Note that the name expands to "enclave page cache", so even the name doesn't really seem to be hinting that the memory declared like this is used by the guest OS. Preferrably the documentation added in this patch will clarify that, because if it is not clarified by the documentation, we will be getting clarification requests and it's very apparent that we can't answer them since neither of us actually knows what's going on. > > > > > Additionally in qemuDomainDefValidateMemoryHotplug you are changing the > > code to specifically exclude the sizing of the 'sgx-epc' memory devices > > from the total size of the memory, but this contrasts with the memory > > _not_ being excluded from the initial memory calculation in > > virDomainDefGetMemoryInitial which is used to format the initial memory > > argument ('-m size=...'). Thus at least one of them is wrong. > > > > If this is not guest usable memory, then the <memory> element should not > > be used to bolt this on, but rather add a new element similarly to what > > we have when AMD SEV is in use. > > > > Alright, I'm hold off reworking these patches per your review until we > are clear on this. > > Michal >
> On Fri, Jul 29, 2022 at 09:38:35 +0200, Michal Prívozník wrote: > > On 7/28/22 14:41, Peter Krempa wrote: > > > On Wed, Jul 27, 2022 at 12:34:57 +0200, Michal Privoznik wrote: > > >> From: Lin Yang <lin.a.yang@intel.com> > > >> > > >> 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@intel.com> > > >> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> > > >> --- > > > > > > [...] > > > > > >> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst > > >> index 1ed969ac3e..bdd0fcea8e 100644 > > >> --- a/docs/formatdomain.rst > > >> +++ b/docs/formatdomain.rst > > >> @@ -7940,6 +7940,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> > > >> ... > > >> > > >> @@ -7948,7 +7962,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.7.0 and QEMU 6.2.0` > > > > > > I don't quite understand from this description whether this is real > > > memory usable by the guest OS or something for internal use by the > > > hypervisor. > > > > > > Specifically which leads me to questioning this is that the example > > > sizes are very tiny compared to real memory sizing. > > > > I admit that I don't know all the details and let somebody from Intel to > > provide them. But basically, SGX works by reserving a chunk of RAM (on > > each NUMA node) which is then encrypted and the processor controls > > access to it. This chunk is referred to as Processor Reserved Memory and > > to my understanding is the maximum size of an enclave. Thus I can > > understand why new <memory/> model was used. > > Even this interpretation would not sit well with the semantics of the > <memory> element. > > > But I'm not sure how QEMU > > accounts for this memory, whether say 16KiB worth of SGX is added to > > whatever current guest has OR it's taken from an existing memory. > > Note that the name expands to "enclave page cache", so even the name > doesn't really seem to be hinting that the memory declared like this is > used by the guest OS. > > Preferrably the documentation added in this patch will clarify that, > because if it is not clarified by the documentation, we will be getting > clarification requests and it's very apparent that we can't answer them > since neither of us actually knows what's going on. > > > > > > > > > Additionally in qemuDomainDefValidateMemoryHotplug you are changing the > > > code to specifically exclude the sizing of the 'sgx-epc' memory devices > > > from the total size of the memory, but this contrasts with the memory > > > _not_ being excluded from the initial memory calculation in > > > virDomainDefGetMemoryInitial which is used to format the initial memory > > > argument ('-m size=...'). Thus at least one of them is wrong. > > > > > > If this is not guest usable memory, then the <memory> element should not > > > be used to bolt this on, but rather add a new element similarly to what > > > we have when AMD SEV is in use. > > > > > > > Alright, I'm hold off reworking these patches per your review until we > > are clear on this. Basically sgx-epc memory created here is usable by guest OS. KVM SGX creates One new misc device, and QEMU will open '/dev/sgx_vepc' device node to mmap() host EPC memory to guest. The sgx-epc memory is a separate memory range. Its size will not change the guest OS size that is initialized by ‘-m size=…’. So it should be excluded from calculation in virDomainDefGetMemoryInitial. Thanks for pointing this out. Thanks, Lin.
© 2016 - 2025 Red Hat, Inc.