[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH RFC 5/5] s390x: initial support for virtio-mem
From: |
David Hildenbrand |
Subject: |
[PATCH RFC 5/5] s390x: initial support for virtio-mem |
Date: |
Wed, 8 Jul 2020 20:51:35 +0200 |
Let's wire up the initial, basic virtio-mem implementation in QEMU. It will
have to see some important extensions (esp., resizeable allocations)
before it can be considered production ready. Also, the focus on the Linux
driver side is on memory hotplug, there are a lot of things optimize in
the future to improve memory unplug capabilities. However, the basics
are in place.
Block migration for now, as we'll have to take proper care of storage
keys and storage attributes. Also, make sure to not hotplug huge pages
to a setup without huge pages.
With a Linux guest that supports virtio-mem (and has
CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE set for now), a basic example.
1. Start a VM with 2G initial memory and a virtio-mem device with a maximum
capacity of 18GB (and an initial size of 300M):
sudo qemu-system-s390x \
--enable-kvm \
-m 2G,maxmem=20G \
-smp 4 \
-nographic \
-chardev socket,id=monitor,path=/var/tmp/monitor,server,nowait \
-mon chardev=monitor,mode=readline \
-net nic -net user \
-hda s390x.cow2 \
-object memory-backend-ram,id=mem0,size=18G \
-device virtio-mem-ccw,id=vm0,memdev=mem0,requested-size=300M
2. Query the current size of virtio-mem device:
(qemu) info memory-devices
Memory device [virtio-mem]: "vm0"
memaddr: 0x80000000
node: 0
requested-size: 314572800
size: 314572800
max-size: 19327352832
block-size: 1048576
memdev: /objects/mem0
3. Request to grow it to 8GB:
(qemu) qom-set vm0 requested-size 8G
(qemu) info memory-devices
Memory device [virtio-mem]: "vm0"
memaddr: 0x80000000
node: 0
requested-size: 8589934592
size: 8589934592
max-size: 19327352832
block-size: 1048576
memdev: /objects/mem0
4. Request to shrink it to 800M (might take a while, might not fully
succeed, and might not be able to remove memory blocks in Linux):
(qemu) qom-set vm0 requested-size 800M
(qemu) info memory-devices
Memory device [virtio-mem]: "vm0"
memaddr: 0x80000000
node: 0
requested-size: 838860800
size: 838860800
max-size: 19327352832
block-size: 1048576
memdev: /objects/mem0
Note: Due to lack of resizeable allocations, we will go ahead and
reserve a 18GB vmalloc area + size the QEMU RAM slot + KVM mamory slot
18GB. echo 1 > /proc/sys/vm/overcommit_memory might be required for
now. In the future, this area will instead grow on actual demand and shrink
when possible.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
hw/s390x/Kconfig | 1 +
hw/s390x/Makefile.objs | 1 +
hw/s390x/s390-virtio-ccw.c | 116 ++++++++++++++++++++++++++++++++++++-
hw/virtio/virtio-mem.c | 2 +
4 files changed, 118 insertions(+), 2 deletions(-)
diff --git a/hw/s390x/Kconfig b/hw/s390x/Kconfig
index 5e7d8a2bae..b8619c1adc 100644
--- a/hw/s390x/Kconfig
+++ b/hw/s390x/Kconfig
@@ -10,3 +10,4 @@ config S390_CCW_VIRTIO
select SCLPCONSOLE
select VIRTIO_CCW
select MSI_NONBROKEN
+ select VIRTIO_MEM_SUPPORTED
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index a46a1c7894..924775d6f0 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -20,6 +20,7 @@ obj-$(CONFIG_VIRTIO_NET) += virtio-ccw-net.o
obj-$(CONFIG_VIRTIO_BLK) += virtio-ccw-blk.o
obj-$(call land,$(CONFIG_VIRTIO_9P),$(CONFIG_VIRTFS)) += virtio-ccw-9p.o
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-ccw.o
+obj-$(CONFIG_VIRTIO_MEM) += virtio-ccw-mem.o
endif
obj-y += css-bridge.o
obj-y += ccw-device.o
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 577590e623..e714035077 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -45,6 +45,7 @@
#include "sysemu/sysemu.h"
#include "hw/s390x/pv.h"
#include "migration/blocker.h"
+#include "hw/mem/memory-device.h"
static Error *pv_mig_blocker;
@@ -542,11 +543,119 @@ static void s390_machine_reset(MachineState *machine)
s390_ipl_clear_reset_request();
}
+static void s390_virtio_md_pre_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev);
+ MemoryDeviceState *md = MEMORY_DEVICE(dev);
+ MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
+ Error *local_err = NULL;
+
+ if (!hotplug_dev2 && dev->hotplugged) {
+ /*
+ * Without a bus hotplug handler, we cannot control the plug/unplug
+ * order. We should never reach this point when hotplugging, however,
+ * better add a safety net.
+ */
+ error_setg(errp, "hotplug of virtio based memory devices not supported"
+ " on this bus.");
+ return;
+ }
+
+ /*
+ * KVM does not support device memory with a bigger page size than initial
+ * memory. The new memory backend is not mapped yet, so
+ * qemu_maxrampagesize() won't consider it.
+ */
+ if (kvm_enabled()) {
+ MemoryRegion *mr = mdc->get_memory_region(md, &local_err);
+
+ if (local_err) {
+ goto out;
+ }
+ if (qemu_ram_pagesize(mr->ram_block) > qemu_maxrampagesize()) {
+ error_setg(&local_err, "Device memory has a bigger page size than"
+ " initial memory");
+ goto out;
+ }
+ }
+
+ /*
+ * First, see if we can plug this memory device at all. If that
+ * succeeds, branch of to the actual hotplug handler.
+ */
+ memory_device_pre_plug(md, MACHINE(hotplug_dev), NULL, &local_err);
+ if (!local_err && hotplug_dev2) {
+ hotplug_handler_pre_plug(hotplug_dev2, dev, &local_err);
+ }
+out:
+ error_propagate(errp, local_err);
+}
+
+static void s390_virtio_md_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev);
+ static Error *migration_blocker;
+ bool add_blocker = !migration_blocker;
+ Error *local_err = NULL;
+
+ /*
+ * Until we support migration of storage keys and storage attributes
+ * for anything that's not initial memory, let's block migration.
+ */
+ if (add_blocker) {
+ error_setg(&migration_blocker, "storage keys/attributes not yet"
+ " migrated for memory devices");
+ migrate_add_blocker(migration_blocker, &local_err);
+ if (local_err) {
+ error_free_or_abort(&migration_blocker);
+ goto out;
+ }
+ }
+
+ /*
+ * Plug the memory device first and then branch off to the actual
+ * hotplug handler. If that one fails, we can easily undo the memory
+ * device bits.
+ */
+ memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
+ if (hotplug_dev2) {
+ hotplug_handler_plug(hotplug_dev2, dev, &local_err);
+ if (local_err) {
+ memory_device_unplug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev));
+ if (add_blocker) {
+ migrate_del_blocker(migration_blocker);
+ error_free_or_abort(&migration_blocker);
+ }
+ }
+ }
+out:
+ error_propagate(errp, local_err);
+}
+
+static void s390_virtio_md_unplug_request(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ /* We don't support hot unplug of virtio based memory devices */
+ error_setg(errp, "virtio based memory devices cannot be unplugged.");
+}
+
+static void s390_machine_device_pre_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_CCW)) {
+ s390_virtio_md_pre_plug(hotplug_dev, dev, errp);
+ }
+}
+
static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
s390_cpu_plug(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_CCW)) {
+ s390_virtio_md_plug(hotplug_dev, dev, errp);
}
}
@@ -555,7 +664,8 @@ static void
s390_machine_device_unplug_request(HotplugHandler *hotplug_dev,
{
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
error_setg(errp, "CPU hot unplug not supported on this machine");
- return;
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_CCW)) {
+ s390_virtio_md_unplug_request(hotplug_dev, dev, errp);
}
}
@@ -596,7 +706,8 @@ static const CPUArchIdList
*s390_possible_cpu_arch_ids(MachineState *ms)
static HotplugHandler *s390_get_hotplug_handler(MachineState *machine,
DeviceState *dev)
{
- if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
+ if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) ||
+ object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_CCW)) {
return HOTPLUG_HANDLER(machine);
}
return NULL;
@@ -668,6 +779,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void
*data)
mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
/* it is overridden with 'host' cpu *in kvm_arch_init* */
mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu");
+ hc->pre_plug = s390_machine_device_pre_plug;
hc->plug = s390_machine_device_plug;
hc->unplug_request = s390_machine_device_unplug_request;
nc->nmi_monitor_handler = s390_nmi;
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 65850530e7..e1b3275089 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -53,6 +53,8 @@
*/
#if defined(TARGET_X86_64) || defined(TARGET_I386)
#define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB))
+#elif defined(TARGET_S390X)
+#define VIRTIO_MEM_USABLE_EXTENT (2 * (256 * MiB))
#else
#error VIRTIO_MEM_USABLE_EXTENT not defined
#endif
--
2.26.2
- Re: [PATCH RFC 2/5] s390x: implement diag260, (continued)
- Re: [PATCH RFC 2/5] s390x: implement diag260, David Hildenbrand, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, Heiko Carstens, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, David Hildenbrand, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, Heiko Carstens, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, David Hildenbrand, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, Heiko Carstens, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, David Hildenbrand, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, David Hildenbrand, 2020/07/15
- Re: [PATCH RFC 2/5] s390x: implement diag260, Heiko Carstens, 2020/07/20
- Re: [PATCH RFC 2/5] s390x: implement diag260, David Hildenbrand, 2020/07/20
[PATCH RFC 5/5] s390x: initial support for virtio-mem,
David Hildenbrand <=
[PATCH RFC 4/5] s390x: implement virtio-mem-ccw, David Hildenbrand, 2020/07/08
[PATCH RFC 3/5] s390x: prepare device memory address space, David Hildenbrand, 2020/07/08