mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
conf, qemu: enable NVDIMM support for ppc64
Using the 'uuid' element for ppc64 NVDIMM memory added in the previous patch, use it in qemuBuildMemoryDeviceStr() to pass it over to QEMU. Another ppc64 restriction is the necessity of a mem->labelsize, given than ppc64 only support label-area backed NVDIMMs. Finally, we don't want ppc64 NVDIMMs to align up due to the high risk of going beyond the end of file with a 256MiB increment that the user didn't predict. Align it down instead. If target size is less than the minimum of 256MiB + labelsize, error out since QEMU will error out if we attempt to round it up to the minimum. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
0011d8d2c8
commit
5540acb9a2
@ -6580,13 +6580,21 @@ virDomainVideoDefValidate(const virDomainVideoDef *video,
|
||||
|
||||
|
||||
static int
|
||||
virDomainMemoryDefValidate(const virDomainMemoryDef *mem)
|
||||
virDomainMemoryDefValidate(const virDomainMemoryDef *mem,
|
||||
const virDomainDef *def)
|
||||
{
|
||||
if (mem->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
|
||||
mem->discard == VIR_TRISTATE_BOOL_YES) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("discard is not supported for nvdimms"));
|
||||
return -1;
|
||||
if (mem->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
|
||||
if (mem->discard == VIR_TRISTATE_BOOL_YES) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("discard is not supported for nvdimms"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ARCH_IS_PPC64(def->os.arch) && mem->labelsize == 0) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("label size is required for NVDIMM device"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -6697,7 +6705,7 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
|
||||
return virDomainVideoDefValidate(dev->data.video, def);
|
||||
|
||||
case VIR_DOMAIN_DEVICE_MEMORY:
|
||||
return virDomainMemoryDefValidate(dev->data.memory);
|
||||
return virDomainMemoryDefValidate(dev->data.memory, def);
|
||||
|
||||
case VIR_DOMAIN_DEVICE_VSOCK:
|
||||
return virDomainVsockDefValidate(dev->data.vsock);
|
||||
|
@ -3678,6 +3678,13 @@ qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
|
||||
if (mem->labelsize)
|
||||
virBufferAsprintf(&buf, "label-size=%llu,", mem->labelsize * 1024);
|
||||
|
||||
if (virUUIDIsValid(mem->uuid)) {
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
|
||||
virUUIDFormat(mem->uuid, uuidstr);
|
||||
virBufferAsprintf(&buf, "uuid=%s,", uuidstr);
|
||||
}
|
||||
|
||||
if (mem->readonly) {
|
||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_NVDIMM_UNARMED)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
|
@ -12614,6 +12614,46 @@ qemuDomainGetMemoryModuleSizeAlignment(const virDomainDef *def,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuDomainNVDimmAlignSizePseries(virDomainDefPtr def,
|
||||
virDomainMemoryDefPtr mem)
|
||||
{
|
||||
/* For NVDIMMs in ppc64 in we want to align down the guest
|
||||
* visible space, instead of align up, to avoid writing
|
||||
* beyond the end of file by adding a potential 256MiB
|
||||
* to the user specified size.
|
||||
*
|
||||
* The label-size is mandatory for ppc64 as well, meaning that
|
||||
* the guest visible space will be target_size-label_size.
|
||||
*
|
||||
* Finally, target_size must include label_size.
|
||||
*
|
||||
* The above can be summed up as follows:
|
||||
*
|
||||
* target_size = AlignDown(target_size - label_size) + label_size
|
||||
*/
|
||||
unsigned long long ppc64AlignSize = qemuDomainGetMemorySizeAlignment(def);
|
||||
unsigned long long guestArea = mem->size - mem->labelsize;
|
||||
|
||||
/* Align down guest_area. 256MiB is the minimum size. Error
|
||||
* out if target_size is smaller than 256MiB + label_size,
|
||||
* since aligning it up will cause QEMU errors. */
|
||||
if (mem->size < (ppc64AlignSize + mem->labelsize)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("minimum target size for the NVDIMM "
|
||||
"must be 256MB plus the label size"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
guestArea = (guestArea/ppc64AlignSize) * ppc64AlignSize;
|
||||
guestArea = MAX(guestArea, ppc64AlignSize);
|
||||
|
||||
mem->size = guestArea + mem->labelsize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuDomainAlignMemorySizes(virDomainDefPtr def)
|
||||
{
|
||||
@ -12660,8 +12700,15 @@ qemuDomainAlignMemorySizes(virDomainDefPtr def)
|
||||
|
||||
/* Align memory module sizes */
|
||||
for (i = 0; i < def->nmems; i++) {
|
||||
align = qemuDomainGetMemoryModuleSizeAlignment(def, def->mems[i]);
|
||||
def->mems[i]->size = VIR_ROUND_UP(def->mems[i]->size, align);
|
||||
if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
|
||||
ARCH_IS_PPC64(def->os.arch)) {
|
||||
if (qemuDomainNVDimmAlignSizePseries(def, def->mems[i]) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
align = qemuDomainGetMemoryModuleSizeAlignment(def, def->mems[i]);
|
||||
def->mems[i]->size = VIR_ROUND_UP(def->mems[i]->size, align);
|
||||
}
|
||||
|
||||
hotplugmem += def->mems[i]->size;
|
||||
|
||||
if (def->mems[i]->size > maxmemkb) {
|
||||
@ -12686,11 +12733,19 @@ qemuDomainAlignMemorySizes(virDomainDefPtr def)
|
||||
* inplace. Default rounding is now to 1 MiB (qemu requires rouding to page,
|
||||
* size so this should be safe).
|
||||
*/
|
||||
void
|
||||
int
|
||||
qemuDomainMemoryDeviceAlignSize(virDomainDefPtr def,
|
||||
virDomainMemoryDefPtr mem)
|
||||
{
|
||||
mem->size = VIR_ROUND_UP(mem->size, qemuDomainGetMemorySizeAlignment(def));
|
||||
if (mem->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
|
||||
ARCH_IS_PPC64(def->os.arch)) {
|
||||
return qemuDomainNVDimmAlignSizePseries(def, mem);
|
||||
} else {
|
||||
mem->size = VIR_ROUND_UP(mem->size,
|
||||
qemuDomainGetMemorySizeAlignment(def));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -967,8 +967,8 @@ bool qemuDomainHasBlockjob(virDomainObjPtr vm, bool copy_only)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
|
||||
int qemuDomainAlignMemorySizes(virDomainDefPtr def);
|
||||
void qemuDomainMemoryDeviceAlignSize(virDomainDefPtr def,
|
||||
virDomainMemoryDefPtr mem);
|
||||
int qemuDomainMemoryDeviceAlignSize(virDomainDefPtr def,
|
||||
virDomainMemoryDefPtr mem);
|
||||
|
||||
virDomainChrDefPtr qemuFindAgentConfig(virDomainDefPtr def);
|
||||
|
||||
|
@ -2352,7 +2352,8 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
|
||||
int id;
|
||||
int ret = -1;
|
||||
|
||||
qemuDomainMemoryDeviceAlignSize(vm->def, mem);
|
||||
if (qemuDomainMemoryDeviceAlignSize(vm->def, mem) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (qemuDomainDefValidateMemoryHotplug(vm->def, priv->qemuCaps, mem) < 0)
|
||||
goto cleanup;
|
||||
@ -5641,7 +5642,8 @@ qemuDomainDetachPrepMemory(virDomainObjPtr vm,
|
||||
virDomainMemoryDefPtr mem;
|
||||
int idx;
|
||||
|
||||
qemuDomainMemoryDeviceAlignSize(vm->def, match);
|
||||
if (qemuDomainMemoryDeviceAlignSize(vm->def, match) < 0)
|
||||
return -1;
|
||||
|
||||
if ((idx = virDomainMemoryFindByDef(vm->def, match)) < 0) {
|
||||
virReportError(VIR_ERR_DEVICE_MISSING,
|
||||
|
32
tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.args
Normal file
32
tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.args
Normal file
@ -0,0 +1,32 @@
|
||||
LC_ALL=C \
|
||||
PATH=/bin \
|
||||
HOME=/tmp/lib/domain--1-QEMUGuest1 \
|
||||
USER=test \
|
||||
LOGNAME=test \
|
||||
XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
|
||||
XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
|
||||
XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
||||
QEMU_AUDIO_DRV=none \
|
||||
/usr/bin/qemu-system-ppc64 \
|
||||
-name QEMUGuest1 \
|
||||
-S \
|
||||
-machine pseries,accel=tcg,usb=off,dump-guest-core=off,nvdimm=on \
|
||||
-m size=1048576k,slots=16,maxmem=1099511627776k \
|
||||
-realtime mlock=off \
|
||||
-smp 2,sockets=2,cores=1,threads=1 \
|
||||
-numa node,nodeid=0,cpus=0-1,mem=1024 \
|
||||
-object memory-backend-file,id=memnvdimm0,prealloc=yes,mem-path=/tmp/nvdimm,\
|
||||
size=537001984 \
|
||||
-device nvdimm,node=0,label-size=131072,\
|
||||
uuid=49545eb3-75e1-2d0a-acdd-f0294406c99e,memdev=memnvdimm0,id=nvdimm0,slot=0 \
|
||||
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
||||
-display none \
|
||||
-no-user-config \
|
||||
-nodefaults \
|
||||
-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
|
||||
server,nowait \
|
||||
-mon chardev=charmonitor,id=monitor,mode=control \
|
||||
-rtc base=utc \
|
||||
-no-shutdown \
|
||||
-usb \
|
||||
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
|
@ -0,0 +1,36 @@
|
||||
LC_ALL=C \
|
||||
PATH=/bin \
|
||||
HOME=/tmp/lib/domain--1-QEMUGuest1 \
|
||||
USER=test \
|
||||
LOGNAME=test \
|
||||
XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
|
||||
XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
|
||||
XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
|
||||
QEMU_AUDIO_DRV=none \
|
||||
/usr/bin/qemu-system-ppc64 \
|
||||
-name guest=QEMUGuest1,debug-threads=on \
|
||||
-S \
|
||||
-object secret,id=masterKey0,format=raw,\
|
||||
file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
|
||||
-machine pseries,accel=tcg,usb=off,dump-guest-core=off,nvdimm=on \
|
||||
-cpu POWER9 \
|
||||
-m size=1048576k,slots=16,maxmem=1099511627776k \
|
||||
-overcommit mem-lock=off \
|
||||
-smp 2,sockets=2,dies=1,cores=1,threads=1 \
|
||||
-numa node,nodeid=0,cpus=0-1,mem=1024 \
|
||||
-object memory-backend-file,id=memnvdimm0,prealloc=yes,mem-path=/tmp/nvdimm,\
|
||||
size=537001984 \
|
||||
-device nvdimm,node=0,label-size=131072,\
|
||||
uuid=49545eb3-75e1-2d0a-acdd-f0294406c99e,memdev=memnvdimm0,id=nvdimm0,slot=0 \
|
||||
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
||||
-display none \
|
||||
-no-user-config \
|
||||
-nodefaults \
|
||||
-chardev socket,id=charmonitor,fd=1729,server,nowait \
|
||||
-mon chardev=charmonitor,id=monitor,mode=control \
|
||||
-rtc base=utc \
|
||||
-no-shutdown \
|
||||
-boot strict=on \
|
||||
-device pci-ohci,id=usb,bus=pci.0,addr=0x1 \
|
||||
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
|
||||
-msg timestamp=on
|
@ -38,8 +38,11 @@
|
||||
<path>/tmp/nvdimm</path>
|
||||
</source>
|
||||
<target>
|
||||
<size unit='KiB'>523264</size>
|
||||
<size unit='KiB'>550000</size>
|
||||
<node>0</node>
|
||||
<label>
|
||||
<size unit='KiB'>128</size>
|
||||
</label>
|
||||
</target>
|
||||
<address type='dimm' slot='0'/>
|
||||
</memory>
|
||||
|
@ -2791,6 +2791,7 @@ mymain(void)
|
||||
DO_TEST_CAPS_LATEST("memory-hotplug-nvdimm-align");
|
||||
DO_TEST_CAPS_LATEST("memory-hotplug-nvdimm-pmem");
|
||||
DO_TEST_CAPS_LATEST("memory-hotplug-nvdimm-readonly");
|
||||
DO_TEST_CAPS_ARCH_LATEST("memory-hotplug-nvdimm-ppc64", "ppc64");
|
||||
|
||||
DO_TEST("machine-aeskeywrap-on-caps",
|
||||
QEMU_CAPS_AES_KEY_WRAP,
|
||||
|
@ -38,8 +38,11 @@
|
||||
<path>/tmp/nvdimm</path>
|
||||
</source>
|
||||
<target>
|
||||
<size unit='KiB'>523264</size>
|
||||
<size unit='KiB'>550000</size>
|
||||
<node>0</node>
|
||||
<label>
|
||||
<size unit='KiB'>128</size>
|
||||
</label>
|
||||
</target>
|
||||
<address type='dimm' slot='0'/>
|
||||
</memory>
|
||||
|
Loading…
Reference in New Issue
Block a user