* Mon Apr 14 2025 Jon Maloy <jmaloy@redhat.com> - 9.1.0-18

- kvm-virtio-kconfig-memory-devices-are-PCI-only.patch [RHEL-72977]
- kvm-hw-s390-ccw-device-Convert-to-three-phase-reset.patch [RHEL-72977]
- kvm-hw-s390-virtio-ccw-Convert-to-three-phase-reset.patch [RHEL-72977]
- kvm-target-s390-Convert-CPU-to-Resettable-interface.patch [RHEL-72977]
- kvm-reset-Use-ResetType-for-qemu_devices_reset-and-Machi.patch [RHEL-72977]
- kvm-reset-Add-RESET_TYPE_WAKEUP.patch [RHEL-72977]
- kvm-virtio-mem-Use-new-Resettable-framework-instead-of-L.patch [RHEL-72977]
- kvm-virtio-mem-Add-support-for-suspend-wake-up-with-plug.patch [RHEL-72977]
- kvm-virtio-mem-unplug-memory-only-during-system-resets-n.patch [RHEL-72977]
- kvm-s390x-s390-virtio-ccw-don-t-crash-on-weird-RAM-sizes.patch [RHEL-72977]
- kvm-s390x-s390-virtio-hcall-remove-hypercall-registratio.patch [RHEL-72977]
- kvm-s390x-s390-virtio-hcall-prepare-for-more-diag500-hyp.patch [RHEL-72977]
- kvm-s390x-rename-s390-virtio-hcall-to-s390-hypercall.patch [RHEL-72977]
- kvm-s390x-s390-virtio-ccw-move-setting-the-maximum-guest.patch [RHEL-72977]
- kvm-s390x-introduce-s390_get_memory_limit.patch [RHEL-72977]
- kvm-s390x-s390-hypercall-introduce-DIAG500-STORAGE_LIMIT.patch [RHEL-72977]
- kvm-s390x-s390-stattrib-kvm-prepare-for-memory-devices-a.patch [RHEL-72977]
- kvm-s390x-s390-skeys-prepare-for-memory-devices.patch [RHEL-72977]
- kvm-s390x-s390-virtio-ccw-prepare-for-memory-devices.patch [RHEL-72977]
- kvm-s390x-pv-prepare-for-memory-devices.patch [RHEL-72977]
- kvm-s390x-remember-the-maximum-page-size.patch [RHEL-72977]
- kvm-s390x-virtio-ccw-add-support-for-virtio-based-memory.patch [RHEL-72977]
- kvm-s390x-virtio-mem-support.patch [RHEL-72977]
- kvm-hw-virtio-Also-include-md-stubs-in-case-CONFIG_VIRTI.patch [RHEL-72977]
- kvm-virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch [RHEL-72977]
- kvm-redhat-Enable-virtio-mem-on-s390x.patch [RHEL-72977]
- Resolves: RHEL-72977
  ([IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part)
This commit is contained in:
Jon Maloy 2025-04-14 18:57:58 -04:00
parent 5b6159d787
commit eace179c9a
27 changed files with 4076 additions and 1 deletions

View File

@ -0,0 +1,63 @@
From 5126609c0714c66a0ec41328017e7e8388c78bf4 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 13 Sep 2024 15:31:43 +0100
Subject: [PATCH 02/26] hw/s390/ccw-device: Convert to three-phase reset
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [2/26] 58f6fc2e65a101e069feac399859464d31e43045 (thuth/qemu-kvm-cs)
Convert the TYPE_CCW_DEVICE to three-phase reset. This is a
device class which is subclassed, so it needs to be three-phase
before we can convert the subclass.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-id: 20240830145812.1967042-2-peter.maydell@linaro.org
(cherry picked from commit 6a0e10b76b68e2f412746a1d5ed7d6efee804864)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/ccw-device.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c
index d7bb364579..30f2fb486f 100644
--- a/hw/s390x/ccw-device.c
+++ b/hw/s390x/ccw-device.c
@@ -88,9 +88,9 @@ static Property ccw_device_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-static void ccw_device_reset(DeviceState *d)
+static void ccw_device_reset_hold(Object *obj, ResetType type)
{
- CcwDevice *ccw_dev = CCW_DEVICE(d);
+ CcwDevice *ccw_dev = CCW_DEVICE(obj);
css_reset_sch(ccw_dev->sch);
}
@@ -99,11 +99,12 @@ static void ccw_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
CCWDeviceClass *k = CCW_DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
k->realize = ccw_device_realize;
k->refill_ids = ccw_device_refill_ids;
device_class_set_props(dc, ccw_device_properties);
- dc->reset = ccw_device_reset;
+ rc->phases.hold = ccw_device_reset_hold;
dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
}
--
2.48.1

View File

@ -0,0 +1,92 @@
From 7cbf9be09907407a64d739a2d0862af2ad08eaf5 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 13 Sep 2024 15:31:43 +0100
Subject: [PATCH 03/26] hw/s390/virtio-ccw: Convert to three-phase reset
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [3/26] e06ee194fa289a387433b905eb0999a048681a92 (thuth/qemu-kvm-cs)
Convert the virtio-ccw code to three-phase reset. This allows us to
remove a call to device_class_set_parent_reset(), replacing it with
the three-phase equivalent resettable_class_set_parent_phases().
Removing all the device_class_set_parent_reset() uses will allow us
to remove some of the glue code that interworks between three-phase
and legacy reset.
This is a simple conversion, with no behavioural changes.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20240830145812.1967042-3-peter.maydell@linaro.org
(cherry picked from commit 6affa00d6ebebf24485667fe146470b0d6feb90d)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/virtio-ccw.c | 13 ++++++++-----
hw/s390x/virtio-ccw.h | 2 +-
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index b4676909dd..96747318d2 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -913,14 +913,15 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
}
}
-static void virtio_ccw_reset(DeviceState *d)
+static void virtio_ccw_reset_hold(Object *obj, ResetType type)
{
- VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(obj);
VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
virtio_ccw_reset_virtio(dev);
- if (vdc->parent_reset) {
- vdc->parent_reset(d);
+
+ if (vdc->parent_phases.hold) {
+ vdc->parent_phases.hold(obj, type);
}
}
@@ -1233,11 +1234,13 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
CCWDeviceClass *k = CCW_DEVICE_CLASS(dc);
VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
k->unplug = virtio_ccw_busdev_unplug;
dc->realize = virtio_ccw_busdev_realize;
dc->unrealize = virtio_ccw_busdev_unrealize;
- device_class_set_parent_reset(dc, virtio_ccw_reset, &vdc->parent_reset);
+ resettable_class_set_parent_phases(rc, NULL, virtio_ccw_reset_hold, NULL,
+ &vdc->parent_phases);
}
static const TypeInfo virtio_ccw_device_info = {
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index fac186c8f6..c7a830a194 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -57,7 +57,7 @@ struct VirtIOCCWDeviceClass {
CCWDeviceClass parent_class;
void (*realize)(VirtioCcwDevice *dev, Error **errp);
void (*unrealize)(VirtioCcwDevice *dev);
- void (*parent_reset)(DeviceState *dev);
+ ResettablePhases parent_phases;
};
/* Performance improves when virtqueue kick processing is decoupled from the
--
2.48.1

View File

@ -0,0 +1,59 @@
From afa3a488f3ca52a5455987e4cd643882c4b15d8a Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Thu, 13 Mar 2025 07:35:22 +0100
Subject: [PATCH 24/26] hw/virtio: Also include md stubs in case
CONFIG_VIRTIO_PCI is not set
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [24/26] ae6307b26d01d2a317f7e5d1d3b3a16b6d5f56de (thuth/qemu-kvm-cs)
For the s390x target, it's possible to build the QEMU binary without
CONFIG_VIRTIO_PCI and only have the virtio-mem device via the ccw
transport. In that case, QEMU currently fails to link correctly:
/usr/bin/ld: libqemu-s390x-softmmu.a.p/hw_s390x_s390-virtio-ccw.c.o: in function `s390_machine_device_pre_plug':
../hw/s390x/s390-virtio-ccw.c:579:(.text+0x1e96): undefined reference to `virtio_md_pci_pre_plug'
/usr/bin/ld: libqemu-s390x-softmmu.a.p/hw_s390x_s390-virtio-ccw.c.o: in function `s390_machine_device_plug':
../hw/s390x/s390-virtio-ccw.c:608:(.text+0x21a4): undefined reference to `virtio_md_pci_plug'
/usr/bin/ld: libqemu-s390x-softmmu.a.p/hw_s390x_s390-virtio-ccw.c.o: in function `s390_machine_device_unplug_request':
../hw/s390x/s390-virtio-ccw.c:622:(.text+0x2334): undefined reference to `virtio_md_pci_unplug_request'
/usr/bin/ld: libqemu-s390x-softmmu.a.p/hw_s390x_s390-virtio-ccw.c.o: in function `s390_machine_device_unplug':
../hw/s390x/s390-virtio-ccw.c:633:(.text+0x2436): undefined reference to `virtio_md_pci_unplug'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
We also need to include the stubs when CONFIG_VIRTIO_PCI is missing.
Fixes: aa910c20ec5 ("s390x: virtio-mem support")
Message-ID: <20250313063522.1348288-1-thuth@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit c1a6bff276ca52ffde472532d92bb5bb122dab3f)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/virtio/meson.build | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index c38bdd6fa4..e2f9c75625 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -89,7 +89,8 @@ specific_virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss)
system_ss.add_all(when: 'CONFIG_VIRTIO', if_true: system_virtio_ss)
system_ss.add(when: 'CONFIG_VIRTIO', if_false: files('vhost-stub.c'))
system_ss.add(when: 'CONFIG_VIRTIO', if_false: files('virtio-stub.c'))
-system_ss.add(when: 'CONFIG_VIRTIO_MD', if_false: files('virtio-md-stubs.c'))
+system_ss.add(when: ['CONFIG_VIRTIO_MD', 'CONFIG_VIRTIO_PCI'],
+ if_false: files('virtio-md-stubs.c'))
system_ss.add(files('virtio-hmp-cmds.c'))
--
2.48.1

View File

@ -0,0 +1,36 @@
From 7300a435547b7e999227648fd1451db00e9c4867 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Mon, 24 Mar 2025 18:09:26 +0100
Subject: [PATCH 26/26] redhat: Enable virtio-mem on s390x
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [26/26] 076b44c8f0262e903c5e17eda676614aec6f5c98 (thuth/qemu-kvm-cs)
JIRA: https://issues.redhat.com/browse/RHEL-72977
Enable virtio-mem on s390x now, too.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
configs/devices/s390x-softmmu/s390x-rh-devices.mak | 1 +
1 file changed, 1 insertion(+)
diff --git a/configs/devices/s390x-softmmu/s390x-rh-devices.mak b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
index 24cf6dbd03..834281d872 100644
--- a/configs/devices/s390x-softmmu/s390x-rh-devices.mak
+++ b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
@@ -12,6 +12,7 @@ CONFIG_VFIO_CCW=y
CONFIG_VFIO_PCI=y
CONFIG_VHOST_USER=y
CONFIG_VIRTIO_CCW=y
+CONFIG_VIRTIO_MEM=y
CONFIG_WDT_DIAG288=y
CONFIG_VHOST_VSOCK=y
CONFIG_VHOST_USER_VSOCK=y
--
2.48.1

View File

@ -0,0 +1,94 @@
From 2de79d978c2cd29ad686dd91e74a86dbf2121f1f Mon Sep 17 00:00:00 2001
From: Juraj Marcin <jmarcin@redhat.com>
Date: Wed, 4 Sep 2024 12:37:13 +0200
Subject: [PATCH 06/26] reset: Add RESET_TYPE_WAKEUP
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [6/26] 6169fe25bfa5715340c180ee8711d0ad61832106 (thuth/qemu-kvm-cs)
Some devices need to distinguish cold start reset from waking up from a
suspended state. This patch adds new value to the enum, and updates the
i386 wakeup method to use this new reset type.
Message-ID: <20240904103722.946194-3-jmarcin@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 759cbb4ee971da13ddfa8ad73befc2351d542044)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
docs/devel/reset.rst | 12 +++++++++++-
hw/i386/pc.c | 2 +-
include/hw/resettable.h | 2 ++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
index d2799eba7a..44bd51b42e 100644
--- a/docs/devel/reset.rst
+++ b/docs/devel/reset.rst
@@ -44,6 +44,17 @@ The Resettable interface handles reset types with an enum ``ResetType``:
value on each cold reset, such as RNG seed information, and which they
must not reinitialize on a snapshot-load reset.
+``RESET_TYPE_WAKEUP``
+ If the machine supports waking up from a suspended state and needs to reset
+ its devices during wake-up (from the ``MachineClass::wakeup()`` method), this
+ reset type should be used for such a request. Devices can utilize this reset
+ type to differentiate the reset requested during machine wake-up from other
+ reset requests. For example, RAM content must not be lost during wake-up, and
+ memory devices like virtio-mem that provide additional RAM must not reset
+ such state during wake-ups, but might do so during cold resets. However, this
+ reset type should not be used for wake-up detection, as not every machine
+ type issues a device reset request during wake-up.
+
``RESET_TYPE_S390_CPU_NORMAL``
This is only used for S390 CPU objects; it clears interrupts, stops
processing, and clears the TLB, but does not touch register contents.
@@ -53,7 +64,6 @@ The Resettable interface handles reset types with an enum ``ResetType``:
``RESET_TYPE_S390_CPU_NORMAL`` does and also clears the PSW, prefix,
FPC, timer and control registers. It does not touch gprs, fprs or acrs.
-
Devices which implement reset methods must treat any unknown ``ResetType``
as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
existing code we need to change if we add more types in future.
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index fedcf2a65f..fa9f16cbaf 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1889,7 +1889,7 @@ static void pc_machine_reset(MachineState *machine, ResetType type)
static void pc_machine_wakeup(MachineState *machine)
{
cpu_synchronize_all_states();
- pc_machine_reset(machine, RESET_TYPE_COLD);
+ pc_machine_reset(machine, RESET_TYPE_WAKEUP);
cpu_synchronize_all_post_reset();
}
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
index 83b561fc83..cf37cd5ead 100644
--- a/include/hw/resettable.h
+++ b/include/hw/resettable.h
@@ -29,6 +29,7 @@ typedef struct ResettableState ResettableState;
* Types of reset.
*
* + Cold: reset resulting from a power cycle of the object.
+ * + Wakeup: reset resulting from a wake-up from a suspended state.
*
* TODO: Support has to be added to handle more types. In particular,
* ResettableState structure needs to be expanded.
@@ -36,6 +37,7 @@ typedef struct ResettableState ResettableState;
typedef enum ResetType {
RESET_TYPE_COLD,
RESET_TYPE_SNAPSHOT_LOAD,
+ RESET_TYPE_WAKEUP,
RESET_TYPE_S390_CPU_INITIAL,
RESET_TYPE_S390_CPU_NORMAL,
} ResetType;
--
2.48.1

View File

@ -0,0 +1,360 @@
From 8d48193b5a661f31c1c1db068d241b31ae379339 Mon Sep 17 00:00:00 2001
From: Juraj Marcin <jmarcin@redhat.com>
Date: Wed, 4 Sep 2024 12:37:12 +0200
Subject: [PATCH 05/26] reset: Use ResetType for qemu_devices_reset() and
MachineClass::reset()
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [5/26] ea1324b27885d979bcc54cc355dbdf940686776c (thuth/qemu-kvm-cs)
Currently, both qemu_devices_reset() and MachineClass::reset() use
ShutdownCause for the reason of the reset. However, the Resettable
interface uses ResetState, so ShutdownCause needs to be translated to
ResetType somewhere. Translating it qemu_devices_reset() makes adding
new reset types harder, as they cannot always be matched to a single
ShutdownCause here, and devices may need to check the ResetType to
determine what to reset and if to reset at all.
This patch moves this translation up in the call stack to
qemu_system_reset() and updates all MachineClass children to use the
ResetType instead.
Message-ID: <20240904103722.946194-2-jmarcin@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 1b063fe2df002052cc2d10799764979b8c583480)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/arm/aspeed.c | 4 ++--
hw/arm/mps2-tz.c | 4 ++--
hw/core/reset.c | 5 +----
hw/hppa/machine.c | 4 ++--
hw/i386/microvm.c | 4 ++--
hw/i386/pc.c | 6 +++---
hw/ppc/pegasos2.c | 4 ++--
hw/ppc/pnv.c | 4 ++--
hw/ppc/spapr.c | 6 +++---
hw/s390x/s390-virtio-ccw.c | 4 ++--
include/hw/boards.h | 3 ++-
include/sysemu/reset.h | 5 +++--
system/runstate.c | 13 +++++++++++--
13 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index fd5603f7aa..cbca7685da 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1529,12 +1529,12 @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data)
aspeed_machine_class_init_cpus_defaults(mc);
}
-static void fby35_reset(MachineState *state, ShutdownCause reason)
+static void fby35_reset(MachineState *state, ResetType type)
{
AspeedMachineState *bmc = ASPEED_MACHINE(state);
AspeedGPIOState *gpio = &bmc->soc->gpio;
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
/* Board ID: 7 (Class-1, 4 slots) */
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index aec57c0d68..8edf57a66d 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -1254,7 +1254,7 @@ static void mps2_set_remap(Object *obj, const char *value, Error **errp)
}
}
-static void mps2_machine_reset(MachineState *machine, ShutdownCause reason)
+static void mps2_machine_reset(MachineState *machine, ResetType type)
{
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
@@ -1264,7 +1264,7 @@ static void mps2_machine_reset(MachineState *machine, ShutdownCause reason)
* reset see the correct mapping.
*/
remap_memory(mms, mms->remap);
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
}
static void mps2tz_class_init(ObjectClass *oc, void *data)
diff --git a/hw/core/reset.c b/hw/core/reset.c
index 58dfc8db3d..14a2639fbf 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -170,11 +170,8 @@ void qemu_unregister_resettable(Object *obj)
resettable_container_remove(get_root_reset_container(), obj);
}
-void qemu_devices_reset(ShutdownCause reason)
+void qemu_devices_reset(ResetType type)
{
- ResetType type = (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD) ?
- RESET_TYPE_SNAPSHOT_LOAD : RESET_TYPE_COLD;
-
/* Reset the simulation */
resettable_reset(OBJECT(get_root_reset_container()), type);
}
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 5d0a8739de..8259fe2e38 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -642,12 +642,12 @@ static void machine_HP_C3700_init(MachineState *machine)
machine_HP_common_init_tail(machine, pci_bus, translate);
}
-static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
+static void hppa_machine_reset(MachineState *ms, ResetType type)
{
unsigned int smp_cpus = ms->smp.cpus;
int i;
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
/* Start all CPUs at the firmware entry point.
* Monarch CPU will initialize firmware, secondary CPUs
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 40edcee7af..8ae4dff7f2 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -462,7 +462,7 @@ static void microvm_machine_state_init(MachineState *machine)
microvm_devices_init(mms);
}
-static void microvm_machine_reset(MachineState *machine, ShutdownCause reason)
+static void microvm_machine_reset(MachineState *machine, ResetType type)
{
MicrovmMachineState *mms = MICROVM_MACHINE(machine);
CPUState *cs;
@@ -475,7 +475,7 @@ static void microvm_machine_reset(MachineState *machine, ShutdownCause reason)
mms->kernel_cmdline_fixed = true;
}
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index fa0e42d072..fedcf2a65f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1869,12 +1869,12 @@ static void pc_machine_initfn(Object *obj)
qemu_add_machine_init_done_notifier(&pcms->machine_done);
}
-static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
+static void pc_machine_reset(MachineState *machine, ResetType type)
{
CPUState *cs;
X86CPU *cpu;
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
/* Reset APIC after devices have been reset to cancel
* any changes that qemu_devices_reset() might have done.
@@ -1889,7 +1889,7 @@ static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
static void pc_machine_wakeup(MachineState *machine)
{
cpu_synchronize_all_states();
- pc_machine_reset(machine, SHUTDOWN_CAUSE_NONE);
+ pc_machine_reset(machine, RESET_TYPE_COLD);
cpu_synchronize_all_post_reset();
}
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index 9b0a6b70ab..8ff4a00c34 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -291,14 +291,14 @@ static void pegasos2_superio_write(uint8_t addr, uint8_t val)
cpu_physical_memory_write(PCI1_IO_BASE + 0x3f1, &val, 1);
}
-static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason)
+static void pegasos2_machine_reset(MachineState *machine, ResetType type)
{
Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
void *fdt;
uint64_t d[2];
int sz;
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
if (!pm->vof) {
return; /* Firmware should set up machine so nothing to do */
}
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 3526852685..988fd55d88 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -709,13 +709,13 @@ static void pnv_powerdown_notify(Notifier *n, void *opaque)
}
}
-static void pnv_reset(MachineState *machine, ShutdownCause reason)
+static void pnv_reset(MachineState *machine, ResetType type)
{
PnvMachineState *pnv = PNV_MACHINE(machine);
IPMIBmc *bmc;
void *fdt;
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
/*
* The machine should provide by default an internal BMC simulator.
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 29e66f1b3f..11c953669a 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1725,7 +1725,7 @@ void spapr_check_mmu_mode(bool guest_radix)
}
}
-static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
+static void spapr_machine_reset(MachineState *machine, ResetType type)
{
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
PowerPCCPU *first_ppc_cpu;
@@ -1733,7 +1733,7 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
void *fdt;
int rc;
- if (reason != SHUTDOWN_CAUSE_SNAPSHOT_LOAD) {
+ if (type != RESET_TYPE_SNAPSHOT_LOAD) {
/*
* Record-replay snapshot load must not consume random, this was
* already replayed from initial machine reset.
@@ -1769,7 +1769,7 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
spapr_setup_hpt(spapr);
}
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
spapr_ovec_cleanup(spapr->ov5_cas);
spapr->ov5_cas = spapr_ovec_new();
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index ef2a9687c7..94cad1705b 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -434,7 +434,7 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms)
s390_pv_prep_reset();
}
-static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
+static void s390_machine_reset(MachineState *machine, ResetType type)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
enum s390_reset reset_type;
@@ -466,7 +466,7 @@ static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
* Device reset includes CPU clear resets so this has to be
* done AFTER the unprotect call above.
*/
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
s390_crypto_reset();
/* configure and start the ipl CPU only */
diff --git a/include/hw/boards.h b/include/hw/boards.h
index ffefc0a625..fe011b1e86 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -10,6 +10,7 @@
#include "qemu/module.h"
#include "qom/object.h"
#include "hw/core/cpu.h"
+#include "hw/resettable.h"
#define TYPE_MACHINE_SUFFIX "-machine"
@@ -253,7 +254,7 @@ struct MachineClass {
const char *deprecation_reason;
void (*init)(MachineState *state);
- void (*reset)(MachineState *state, ShutdownCause reason);
+ void (*reset)(MachineState *state, ResetType type);
void (*wakeup)(MachineState *state);
int (*kvm_type)(MachineState *machine, const char *arg);
diff --git a/include/sysemu/reset.h b/include/sysemu/reset.h
index ae436044a9..0e297c0e02 100644
--- a/include/sysemu/reset.h
+++ b/include/sysemu/reset.h
@@ -27,6 +27,7 @@
#ifndef QEMU_SYSEMU_RESET_H
#define QEMU_SYSEMU_RESET_H
+#include "hw/resettable.h"
#include "qapi/qapi-events-run-state.h"
typedef void QEMUResetHandler(void *opaque);
@@ -110,7 +111,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
/**
* qemu_devices_reset: Perform a complete system reset
- * @reason: reason for the reset
+ * @reason: type of the reset
*
* This function performs the low-level work needed to do a complete reset
* of the system (calling all the callbacks registered with
@@ -121,6 +122,6 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
* If you want to trigger a system reset from, for instance, a device
* model, don't use this function. Use qemu_system_reset_request().
*/
-void qemu_devices_reset(ShutdownCause reason);
+void qemu_devices_reset(ResetType type);
#endif
diff --git a/system/runstate.c b/system/runstate.c
index a0e2a5fd22..c2c9afa905 100644
--- a/system/runstate.c
+++ b/system/runstate.c
@@ -32,6 +32,7 @@
#include "exec/cpu-common.h"
#include "gdbstub/syscalls.h"
#include "hw/boards.h"
+#include "hw/resettable.h"
#include "migration/misc.h"
#include "migration/postcopy-ram.h"
#include "monitor/monitor.h"
@@ -507,15 +508,23 @@ static int qemu_debug_requested(void)
void qemu_system_reset(ShutdownCause reason)
{
MachineClass *mc;
+ ResetType type;
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
cpu_synchronize_all_states();
+ switch (reason) {
+ case SHUTDOWN_CAUSE_SNAPSHOT_LOAD:
+ type = RESET_TYPE_SNAPSHOT_LOAD;
+ break;
+ default:
+ type = RESET_TYPE_COLD;
+ }
if (mc && mc->reset) {
- mc->reset(current_machine, reason);
+ mc->reset(current_machine, type);
} else {
- qemu_devices_reset(reason);
+ qemu_devices_reset(type);
}
switch (reason) {
case SHUTDOWN_CAUSE_NONE:
--
2.48.1

View File

@ -0,0 +1,144 @@
From 1dd38383832fc27f2980f33bb5e10ec1af7e3fc3 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:07 +0100
Subject: [PATCH 15/26] s390x: introduce s390_get_memory_limit()
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [15/26] 5ae6a624a6541283cb15e90ebeb8fef3940c823b (thuth/qemu-kvm-cs)
Let's add s390_get_memory_limit(), to query what has been successfully
set via s390_set_memory_limit(). Allow setting the limit only once.
We'll remember the limit in the machine state. Move
s390_set_memory_limit() to machine code, merging it into
set_memory_limit(), because this really is a machine property.
Message-ID: <20241219144115.2820241-7-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 27221b69a3ea49339a1f82b9622126f3928e0915)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 17 ++++++++++++-----
include/hw/s390x/s390-virtio-ccw.h | 8 ++++++++
target/s390x/cpu-sysemu.c | 8 --------
target/s390x/cpu.h | 1 -
4 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 248ac28d20..f5f147eb92 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -45,6 +45,7 @@
#include "migration/blocker.h"
#include "qapi/visitor.h"
#include "hw/s390x/cpu-topology.h"
+#include "kvm/kvm_s390x.h"
#include CONFIG_DEVICES
static Error *pv_mig_blocker;
@@ -121,12 +122,16 @@ static void subsystem_reset(void)
}
}
-static void set_memory_limit(uint64_t new_limit)
+static void s390_set_memory_limit(S390CcwMachineState *s390ms,
+ uint64_t new_limit)
{
- uint64_t hw_limit;
- int ret;
+ uint64_t hw_limit = 0;
+ int ret = 0;
- ret = s390_set_memory_limit(new_limit, &hw_limit);
+ assert(!s390ms->memory_limit && new_limit);
+ if (kvm_enabled()) {
+ ret = kvm_s390_set_mem_limit(new_limit, &hw_limit);
+ }
if (ret == -E2BIG) {
error_report("host supports a maximum of %" PRIu64 " GB",
hw_limit / GiB);
@@ -135,10 +140,12 @@ static void set_memory_limit(uint64_t new_limit)
error_report("setting the guest size failed");
exit(EXIT_FAILURE);
}
+ s390ms->memory_limit = new_limit;
}
static void s390_memory_init(MachineState *machine)
{
+ S390CcwMachineState *s390ms = S390_CCW_MACHINE(machine);
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = machine->ram;
uint64_t ram_size = memory_region_size(ram);
@@ -154,7 +161,7 @@ static void s390_memory_init(MachineState *machine)
exit(EXIT_FAILURE);
}
- set_memory_limit(ram_size);
+ s390_set_memory_limit(s390ms, ram_size);
/* Map the initial memory. Must happen after setting the memory limit. */
memory_region_add_subregion(sysmem, 0, ram);
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index 996864a34e..de04336c5a 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -29,10 +29,18 @@ struct S390CcwMachineState {
bool dea_key_wrap;
bool pv;
uint8_t loadparm[8];
+ uint64_t memory_limit;
SCLPDevice *sclp;
};
+static inline uint64_t s390_get_memory_limit(S390CcwMachineState *s390ms)
+{
+ /* We expect to be called only after the limit was set. */
+ assert(s390ms->memory_limit);
+ return s390ms->memory_limit;
+}
+
#define S390_PTF_REASON_NONE (0x00 << 8)
#define S390_PTF_REASON_DONE (0x01 << 8)
#define S390_PTF_REASON_BUSY (0x02 << 8)
diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c
index 1cd30c1d84..3118a25fee 100644
--- a/target/s390x/cpu-sysemu.c
+++ b/target/s390x/cpu-sysemu.c
@@ -255,14 +255,6 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
return s390_count_running_cpus();
}
-int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
-{
- if (kvm_enabled()) {
- return kvm_s390_set_mem_limit(new_limit, hw_limit);
- }
- return 0;
-}
-
void s390_set_max_pagesize(uint64_t pagesize, Error **errp)
{
if (kvm_enabled()) {
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 6a64472403..ecaf3191d2 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -881,7 +881,6 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
/* cpu.c */
void s390_crypto_reset(void);
-int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void s390_cmma_reset(void);
void s390_enable_css_support(S390CPU *cpu);
--
2.48.1

View File

@ -0,0 +1,46 @@
From 9d5420c4370b74d60f082f2aa1225b19150ee629 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:12 +0100
Subject: [PATCH 20/26] s390x/pv: prepare for memory devices
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [20/26] cdbe71168b9afa9657b94f1e7500568314c707a8 (thuth/qemu-kvm-cs)
Let's avoid checking for the maxram_size, and instead rely on the memory
limit determined in s390_memory_init(), that might be larger than
maxram_size, for example due to alignment purposes.
This check now correctly mimics what the kernel will check in
kvm_s390_pv_set_aside(), whereby a VM <= 2 GiB VM would end up using
a segment type ASCE.
Message-ID: <20241219144115.2820241-12-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit a056332e732110c8ef0d40ffd49bd03afc2f04ca)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
target/s390x/kvm/pv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/s390x/kvm/pv.c b/target/s390x/kvm/pv.c
index 424cce75ca..fa66607e7b 100644
--- a/target/s390x/kvm/pv.c
+++ b/target/s390x/kvm/pv.c
@@ -133,7 +133,7 @@ bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms)
* If the feature is not present or if the VM is not larger than 2 GiB,
* KVM_PV_ASYNC_CLEANUP_PREPARE fill fail; no point in attempting it.
*/
- if ((MACHINE(ms)->ram_size <= 2 * GiB) ||
+ if (s390_get_memory_limit(ms) <= 2 * GiB ||
!kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) {
return false;
}
--
2.48.1

View File

@ -0,0 +1,107 @@
From 5a311d410bca4a5530a51c0b789ce8525d2d0653 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:13 +0100
Subject: [PATCH 21/26] s390x: remember the maximum page size
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [21/26] 3b97c555b153d42e4fcb27dbb65fbf3edac622a4 (thuth/qemu-kvm-cs)
Let's remember the value (successfully) set via s390_set_max_pagesize().
This will be helpful to reject hotplugged memory devices that would exceed
this initially set page size.
Handle it just like how we handle s390_get_memory_limit(), storing it in
the machine, and moving the handling to machine code.
Message-ID: <20241219144115.2820241-13-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit df2ac211a62e6ced7f1495b634fa6f78962f2321)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 12 +++++++++++-
include/hw/s390x/s390-virtio-ccw.h | 1 +
target/s390x/cpu-sysemu.c | 7 -------
target/s390x/cpu.h | 1 -
4 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 824c73536a..bd05a22b4e 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -143,6 +143,16 @@ static void s390_set_memory_limit(S390CcwMachineState *s390ms,
s390ms->memory_limit = new_limit;
}
+static void s390_set_max_pagesize(S390CcwMachineState *s390ms,
+ uint64_t pagesize)
+{
+ assert(!s390ms->max_pagesize && pagesize);
+ if (kvm_enabled()) {
+ kvm_s390_set_max_pagesize(pagesize, &error_fatal);
+ }
+ s390ms->max_pagesize = pagesize;
+}
+
static void s390_memory_init(MachineState *machine)
{
S390CcwMachineState *s390ms = S390_CCW_MACHINE(machine);
@@ -191,7 +201,7 @@ static void s390_memory_init(MachineState *machine)
* Configure the maximum page size. As no memory devices were created
* yet, this is the page size of initial memory only.
*/
- s390_set_max_pagesize(qemu_maxrampagesize(), &error_fatal);
+ s390_set_max_pagesize(s390ms, qemu_maxrampagesize());
/* Initialize storage key device */
s390_skeys_init();
/* Initialize storage attributes device */
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index de04336c5a..599740a998 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -30,6 +30,7 @@ struct S390CcwMachineState {
bool pv;
uint8_t loadparm[8];
uint64_t memory_limit;
+ uint64_t max_pagesize;
SCLPDevice *sclp;
};
diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c
index 3118a25fee..706a5c53e2 100644
--- a/target/s390x/cpu-sysemu.c
+++ b/target/s390x/cpu-sysemu.c
@@ -255,13 +255,6 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
return s390_count_running_cpus();
}
-void s390_set_max_pagesize(uint64_t pagesize, Error **errp)
-{
- if (kvm_enabled()) {
- kvm_s390_set_max_pagesize(pagesize, errp);
- }
-}
-
void s390_cmma_reset(void)
{
if (kvm_enabled()) {
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index ecaf3191d2..9770a62ac9 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -881,7 +881,6 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
/* cpu.c */
void s390_crypto_reset(void);
-void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void s390_cmma_reset(void);
void s390_enable_css_support(S390CPU *cpu);
void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg);
--
2.48.1

View File

@ -0,0 +1,113 @@
From 2fbdf7e3cf23daea470aaa4a29e16641feb76f3c Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:05 +0100
Subject: [PATCH 13/26] s390x: rename s390-virtio-hcall* to s390-hypercall*
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [13/26] 3c1ef3cbb137517b306871f0a88a61a59740af5a (thuth/qemu-kvm-cs)
Let's make it clearer that we are talking about general
QEMU/KVM-specific hypercalls.
Message-ID: <20241219144115.2820241-5-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 85489fc3652d0c4433c940f1a80a952e8cb5d3cb)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/meson.build | 2 +-
hw/s390x/{s390-virtio-hcall.c => s390-hypercall.c} | 2 +-
hw/s390x/{s390-virtio-hcall.h => s390-hypercall.h} | 6 +++---
target/s390x/kvm/kvm.c | 2 +-
target/s390x/tcg/misc_helper.c | 2 +-
5 files changed, 7 insertions(+), 7 deletions(-)
rename hw/s390x/{s390-virtio-hcall.c => s390-hypercall.c} (97%)
rename hw/s390x/{s390-virtio-hcall.h => s390-hypercall.h} (86%)
diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build
index d6c8c33915..e344a3bd8c 100644
--- a/hw/s390x/meson.build
+++ b/hw/s390x/meson.build
@@ -29,7 +29,7 @@ s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
))
s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files(
's390-virtio-ccw.c',
- 's390-virtio-hcall.c',
+ 's390-hypercall.c',
))
s390x_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('3270-ccw.c'))
s390x_ss.add(when: 'CONFIG_VFIO', if_true: files('s390-pci-vfio.c'))
diff --git a/hw/s390x/s390-virtio-hcall.c b/hw/s390x/s390-hypercall.c
similarity index 97%
rename from hw/s390x/s390-virtio-hcall.c
rename to hw/s390x/s390-hypercall.c
index 5fb78a719e..f816c2b1ef 100644
--- a/hw/s390x/s390-virtio-hcall.c
+++ b/hw/s390x/s390-hypercall.c
@@ -12,7 +12,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "hw/boards.h"
-#include "hw/s390x/s390-virtio-hcall.h"
+#include "hw/s390x/s390-hypercall.h"
#include "hw/s390x/ioinst.h"
#include "hw/s390x/css.h"
#include "virtio-ccw.h"
diff --git a/hw/s390x/s390-virtio-hcall.h b/hw/s390x/s390-hypercall.h
similarity index 86%
rename from hw/s390x/s390-virtio-hcall.h
rename to hw/s390x/s390-hypercall.h
index dca456b926..2fa81dbfdd 100644
--- a/hw/s390x/s390-virtio-hcall.h
+++ b/hw/s390x/s390-hypercall.h
@@ -9,8 +9,8 @@
* directory.
*/
-#ifndef HW_S390_VIRTIO_HCALL_H
-#define HW_S390_VIRTIO_HCALL_H
+#ifndef HW_S390_HYPERCALL_H
+#define HW_S390_HYPERCALL_H
#include "cpu.h"
@@ -21,4 +21,4 @@
void handle_diag_500(S390CPU *cpu, uintptr_t ra);
-#endif /* HW_S390_VIRTIO_HCALL_H */
+#endif /* HW_S390_HYPERCALL_H */
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 42d6a54126..afc8d570c9 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -49,7 +49,7 @@
#include "hw/s390x/ebcdic.h"
#include "exec/memattrs.h"
#include "hw/s390x/s390-virtio-ccw.h"
-#include "hw/s390x/s390-virtio-hcall.h"
+#include "hw/s390x/s390-hypercall.h"
#include "target/s390x/kvm/pv.h"
#include CONFIG_DEVICES
diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c
index 2b4310003b..b726a95352 100644
--- a/target/s390x/tcg/misc_helper.c
+++ b/target/s390x/tcg/misc_helper.c
@@ -36,7 +36,7 @@
#include "sysemu/cpus.h"
#include "sysemu/sysemu.h"
#include "hw/s390x/ebcdic.h"
-#include "hw/s390x/s390-virtio-hcall.h"
+#include "hw/s390x/s390-hypercall.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/ioinst.h"
--
2.48.1

View File

@ -0,0 +1,99 @@
From 86417a068f24964422d4fd5ea301d70a0f8142d2 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:08 +0100
Subject: [PATCH 16/26] s390x/s390-hypercall: introduce DIAG500 STORAGE_LIMIT
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [16/26] c1c341227388735450ddbba0201e7523e0658c07 (thuth/qemu-kvm-cs)
A guest OS that supports memory hotplug / memory devices must during
boot be aware of the maximum possible physical memory address that it might
have to handle at a later stage during its runtime.
For example, the maximum possible memory address might be required to
prepare the kernel virtual address space accordingly (e.g., select page
table hierarchy depth).
On s390x there is currently no such mechanism that is compatible with
paravirtualized memory devices, because the whole SCLP interface was
designed around the idea of "storage increments" and "standby memory".
Paravirtualized memory devices we want to support, such as virtio-mem, have
no intersection with any of that, but could co-exist with them in the
future if ever needed.
In particular, a guest OS must never detect and use device memory
without the help of a proper device driver. Device memory must not be
exposed in any firmware-provided memory map (SCLP or diag260 on s390x).
For this reason, these memory devices will be places in memory *above*
the "maximum storage increment" exposed via SCLP.
Let's provide a new diag500 subcode to query the memory limit determined in
s390_memory_init().
Message-ID: <20241219144115.2820241-8-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit f7c168657816486527727d860b73747d41f0c5f6)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-hypercall.c | 12 +++++++++++-
hw/s390x/s390-hypercall.h | 1 +
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/hw/s390x/s390-hypercall.c b/hw/s390x/s390-hypercall.c
index f816c2b1ef..ac1b08b2cd 100644
--- a/hw/s390x/s390-hypercall.c
+++ b/hw/s390x/s390-hypercall.c
@@ -11,7 +11,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
-#include "hw/boards.h"
+#include "hw/s390x/s390-virtio-ccw.h"
#include "hw/s390x/s390-hypercall.h"
#include "hw/s390x/ioinst.h"
#include "hw/s390x/css.h"
@@ -57,6 +57,13 @@ static int handle_virtio_ccw_notify(uint64_t subch_id, uint64_t data)
return 0;
}
+static uint64_t handle_storage_limit(void)
+{
+ S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
+
+ return s390_get_memory_limit(s390ms) - 1;
+}
+
void handle_diag_500(S390CPU *cpu, uintptr_t ra)
{
CPUS390XState *env = &cpu->env;
@@ -69,6 +76,9 @@ void handle_diag_500(S390CPU *cpu, uintptr_t ra)
case DIAG500_VIRTIO_CCW_NOTIFY:
env->regs[2] = handle_virtio_ccw_notify(env->regs[2], env->regs[3]);
break;
+ case DIAG500_STORAGE_LIMIT:
+ env->regs[2] = handle_storage_limit();
+ break;
default:
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
}
diff --git a/hw/s390x/s390-hypercall.h b/hw/s390x/s390-hypercall.h
index 2fa81dbfdd..4f07209128 100644
--- a/hw/s390x/s390-hypercall.h
+++ b/hw/s390x/s390-hypercall.h
@@ -18,6 +18,7 @@
#define DIAG500_VIRTIO_RESET 1 /* legacy */
#define DIAG500_VIRTIO_SET_STATUS 2 /* legacy */
#define DIAG500_VIRTIO_CCW_NOTIFY 3 /* KVM_S390_VIRTIO_CCW_NOTIFY */
+#define DIAG500_STORAGE_LIMIT 4
void handle_diag_500(S390CPU *cpu, uintptr_t ra);
--
2.48.1

View File

@ -0,0 +1,56 @@
From 53d1b43699c6b30583f41a18a33c28893718aeac Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:10 +0100
Subject: [PATCH 18/26] s390x/s390-skeys: prepare for memory devices
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [18/26] 47edda0eeb6d5932f81633f2d9d294b1ca5f413c (thuth/qemu-kvm-cs)
With memory devices, we will have storage keys for memory that
exceeds the initial ram size.
The TODO already states that current handling is subopimal,
but we won't worry about improving that (TCG-only) thing for now.
Message-ID: <20241219144115.2820241-10-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit d1e3c2ac41b3f73708682e4e8212c32ad35013b9)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-skeys.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index bf22d6863e..e4297b3b8a 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -11,7 +11,7 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
-#include "hw/boards.h"
+#include "hw/s390x/s390-virtio-ccw.h"
#include "hw/qdev-properties.h"
#include "hw/s390x/storage-keys.h"
#include "qapi/error.h"
@@ -251,9 +251,9 @@ static bool qemu_s390_enable_skeys(S390SKeysState *ss)
* g_once_init_enter() is good enough.
*/
if (g_once_init_enter(&initialized)) {
- MachineState *machine = MACHINE(qdev_get_machine());
+ S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
- skeys->key_count = machine->ram_size / TARGET_PAGE_SIZE;
+ skeys->key_count = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
skeys->keydata = g_malloc0(skeys->key_count);
g_once_init_leave(&initialized, 1);
}
--
2.48.1

View File

@ -0,0 +1,155 @@
From 1195c91d10892a888870248fd881612955b9e1eb Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:09 +0100
Subject: [PATCH 17/26] s390x/s390-stattrib-kvm: prepare for memory devices and
sparse memory layouts
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [17/26] 799aa7b2b9cc2a948e9f391bc0ecf739254c78b1 (thuth/qemu-kvm-cs)
With memory devices, we will have storage attributes for memory that
exceeds the initial ram size. Further, we can easily have memory holes,
for which there (currently) are no storage attributes.
In particular, with memory holes, KVM_S390_SET_CMMA_BITS will fail to set
some storage attributes.
So let's do it like we handle storage keys migration, relying on
guest_phys_blocks_append(). However, in contrast to storage key
migration, we will handle it on the migration destination.
This is a preparation for virtio-mem support. Note that ever since the
"early migration" feature was added (x-early-migration), the state
of device blocks (plugged/unplugged) is migrated early such that
guest_phys_blocks_append() will properly consider all currently plugged
memory blocks and skip any unplugged ones.
In the future, we should try getting rid of the large temporary buffer
and also not send any attributes for any memory holes, just so they
get ignored on the destination.
Message-ID: <20241219144115.2820241-9-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 241e6b2d27b090b17cda5b011b2064544b0c458b)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-stattrib-kvm.c | 67 +++++++++++++++++++++++-------------
1 file changed, 43 insertions(+), 24 deletions(-)
diff --git a/hw/s390x/s390-stattrib-kvm.c b/hw/s390x/s390-stattrib-kvm.c
index eeaa811098..33ec91422a 100644
--- a/hw/s390x/s390-stattrib-kvm.c
+++ b/hw/s390x/s390-stattrib-kvm.c
@@ -10,11 +10,12 @@
*/
#include "qemu/osdep.h"
-#include "hw/boards.h"
+#include "hw/s390x/s390-virtio-ccw.h"
#include "migration/qemu-file.h"
#include "hw/s390x/storage-attributes.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
+#include "sysemu/memory_mapping.h"
#include "exec/ram_addr.h"
#include "kvm/kvm_s390x.h"
#include "qapi/error.h"
@@ -84,8 +85,8 @@ static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
uint8_t *values)
{
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
- MachineState *machine = MACHINE(qdev_get_machine());
- unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
+ S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
+ unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
if (start_gfn + count > max) {
error_report("Out of memory bounds when setting storage attributes");
@@ -103,39 +104,57 @@ static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
{
KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
- MachineState *machine = MACHINE(qdev_get_machine());
- unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
- /* We do not need to reach the maximum buffer size allowed */
- unsigned long cx, len = KVM_S390_SKEYS_MAX / 2;
+ S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
+ unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
+ unsigned long start_gfn, end_gfn, pages;
+ GuestPhysBlockList guest_phys_blocks;
+ GuestPhysBlock *block;
int r;
struct kvm_s390_cmma_log clog = {
.flags = 0,
.mask = ~0ULL,
};
- if (sas->incoming_buffer) {
- for (cx = 0; cx + len <= max; cx += len) {
- clog.start_gfn = cx;
- clog.count = len;
- clog.values = (uint64_t)(sas->incoming_buffer + cx);
- r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
- if (r) {
- error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
- return;
- }
- }
- if (cx < max) {
- clog.start_gfn = cx;
- clog.count = max - cx;
- clog.values = (uint64_t)(sas->incoming_buffer + cx);
+ if (!sas->incoming_buffer) {
+ return;
+ }
+ guest_phys_blocks_init(&guest_phys_blocks);
+ guest_phys_blocks_append(&guest_phys_blocks);
+
+ QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
+ assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE));
+ assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE));
+
+ start_gfn = block->target_start / TARGET_PAGE_SIZE;
+ end_gfn = block->target_end / TARGET_PAGE_SIZE;
+
+ while (start_gfn < end_gfn) {
+ /* Don't exceed the maximum buffer size. */
+ pages = MIN(end_gfn - start_gfn, KVM_S390_SKEYS_MAX / 2);
+
+ /*
+ * If we ever get guest physical memory beyond the configured
+ * memory limit, something went very wrong.
+ */
+ assert(start_gfn + pages <= max);
+
+ clog.start_gfn = start_gfn;
+ clog.count = pages;
+ clog.values = (uint64_t)(sas->incoming_buffer + start_gfn);
r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
if (r) {
error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
+ goto out;
}
+
+ start_gfn += pages;
}
- g_free(sas->incoming_buffer);
- sas->incoming_buffer = NULL;
}
+
+out:
+ guest_phys_blocks_free(&guest_phys_blocks);
+ g_free(sas->incoming_buffer);
+ sas->incoming_buffer = NULL;
}
static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val,
--
2.48.1

View File

@ -0,0 +1,63 @@
From 4ee3076ac566622929f9410636483c4f0b2da967 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:02 +0100
Subject: [PATCH 10/26] s390x/s390-virtio-ccw: don't crash on weird RAM sizes
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [10/26] 55738da52f3cf4746bee2b17780a10720fa05863 (thuth/qemu-kvm-cs)
KVM is not happy when starting a VM with weird RAM sizes:
# qemu-system-s390x --enable-kvm --nographic -m 1234K
qemu-system-s390x: kvm_set_user_memory_region: KVM_SET_USER_MEMORY_REGION
failed, slot=0, start=0x0, size=0x244000: Invalid argument
kvm_set_phys_mem: error registering slot: Invalid argument
Aborted (core dumped)
Let's handle that in a better way by rejecting such weird RAM sizes
right from the start:
# qemu-system-s390x --enable-kvm --nographic -m 1234K
qemu-system-s390x: ram size must be multiples of 1 MiB
Message-ID: <20241219144115.2820241-2-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Janosch Frank <frankja@linux.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 14e568ab4836347481af2e334009c385f456a734)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 94cad1705b..82ded9666c 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -180,6 +180,17 @@ static void s390_memory_init(MemoryRegion *ram)
{
MemoryRegion *sysmem = get_system_memory();
+ if (!QEMU_IS_ALIGNED(memory_region_size(ram), 1 * MiB)) {
+ /*
+ * SCLP cannot possibly expose smaller granularity right now and KVM
+ * cannot handle smaller granularity. As we don't support NUMA, the
+ * region size directly corresponds to machine->ram_size, and the region
+ * is a single RAM memory region.
+ */
+ error_report("ram size must be multiples of 1 MiB");
+ exit(EXIT_FAILURE);
+ }
+
/* allocate RAM for core */
memory_region_add_subregion(sysmem, 0, ram);
--
2.48.1

View File

@ -0,0 +1,140 @@
From 9ec2d356210f1e66f50519cc4d58633a13db9004 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:06 +0100
Subject: [PATCH 14/26] s390x/s390-virtio-ccw: move setting the maximum guest
size from sclp to machine code
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [14/26] a5970c1c6d8d09a473a25a7eee533ec3a6711ec8 (thuth/qemu-kvm-cs)
Nowadays, it feels more natural to have that code located in
s390_memory_init(), where we also have direct access to the machine
object.
While at it, use the actual RAM size, not the maximum RAM size which
cannot currently be reached without support for any memory devices.
Consequently update s390_pv_vm_try_disable_async() to rely on the RAM size
as well, to avoid temporary issues while we further rework that
handling.
set_memory_limit() is temporary, we'll merge it with
s390_set_memory_limit() next.
Message-ID: <20241219144115.2820241-6-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 3c6fb557d295949bea291c3bf88ee9c83392e78c)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 28 ++++++++++++++++++++++++----
hw/s390x/sclp.c | 11 -----------
target/s390x/kvm/pv.c | 2 +-
3 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d47e99028e..248ac28d20 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -121,11 +121,29 @@ static void subsystem_reset(void)
}
}
-static void s390_memory_init(MemoryRegion *ram)
+static void set_memory_limit(uint64_t new_limit)
+{
+ uint64_t hw_limit;
+ int ret;
+
+ ret = s390_set_memory_limit(new_limit, &hw_limit);
+ if (ret == -E2BIG) {
+ error_report("host supports a maximum of %" PRIu64 " GB",
+ hw_limit / GiB);
+ exit(EXIT_FAILURE);
+ } else if (ret) {
+ error_report("setting the guest size failed");
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void s390_memory_init(MachineState *machine)
{
MemoryRegion *sysmem = get_system_memory();
+ MemoryRegion *ram = machine->ram;
+ uint64_t ram_size = memory_region_size(ram);
- if (!QEMU_IS_ALIGNED(memory_region_size(ram), 1 * MiB)) {
+ if (!QEMU_IS_ALIGNED(ram_size, 1 * MiB)) {
/*
* SCLP cannot possibly expose smaller granularity right now and KVM
* cannot handle smaller granularity. As we don't support NUMA, the
@@ -136,7 +154,9 @@ static void s390_memory_init(MemoryRegion *ram)
exit(EXIT_FAILURE);
}
- /* allocate RAM for core */
+ set_memory_limit(ram_size);
+
+ /* Map the initial memory. Must happen after setting the memory limit. */
memory_region_add_subregion(sysmem, 0, ram);
/*
@@ -211,7 +231,7 @@ static void ccw_init(MachineState *machine)
qdev_realize_and_unref(DEVICE(ms->sclp), NULL, &error_fatal);
/* init memory + setup max page size. Required for the CPU model */
- s390_memory_init(machine->ram);
+ s390_memory_init(machine);
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
s390_init_cpus(machine);
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 8757626b5c..73e88ab4eb 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -376,10 +376,7 @@ void sclp_service_interrupt(uint32_t sccb)
/* qemu object creation and initialization functions */
static void sclp_realize(DeviceState *dev, Error **errp)
{
- MachineState *machine = MACHINE(qdev_get_machine());
SCLPDevice *sclp = SCLP(dev);
- uint64_t hw_limit;
- int ret;
/*
* qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
@@ -389,14 +386,6 @@ static void sclp_realize(DeviceState *dev, Error **errp)
if (!sysbus_realize(SYS_BUS_DEVICE(sclp->event_facility), errp)) {
return;
}
-
- ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
- if (ret == -E2BIG) {
- error_setg(errp, "host supports a maximum of %" PRIu64 " GB",
- hw_limit / GiB);
- } else if (ret) {
- error_setg(errp, "setting the guest size failed");
- }
}
static void sclp_memory_init(SCLPDevice *sclp)
diff --git a/target/s390x/kvm/pv.c b/target/s390x/kvm/pv.c
index dde836d21a..424cce75ca 100644
--- a/target/s390x/kvm/pv.c
+++ b/target/s390x/kvm/pv.c
@@ -133,7 +133,7 @@ bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms)
* If the feature is not present or if the VM is not larger than 2 GiB,
* KVM_PV_ASYNC_CLEANUP_PREPARE fill fail; no point in attempting it.
*/
- if ((MACHINE(ms)->maxram_size <= 2 * GiB) ||
+ if ((MACHINE(ms)->ram_size <= 2 * GiB) ||
!kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) {
return false;
}
--
2.48.1

View File

@ -0,0 +1,117 @@
From 0e7d7bf86fb242c1ea90bf9648fb061626790eda Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:11 +0100
Subject: [PATCH 19/26] s390x/s390-virtio-ccw: prepare for memory devices
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [19/26] 2441c8c5f5a06d5ca93188dd44e8a08f06d1722b (thuth/qemu-kvm-cs)
Let's prepare our address space for memory devices if enabled via
"maxmem" and if we have CONFIG_MEM_DEVICE enabled at all. Note that
CONFIG_MEM_DEVICE will be selected automatically once we add support
for devices.
Just like on other architectures, the region container for memory devices
is placed directly above our initial memory. For now, we only align the
start address of the region up to 1 GiB, but we won't add any additional
space to the region for internal alignment purposes; this can be done in
the future if really required.
The RAM size returned via SCLP is not modified, as this only
covers initial RAM (and standby memory we don't implement) and not memory
devices; clarify that in the docs of read_SCP_info(). Existing OSes without
support for memory devices will keep working as is, even when memory
devices would be attached the VM.
Guest OSs which support memory devices, such as virtio-mem, will
consult diag500(), to find out the maximum possible pfn. Guest OSes that
don't support memory devices, don't have to be changed and will continue
relying on information provided by SCLP.
There are no remaining maxram_size users in s390x code, and the remaining
ram_size users only care about initial RAM:
* hw/s390x/ipl.c
* hw/s390x/s390-hypercall.c
* hw/s390x/sclp.c
* target/s390x/kvm/pv.c
Message-ID: <20241219144115.2820241-11-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 1e86400298cf0fed5f7d49427db477775b859093)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 23 ++++++++++++++++++++++-
hw/s390x/sclp.c | 6 +++++-
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index f5f147eb92..824c73536a 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -149,6 +149,7 @@ static void s390_memory_init(MachineState *machine)
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = machine->ram;
uint64_t ram_size = memory_region_size(ram);
+ uint64_t devmem_base, devmem_size;
if (!QEMU_IS_ALIGNED(ram_size, 1 * MiB)) {
/*
@@ -161,11 +162,31 @@ static void s390_memory_init(MachineState *machine)
exit(EXIT_FAILURE);
}
- s390_set_memory_limit(s390ms, ram_size);
+ devmem_size = 0;
+ devmem_base = ram_size;
+#ifdef CONFIG_MEM_DEVICE
+ if (machine->ram_size < machine->maxram_size) {
+
+ /*
+ * Make sure memory devices have a sane default alignment, even
+ * when weird initial memory sizes are specified.
+ */
+ devmem_base = QEMU_ALIGN_UP(devmem_base, 1 * GiB);
+ devmem_size = machine->maxram_size - machine->ram_size;
+ }
+#endif
+ s390_set_memory_limit(s390ms, devmem_base + devmem_size);
/* Map the initial memory. Must happen after setting the memory limit. */
memory_region_add_subregion(sysmem, 0, ram);
+ /* Initialize address space for memory devices. */
+#ifdef CONFIG_MEM_DEVICE
+ if (devmem_size) {
+ machine_memory_devices_init(machine, devmem_base, devmem_size);
+ }
+#endif /* CONFIG_MEM_DEVICE */
+
/*
* Configure the maximum page size. As no memory devices were created
* yet, this is the page size of initial memory only.
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 73e88ab4eb..5945c9b1d8 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -161,7 +161,11 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
read_info->rnsize2 = cpu_to_be32(rnsize);
}
- /* we don't support standby memory, maxram_size is never exposed */
+ /*
+ * We don't support standby memory. maxram_size is used for sizing the
+ * memory device region, which is not exposed through SCLP but through
+ * diag500.
+ */
rnmax = machine->ram_size >> sclp->increment_size;
if (rnmax < 0x10000) {
read_info->rnmax = cpu_to_be16(rnmax);
--
2.48.1

View File

@ -0,0 +1,163 @@
From d2764db41fc6edcead9ad27b8d31e7bff524c0c0 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:04 +0100
Subject: [PATCH 12/26] s390x/s390-virtio-hcall: prepare for more diag500
hypercalls
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [12/26] 6573602d71b9e70679a48315f913309be29d6239 (thuth/qemu-kvm-cs)
Let's generalize, abstracting the virtio bits. diag500 is now a generic
hypercall to handle QEMU/KVM specific things. Explicitly specify all
already defined subcodes, including legacy ones (so we know what we can
use for new hypercalls).
Move the PGM_SPECIFICATION injection into the renamed function
handle_diag_500(), so we can turn it into a void function.
We'll rename the files separately, so git properly detects the rename.
Message-ID: <20241219144115.2820241-4-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 6e9cc2da4e8b997fd6ff3249034f436b84fc7974)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-hcall.c | 15 ++++++++-------
hw/s390x/s390-virtio-hcall.h | 11 ++++++-----
target/s390x/kvm/kvm.c | 20 +++-----------------
target/s390x/tcg/misc_helper.c | 5 +++--
4 files changed, 20 insertions(+), 31 deletions(-)
diff --git a/hw/s390x/s390-virtio-hcall.c b/hw/s390x/s390-virtio-hcall.c
index ca49e3cd22..5fb78a719e 100644
--- a/hw/s390x/s390-virtio-hcall.c
+++ b/hw/s390x/s390-virtio-hcall.c
@@ -1,5 +1,5 @@
/*
- * Support for virtio hypercalls on s390
+ * Support for QEMU/KVM hypercalls on s390
*
* Copyright 2012 IBM Corp.
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -57,18 +57,19 @@ static int handle_virtio_ccw_notify(uint64_t subch_id, uint64_t data)
return 0;
}
-int s390_virtio_hypercall(CPUS390XState *env)
+void handle_diag_500(S390CPU *cpu, uintptr_t ra)
{
+ CPUS390XState *env = &cpu->env;
const uint64_t subcode = env->regs[1];
switch (subcode) {
- case KVM_S390_VIRTIO_NOTIFY:
+ case DIAG500_VIRTIO_NOTIFY:
env->regs[2] = handle_virtio_notify(env->regs[2]);
- return 0;
- case KVM_S390_VIRTIO_CCW_NOTIFY:
+ break;
+ case DIAG500_VIRTIO_CCW_NOTIFY:
env->regs[2] = handle_virtio_ccw_notify(env->regs[2], env->regs[3]);
- return 0;
+ break;
default:
- return -EINVAL;
+ s390_program_interrupt(env, PGM_SPECIFICATION, ra);
}
}
diff --git a/hw/s390x/s390-virtio-hcall.h b/hw/s390x/s390-virtio-hcall.h
index 3d9fe147d2..dca456b926 100644
--- a/hw/s390x/s390-virtio-hcall.h
+++ b/hw/s390x/s390-virtio-hcall.h
@@ -1,5 +1,5 @@
/*
- * Support for virtio hypercalls on s390x
+ * Support for QEMU/KVM hypercalls on s390x
*
* Copyright IBM Corp. 2012, 2017
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -12,12 +12,13 @@
#ifndef HW_S390_VIRTIO_HCALL_H
#define HW_S390_VIRTIO_HCALL_H
-#include "standard-headers/asm-s390/virtio-ccw.h"
#include "cpu.h"
-/* The only thing that we need from the old kvm_virtio.h file */
-#define KVM_S390_VIRTIO_NOTIFY 0
+#define DIAG500_VIRTIO_NOTIFY 0 /* legacy, implemented as a NOP */
+#define DIAG500_VIRTIO_RESET 1 /* legacy */
+#define DIAG500_VIRTIO_SET_STATUS 2 /* legacy */
+#define DIAG500_VIRTIO_CCW_NOTIFY 3 /* KVM_S390_VIRTIO_CCW_NOTIFY */
-int s390_virtio_hypercall(CPUS390XState *env);
+void handle_diag_500(S390CPU *cpu, uintptr_t ra);
#endif /* HW_S390_VIRTIO_HCALL_H */
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 5947dda829..42d6a54126 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -1492,22 +1492,6 @@ static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl)
return r;
}
-static int handle_hypercall(S390CPU *cpu, struct kvm_run *run)
-{
- CPUS390XState *env = &cpu->env;
- int ret = -EINVAL;
-
-#ifdef CONFIG_S390_CCW_VIRTIO
- ret = s390_virtio_hypercall(env);
-#endif /* CONFIG_S390_CCW_VIRTIO */
- if (ret == -EINVAL) {
- kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
- return 0;
- }
-
- return ret;
-}
-
static void kvm_handle_diag_288(S390CPU *cpu, struct kvm_run *run)
{
uint64_t r1, r3;
@@ -1603,9 +1587,11 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
case DIAG_SET_CONTROL_PROGRAM_CODES:
handle_diag_318(cpu, run);
break;
+#ifdef CONFIG_S390_CCW_VIRTIO
case DIAG_KVM_HYPERCALL:
- r = handle_hypercall(cpu, run);
+ handle_diag_500(cpu, RA_IGNORED);
break;
+#endif /* CONFIG_S390_CCW_VIRTIO */
case DIAG_KVM_BREAKPOINT:
r = handle_sw_breakpoint(cpu, run);
break;
diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c
index f44136a568..2b4310003b 100644
--- a/target/s390x/tcg/misc_helper.c
+++ b/target/s390x/tcg/misc_helper.c
@@ -119,10 +119,11 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
switch (num) {
#ifdef CONFIG_S390_CCW_VIRTIO
case 0x500:
- /* KVM hypercall */
+ /* QEMU/KVM hypercall */
bql_lock();
- r = s390_virtio_hypercall(env);
+ handle_diag_500(env_archcpu(env), GETPC());
bql_unlock();
+ r = 0;
break;
#endif /* CONFIG_S390_CCW_VIRTIO */
case 0x44:
--
2.48.1

View File

@ -0,0 +1,296 @@
From 16ccb16d393a3e63936dc993c30c67fdecb1f120 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:03 +0100
Subject: [PATCH 11/26] s390x/s390-virtio-hcall: remove hypercall registration
mechanism
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [11/26] 5e8d2720fe9fd6e6e24487d71988821f1cf27f17 (thuth/qemu-kvm-cs)
Nowadays, we only have a single machine type in QEMU, everything is based
on virtio-ccw and the traditional virtio machine does no longer exist. No
need to dynamically register diag500 handlers. Move the two existing
handlers into s390-virtio-hcall.c.
Message-ID: <20241219144115.2820241-3-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 4be0fce498d0a08f18b3a9accdb9ded79484d30a)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/meson.build | 6 ++--
hw/s390x/s390-virtio-ccw.c | 58 ------------------------------
hw/s390x/s390-virtio-hcall.c | 65 +++++++++++++++++++++++++---------
hw/s390x/s390-virtio-hcall.h | 2 --
target/s390x/kvm/kvm.c | 5 ++-
target/s390x/tcg/misc_helper.c | 3 ++
6 files changed, 60 insertions(+), 79 deletions(-)
diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build
index 482fd13420..d6c8c33915 100644
--- a/hw/s390x/meson.build
+++ b/hw/s390x/meson.build
@@ -12,7 +12,6 @@ s390x_ss.add(files(
's390-pci-inst.c',
's390-skeys.c',
's390-stattrib.c',
- 's390-virtio-hcall.c',
'sclp.c',
'sclpcpu.c',
'sclpquiesce.c',
@@ -28,7 +27,10 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files(
s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
'tod-tcg.c',
))
-s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files('s390-virtio-ccw.c'))
+s390x_ss.add(when: 'CONFIG_S390_CCW_VIRTIO', if_true: files(
+ 's390-virtio-ccw.c',
+ 's390-virtio-hcall.c',
+))
s390x_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('3270-ccw.c'))
s390x_ss.add(when: 'CONFIG_VFIO', if_true: files('s390-pci-vfio.c'))
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 82ded9666c..d47e99028e 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -16,11 +16,8 @@
#include "exec/ram_addr.h"
#include "exec/confidential-guest-support.h"
#include "hw/boards.h"
-#include "hw/s390x/s390-virtio-hcall.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
-#include "hw/s390x/ioinst.h"
-#include "hw/s390x/css.h"
#include "virtio-ccw.h"
#include "qemu/config-file.h"
#include "qemu/ctype.h"
@@ -124,58 +121,6 @@ static void subsystem_reset(void)
}
}
-static int virtio_ccw_hcall_notify(const uint64_t *args)
-{
- uint64_t subch_id = args[0];
- uint64_t data = args[1];
- SubchDev *sch;
- VirtIODevice *vdev;
- int cssid, ssid, schid, m;
- uint16_t vq_idx = data;
-
- if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
- return -EINVAL;
- }
- sch = css_find_subch(m, cssid, ssid, schid);
- if (!sch || !css_subch_visible(sch)) {
- return -EINVAL;
- }
-
- vdev = virtio_ccw_get_vdev(sch);
- if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) {
- return -EINVAL;
- }
-
- if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
- virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx),
- (data >> 16) & 0xFFFF);
- }
-
- virtio_queue_notify(vdev, vq_idx);
- return 0;
-}
-
-static int virtio_ccw_hcall_early_printk(const uint64_t *args)
-{
- uint64_t mem = args[0];
- MachineState *ms = MACHINE(qdev_get_machine());
-
- if (mem < ms->ram_size) {
- /* Early printk */
- return 0;
- }
- return -EINVAL;
-}
-
-static void virtio_ccw_register_hcalls(void)
-{
- s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY,
- virtio_ccw_hcall_notify);
- /* Tolerate early printk. */
- s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY,
- virtio_ccw_hcall_early_printk);
-}
-
static void s390_memory_init(MemoryRegion *ram)
{
MemoryRegion *sysmem = get_system_memory();
@@ -296,9 +241,6 @@ static void ccw_init(MachineState *machine)
OBJECT(dev));
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- /* register hypercalls */
- virtio_ccw_register_hcalls();
-
s390_enable_css_support(s390_cpu_addr2state(0));
ret = css_create_css_image(VIRTUAL_CSSID, true);
diff --git a/hw/s390x/s390-virtio-hcall.c b/hw/s390x/s390-virtio-hcall.c
index ec7cf8beb3..ca49e3cd22 100644
--- a/hw/s390x/s390-virtio-hcall.c
+++ b/hw/s390x/s390-virtio-hcall.c
@@ -11,31 +11,64 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "hw/boards.h"
#include "hw/s390x/s390-virtio-hcall.h"
+#include "hw/s390x/ioinst.h"
+#include "hw/s390x/css.h"
+#include "virtio-ccw.h"
-#define MAX_DIAG_SUBCODES 255
+static int handle_virtio_notify(uint64_t mem)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
-static s390_virtio_fn s390_diag500_table[MAX_DIAG_SUBCODES];
+ if (mem < ms->ram_size) {
+ /* Early printk */
+ return 0;
+ }
+ return -EINVAL;
+}
-void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn)
+static int handle_virtio_ccw_notify(uint64_t subch_id, uint64_t data)
{
- assert(code < MAX_DIAG_SUBCODES);
- assert(!s390_diag500_table[code]);
+ SubchDev *sch;
+ VirtIODevice *vdev;
+ int cssid, ssid, schid, m;
+ uint16_t vq_idx = data;
+
+ if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) {
+ return -EINVAL;
+ }
+ sch = css_find_subch(m, cssid, ssid, schid);
+ if (!sch || !css_subch_visible(sch)) {
+ return -EINVAL;
+ }
- s390_diag500_table[code] = fn;
+ vdev = virtio_ccw_get_vdev(sch);
+ if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) {
+ return -EINVAL;
+ }
+
+ if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
+ virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx),
+ (data >> 16) & 0xFFFF);
+ }
+
+ virtio_queue_notify(vdev, vq_idx);
+ return 0;
}
int s390_virtio_hypercall(CPUS390XState *env)
{
- s390_virtio_fn fn;
-
- if (env->regs[1] < MAX_DIAG_SUBCODES) {
- fn = s390_diag500_table[env->regs[1]];
- if (fn) {
- env->regs[2] = fn(&env->regs[2]);
- return 0;
- }
- }
+ const uint64_t subcode = env->regs[1];
- return -EINVAL;
+ switch (subcode) {
+ case KVM_S390_VIRTIO_NOTIFY:
+ env->regs[2] = handle_virtio_notify(env->regs[2]);
+ return 0;
+ case KVM_S390_VIRTIO_CCW_NOTIFY:
+ env->regs[2] = handle_virtio_ccw_notify(env->regs[2], env->regs[3]);
+ return 0;
+ default:
+ return -EINVAL;
+ }
}
diff --git a/hw/s390x/s390-virtio-hcall.h b/hw/s390x/s390-virtio-hcall.h
index 3ae6d6ae3a..3d9fe147d2 100644
--- a/hw/s390x/s390-virtio-hcall.h
+++ b/hw/s390x/s390-virtio-hcall.h
@@ -18,8 +18,6 @@
/* The only thing that we need from the old kvm_virtio.h file */
#define KVM_S390_VIRTIO_NOTIFY 0
-typedef int (*s390_virtio_fn)(const uint64_t *args);
-void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
int s390_virtio_hypercall(CPUS390XState *env);
#endif /* HW_S390_VIRTIO_HCALL_H */
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 7a0ca5570f..5947dda829 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -51,6 +51,7 @@
#include "hw/s390x/s390-virtio-ccw.h"
#include "hw/s390x/s390-virtio-hcall.h"
#include "target/s390x/kvm/pv.h"
+#include CONFIG_DEVICES
#define kvm_vm_check_mem_attr(s, attr) \
kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr)
@@ -1494,9 +1495,11 @@ static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl)
static int handle_hypercall(S390CPU *cpu, struct kvm_run *run)
{
CPUS390XState *env = &cpu->env;
- int ret;
+ int ret = -EINVAL;
+#ifdef CONFIG_S390_CCW_VIRTIO
ret = s390_virtio_hypercall(env);
+#endif /* CONFIG_S390_CCW_VIRTIO */
if (ret == -EINVAL) {
kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
return 0;
diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c
index 303f86d363..f44136a568 100644
--- a/target/s390x/tcg/misc_helper.c
+++ b/target/s390x/tcg/misc_helper.c
@@ -43,6 +43,7 @@
#include "hw/s390x/s390-pci-inst.h"
#include "hw/boards.h"
#include "hw/s390x/tod.h"
+#include CONFIG_DEVICES
#endif
/* #define DEBUG_HELPER */
@@ -116,12 +117,14 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
uint64_t r;
switch (num) {
+#ifdef CONFIG_S390_CCW_VIRTIO
case 0x500:
/* KVM hypercall */
bql_lock();
r = s390_virtio_hypercall(env);
bql_unlock();
break;
+#endif /* CONFIG_S390_CCW_VIRTIO */
case 0x44:
/* yield */
r = 0;
--
2.48.1

View File

@ -0,0 +1,423 @@
From 6b82fca2ecac0c7b30780ebb71ce5bad0421b9b4 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:14 +0100
Subject: [PATCH 22/26] s390x/virtio-ccw: add support for virtio based memory
devices
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [22/26] 270a9fbe7e5bacfa6c9377815a01da26c4d26097 (thuth/qemu-kvm-cs)
Let's implement support for abstract virtio based memory devices, using
the virtio-pci implementation as an orientation. Wire them up in the
machine hotplug handler, taking care of s390x page size limitations.
As we neither support virtio-mem or virtio-pmem yet, the code is
effectively unused. We'll implement support for virtio-mem based on this
next.
Note that we won't wire up the virtio-pci variant (should currently be
impossible due to lack of support for MSI-X), but we'll add a safety net
to reject plugging them in the pre-plug handler.
Message-ID: <20241219144115.2820241-14-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 88d86f6f1e36741ba9e1625da19a7ccf1a343d39)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 3 +
hw/s390x/meson.build | 3 +
hw/s390x/s390-virtio-ccw.c | 47 +++++++++-
hw/s390x/virtio-ccw-md-stubs.c | 24 ++++++
hw/s390x/virtio-ccw-md.c | 153 +++++++++++++++++++++++++++++++++
hw/s390x/virtio-ccw-md.h | 44 ++++++++++
hw/virtio/Kconfig | 1 +
7 files changed, 274 insertions(+), 1 deletion(-)
create mode 100644 hw/s390x/virtio-ccw-md-stubs.c
create mode 100644 hw/s390x/virtio-ccw-md.c
create mode 100644 hw/s390x/virtio-ccw-md.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 3584d6a6c6..f21dc3fa75 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2387,6 +2387,9 @@ F: include/hw/virtio/virtio-crypto.h
virtio based memory device
M: David Hildenbrand <david@redhat.com>
S: Supported
+F: hw/s390x/virtio-ccw-md.c
+F: hw/s390x/virtio-ccw-md.h
+F: hw/s390x/virtio-ccw-md-stubs.c
F: hw/virtio/virtio-md-pci.c
F: include/hw/virtio/virtio-md-pci.h
F: stubs/virtio-md-pci.c
diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build
index e344a3bd8c..4431868408 100644
--- a/hw/s390x/meson.build
+++ b/hw/s390x/meson.build
@@ -50,8 +50,11 @@ endif
virtio_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-ccw.c'))
virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-ccw.c'))
virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c'))
+virtio_ss.add(when: 'CONFIG_VIRTIO_MD', if_true: files('virtio-ccw-md.c'))
s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss)
+s390x_ss.add(when: 'CONFIG_VIRTIO_MD', if_false: files('virtio-ccw-md-stubs.c'))
+
hw_arch += {'s390x': s390x_ss}
hw_s390x_modules = {}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index bd05a22b4e..9f4ad01789 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -46,6 +46,8 @@
#include "qapi/visitor.h"
#include "hw/s390x/cpu-topology.h"
#include "kvm/kvm_s390x.h"
+#include "hw/virtio/virtio-md-pci.h"
+#include "hw/s390x/virtio-ccw-md.h"
#include CONFIG_DEVICES
static Error *pv_mig_blocker;
@@ -546,11 +548,39 @@ static void s390_machine_reset(MachineState *machine, ResetType type)
s390_ipl_clear_reset_request();
}
+static void s390_machine_device_pre_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
+ virtio_ccw_md_pre_plug(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev), errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
+ error_setg(errp,
+ "PCI-attached virtio based memory devices not supported");
+ }
+}
+
static void s390_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
+ S390CcwMachineState *s390ms = S390_CCW_MACHINE(hotplug_dev);
+
if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
s390_cpu_plug(hotplug_dev, dev, errp);
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
+ /*
+ * At this point, the device is realized and set all memdevs mapped, so
+ * qemu_maxrampagesize() will pick up the page sizes of these memdevs
+ * as well. Before we plug the device and expose any RAM memory regions
+ * to the system, make sure we don't exceed the previously set max page
+ * size. While only relevant for KVM, there is not really any use case
+ * for this with TCG, so we'll unconditionally reject it.
+ */
+ if (qemu_maxrampagesize() != s390ms->max_pagesize) {
+ error_setg(errp, "Memory device uses a bigger page size than"
+ " initial memory");
+ return;
+ }
+ virtio_ccw_md_plug(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev), errp);
}
}
@@ -560,9 +590,20 @@ 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_MD_CCW)) {
+ virtio_ccw_md_unplug_request(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev),
+ errp);
}
}
+static void s390_machine_device_unplug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_CCW)) {
+ virtio_ccw_md_unplug(VIRTIO_MD_CCW(dev), MACHINE(hotplug_dev), errp);
+ }
+ }
+
static CpuInstanceProperties s390_cpu_index_to_props(MachineState *ms,
unsigned cpu_index)
{
@@ -609,7 +650,9 @@ 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_MD_CCW) ||
+ object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
return HOTPLUG_HANDLER(machine);
}
return NULL;
@@ -769,8 +812,10 @@ 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;
+ hc->unplug = s390_machine_device_unplug;
nc->nmi_monitor_handler = s390_nmi;
mc->default_ram_id = "s390.ram";
mc->default_nic = "virtio-net-ccw";
diff --git a/hw/s390x/virtio-ccw-md-stubs.c b/hw/s390x/virtio-ccw-md-stubs.c
new file mode 100644
index 0000000000..e937865550
--- /dev/null
+++ b/hw/s390x/virtio-ccw-md-stubs.c
@@ -0,0 +1,24 @@
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/s390x/virtio-ccw-md.h"
+
+void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
+{
+ error_setg(errp, "virtio based memory devices not supported");
+}
+
+void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
+{
+ error_setg(errp, "virtio based memory devices not supported");
+}
+
+void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
+ Error **errp)
+{
+ error_setg(errp, "virtio based memory devices not supported");
+}
+
+void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
+{
+ error_setg(errp, "virtio based memory devices not supported");
+}
diff --git a/hw/s390x/virtio-ccw-md.c b/hw/s390x/virtio-ccw-md.c
new file mode 100644
index 0000000000..de333282df
--- /dev/null
+++ b/hw/s390x/virtio-ccw-md.c
@@ -0,0 +1,153 @@
+/*
+ * Virtio CCW support for abstract virtio based memory device
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/s390x/virtio-ccw-md.h"
+#include "hw/mem/memory-device.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+
+void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
+{
+ DeviceState *dev = DEVICE(vmd);
+ HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ MemoryDeviceState *md = MEMORY_DEVICE(vmd);
+ Error *local_err = NULL;
+
+ if (!bus_handler && dev->hotplugged) {
+ /*
+ * Without a bus hotplug handler, we cannot control the plug/unplug
+ * order. We should never reach this point when hotplugging, but
+ * better add a safety net.
+ */
+ error_setg(errp, "hotplug of virtio based memory devices not supported"
+ " on this bus.");
+ return;
+ }
+
+ /*
+ * 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, ms, &local_err);
+ if (!local_err && bus_handler) {
+ hotplug_handler_pre_plug(bus_handler, dev, &local_err);
+ }
+ error_propagate(errp, local_err);
+}
+
+void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
+{
+ DeviceState *dev = DEVICE(vmd);
+ HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ MemoryDeviceState *md = MEMORY_DEVICE(vmd);
+ Error *local_err = NULL;
+
+ /*
+ * 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(md, ms);
+ if (bus_handler) {
+ hotplug_handler_plug(bus_handler, dev, &local_err);
+ if (local_err) {
+ memory_device_unplug(md, ms);
+ }
+ }
+ error_propagate(errp, local_err);
+}
+
+void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
+ Error **errp)
+{
+ VirtIOMDCcwClass *vmdc = VIRTIO_MD_CCW_GET_CLASS(vmd);
+ DeviceState *dev = DEVICE(vmd);
+ HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ HotplugHandlerClass *hdc;
+ Error *local_err = NULL;
+
+ if (!vmdc->unplug_request_check) {
+ error_setg(errp,
+ "this virtio based memory devices cannot be unplugged");
+ return;
+ }
+
+ if (!bus_handler) {
+ error_setg(errp, "hotunplug of virtio based memory devices not"
+ "supported on this bus");
+ return;
+ }
+
+ vmdc->unplug_request_check(vmd, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ /*
+ * Forward the async request or turn it into a sync request (handling it
+ * like qdev_unplug()).
+ */
+ hdc = HOTPLUG_HANDLER_GET_CLASS(bus_handler);
+ if (hdc->unplug_request) {
+ hotplug_handler_unplug_request(bus_handler, dev, &local_err);
+ } else {
+ virtio_ccw_md_unplug(vmd, ms, &local_err);
+ if (!local_err) {
+ object_unparent(OBJECT(dev));
+ }
+ }
+}
+
+void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp)
+{
+ DeviceState *dev = DEVICE(vmd);
+ HotplugHandler *bus_handler = qdev_get_bus_hotplug_handler(dev);
+ MemoryDeviceState *md = MEMORY_DEVICE(vmd);
+ Error *local_err = NULL;
+
+ /* Unplug the memory device while it is still realized. */
+ memory_device_unplug(md, ms);
+
+ if (bus_handler) {
+ hotplug_handler_unplug(bus_handler, dev, &local_err);
+ if (local_err) {
+ /* Not expected to fail ... but still try to recover. */
+ memory_device_plug(md, ms);
+ error_propagate(errp, local_err);
+ return;
+ }
+ } else {
+ /* Very unexpected, but let's just try to do the right thing. */
+ warn_report("Unexpected unplug of virtio based memory device");
+ qdev_unrealize(dev);
+ }
+}
+
+static const TypeInfo virtio_ccw_md_info = {
+ .name = TYPE_VIRTIO_MD_CCW,
+ .parent = TYPE_VIRTIO_CCW_DEVICE,
+ .instance_size = sizeof(VirtIOMDCcw),
+ .class_size = sizeof(VirtIOMDCcwClass),
+ .abstract = true,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_MEMORY_DEVICE },
+ { }
+ },
+};
+
+static void virtio_ccw_md_register(void)
+{
+ type_register_static(&virtio_ccw_md_info);
+}
+type_init(virtio_ccw_md_register)
diff --git a/hw/s390x/virtio-ccw-md.h b/hw/s390x/virtio-ccw-md.h
new file mode 100644
index 0000000000..39ba864c92
--- /dev/null
+++ b/hw/s390x/virtio-ccw-md.h
@@ -0,0 +1,44 @@
+/*
+ * Virtio CCW support for abstract virtio based memory device
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_S390X_VIRTIO_CCW_MD_H
+#define HW_S390X_VIRTIO_CCW_MD_H
+
+#include "virtio-ccw.h"
+#include "qom/object.h"
+
+/*
+ * virtio-md-ccw: This extends VirtioCcwDevice.
+ */
+#define TYPE_VIRTIO_MD_CCW "virtio-md-ccw"
+
+OBJECT_DECLARE_TYPE(VirtIOMDCcw, VirtIOMDCcwClass, VIRTIO_MD_CCW)
+
+struct VirtIOMDCcwClass {
+ /* private */
+ VirtIOCCWDeviceClass parent;
+
+ /* public */
+ void (*unplug_request_check)(VirtIOMDCcw *vmd, Error **errp);
+};
+
+struct VirtIOMDCcw {
+ VirtioCcwDevice parent_obj;
+};
+
+void virtio_ccw_md_pre_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp);
+void virtio_ccw_md_plug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp);
+void virtio_ccw_md_unplug_request(VirtIOMDCcw *vmd, MachineState *ms,
+ Error **errp);
+void virtio_ccw_md_unplug(VirtIOMDCcw *vmd, MachineState *ms, Error **errp);
+
+#endif /* HW_S390X_VIRTIO_CCW_MD_H */
diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
index 0afec2ae92..f4b14e1a44 100644
--- a/hw/virtio/Kconfig
+++ b/hw/virtio/Kconfig
@@ -25,6 +25,7 @@ config VIRTIO_MMIO
config VIRTIO_CCW
bool
select VIRTIO
+ select VIRTIO_MD_SUPPORTED
config VIRTIO_BALLOON
bool
--
2.48.1

View File

@ -0,0 +1,459 @@
From fa68427f55bee8d18d846e03ebf9f1eeb80f274d Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 19 Dec 2024 15:41:15 +0100
Subject: [PATCH 23/26] s390x: virtio-mem support
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [23/26] 4c59ba9025ce5ba7686a7f3e01bb70e8c580709f (thuth/qemu-kvm-cs)
Let's add our virtio-mem-ccw proxy device and wire it up. We should
be supporting everything (e.g., device unplug, "dynamic-memslots") that
we already support for the virtio-pci variant.
With a Linux guest that supports virtio-mem (and has automatic memory
onlining properly configured) the following example will work:
1. Start a VM with 4G initial memory and a virtio-mem device with a maximum
capacity of 16GB:
qemu/build/qemu-system-s390x \
--enable-kvm \
-m 4G,maxmem=20G \
-nographic \
-smp 8 \
-hda Fedora-Server-KVM-40-1.14.s390x.qcow2 \
-chardev socket,id=monitor,path=/var/tmp/monitor,server,nowait \
-mon chardev=monitor,mode=readline \
-object memory-backend-ram,id=mem0,size=16G,reserve=off \
-device virtio-mem-ccw,id=vmem0,memdev=mem0,dynamic-memslots=on
2. Query the current size of virtio-mem device:
(qemu) info memory-devices
Memory device [virtio-mem]: "vmem0"
memaddr: 0x100000000
node: 0
requested-size: 0
size: 0
max-size: 17179869184
block-size: 1048576
memdev: /objects/mem0
3. Request to grow it to 8GB (hotplug 8GB):
(qemu) qom-set vmem0 requested-size 8G
(qemu) info memory-devices
Memory device [virtio-mem]: "vmem0"
memaddr: 0x100000000
node: 0
requested-size: 8589934592
size: 8589934592
max-size: 17179869184
block-size: 1048576
memdev: /objects/mem0
4. Request to grow to 16GB (hotplug another 8GB):
(qemu) qom-set vmem0 requested-size 16G
(qemu) info memory-devices
Memory device [virtio-mem]: "vmem0"
memaddr: 0x100000000
node: 0
requested-size: 17179869184
size: 17179869184
max-size: 17179869184
block-size: 1048576
memdev: /objects/mem0
5. Try to hotunplug all memory again, shrinking to 0GB:
(qemu) qom-set vmem0 requested-size 0G
(qemu) info memory-devices
Memory device [virtio-mem]: "vmem0"
memaddr: 0x100000000
node: 0
requested-size: 0
size: 0
max-size: 17179869184
block-size: 1048576
memdev: /objects/mem0
6. If it worked, unplug the device
(qemu) device_del vmem0
(qemu) info memory-devices
(qemu) object_del mem0
7. Hotplug a new device with a smaller capacity and directly size it to 1GB
(qemu) object_add memory-backend-ram,id=mem0,size=8G,reserve=off
(qemu) device_add virtio-mem-ccw,id=vmem0,memdev=mem0,\
dynamic-memslots=on,requested-size=1G
(qemu) info memory-devices
Memory device [virtio-mem]: "vmem0"
memaddr: 0x100000000
node: 0
requested-size: 1073741824
size: 1073741824
max-size: 8589934592
block-size: 1048576
memdev: /objects/mem0
Trying to use a virtio-mem device backed by hugetlb into a !hugetlb VM
correctly results in the error:
... Memory device uses a bigger page size than initial memory
Note that the virtio-mem driver in Linux will supports 1 MiB (pageblock)
granularity.
Message-ID: <20241219144115.2820241-15-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit aa910c20ec5f3b10551da19e441b3e2b54406e25)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 2 +
hw/s390x/Kconfig | 1 +
hw/s390x/meson.build | 1 +
hw/s390x/virtio-ccw-mem.c | 226 ++++++++++++++++++++++++++++++++++++++
hw/s390x/virtio-ccw-mem.h | 34 ++++++
hw/virtio/virtio-mem.c | 4 +-
6 files changed, 267 insertions(+), 1 deletion(-)
create mode 100644 hw/s390x/virtio-ccw-mem.c
create mode 100644 hw/s390x/virtio-ccw-mem.h
diff --git a/MAINTAINERS b/MAINTAINERS
index f21dc3fa75..f7b7ceffc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2401,6 +2401,8 @@ W: https://virtio-mem.gitlab.io/
F: hw/virtio/virtio-mem.c
F: hw/virtio/virtio-mem-pci.h
F: hw/virtio/virtio-mem-pci.c
+F: hw/s390x/virtio-ccw-mem.c
+F: hw/s390x/virtio-ccw-mem.h
F: include/hw/virtio/virtio-mem.h
virtio-snd
diff --git a/hw/s390x/Kconfig b/hw/s390x/Kconfig
index 3bbf4ae56e..5d57daff77 100644
--- a/hw/s390x/Kconfig
+++ b/hw/s390x/Kconfig
@@ -15,3 +15,4 @@ config S390_CCW_VIRTIO
select SCLPCONSOLE
select VIRTIO_CCW
select MSI_NONBROKEN
+ select VIRTIO_MEM_SUPPORTED
diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build
index 4431868408..3bbebfd817 100644
--- a/hw/s390x/meson.build
+++ b/hw/s390x/meson.build
@@ -51,6 +51,7 @@ virtio_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-ccw.c'))
virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-ccw.c'))
virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c'))
virtio_ss.add(when: 'CONFIG_VIRTIO_MD', if_true: files('virtio-ccw-md.c'))
+virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-ccw-mem.c'))
s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss)
s390x_ss.add(when: 'CONFIG_VIRTIO_MD', if_false: files('virtio-ccw-md-stubs.c'))
diff --git a/hw/s390x/virtio-ccw-mem.c b/hw/s390x/virtio-ccw-mem.c
new file mode 100644
index 0000000000..bee0d560cb
--- /dev/null
+++ b/hw/s390x/virtio-ccw-mem.c
@@ -0,0 +1,226 @@
+/*
+ * virtio-mem CCW implementation
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "virtio-ccw-mem.h"
+#include "hw/mem/memory-device.h"
+#include "qapi/qapi-events-machine.h"
+#include "qapi/qapi-events-misc.h"
+
+static void virtio_ccw_mem_realize(VirtioCcwDevice *ccw_dev, Error **errp)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(ccw_dev);
+ DeviceState *vdev = DEVICE(&dev->vdev);
+
+ qdev_realize(vdev, BUS(&ccw_dev->bus), errp);
+}
+
+static void virtio_ccw_mem_set_addr(MemoryDeviceState *md, uint64_t addr,
+ Error **errp)
+{
+ object_property_set_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP, addr, errp);
+}
+
+static uint64_t virtio_ccw_mem_get_addr(const MemoryDeviceState *md)
+{
+ return object_property_get_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP,
+ &error_abort);
+}
+
+static MemoryRegion *virtio_ccw_mem_get_memory_region(MemoryDeviceState *md,
+ Error **errp)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
+ VirtIOMEM *vmem = &dev->vdev;
+ VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
+
+ return vmc->get_memory_region(vmem, errp);
+}
+
+static void virtio_ccw_mem_decide_memslots(MemoryDeviceState *md,
+ unsigned int limit)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
+ VirtIOMEM *vmem = VIRTIO_MEM(&dev->vdev);
+ VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
+
+ vmc->decide_memslots(vmem, limit);
+}
+
+static unsigned int virtio_ccw_mem_get_memslots(MemoryDeviceState *md)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
+ VirtIOMEM *vmem = VIRTIO_MEM(&dev->vdev);
+ VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
+
+ return vmc->get_memslots(vmem);
+}
+
+static uint64_t virtio_ccw_mem_get_plugged_size(const MemoryDeviceState *md,
+ Error **errp)
+{
+ return object_property_get_uint(OBJECT(md), VIRTIO_MEM_SIZE_PROP,
+ errp);
+}
+
+static void virtio_ccw_mem_fill_device_info(const MemoryDeviceState *md,
+ MemoryDeviceInfo *info)
+{
+ VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(md);
+ VirtIOMEM *vmem = &dev->vdev;
+ VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
+ DeviceState *vdev = DEVICE(md);
+
+ if (vdev->id) {
+ vi->id = g_strdup(vdev->id);
+ }
+
+ /* let the real device handle everything else */
+ vpc->fill_device_info(vmem, vi);
+
+ info->u.virtio_mem.data = vi;
+ info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;
+}
+
+static uint64_t virtio_ccw_mem_get_min_alignment(const MemoryDeviceState *md)
+{
+ return object_property_get_uint(OBJECT(md), VIRTIO_MEM_BLOCK_SIZE_PROP,
+ &error_abort);
+}
+
+static void virtio_ccw_mem_size_change_notify(Notifier *notifier, void *data)
+{
+ VirtIOMEMCcw *dev = container_of(notifier, VirtIOMEMCcw,
+ size_change_notifier);
+ DeviceState *vdev = DEVICE(dev);
+ char *qom_path = object_get_canonical_path(OBJECT(dev));
+ const uint64_t * const size_p = data;
+
+ qapi_event_send_memory_device_size_change(vdev->id, *size_p, qom_path);
+ g_free(qom_path);
+}
+
+static void virtio_ccw_mem_unplug_request_check(VirtIOMDCcw *vmd, Error **errp)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(vmd);
+ VirtIOMEM *vmem = &dev->vdev;
+ VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
+
+ vpc->unplug_request_check(vmem, errp);
+}
+
+static void virtio_ccw_mem_get_requested_size(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(obj);
+
+ object_property_get(OBJECT(&dev->vdev), name, v, errp);
+}
+
+static void virtio_ccw_mem_set_requested_size(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(obj);
+ DeviceState *vdev = DEVICE(obj);
+
+ /*
+ * If we passed virtio_ccw_mem_unplug_request_check(), making sure that
+ * the requested size is 0, don't allow modifying the requested size
+ * anymore, otherwise the VM might end up hotplugging memory before
+ * handling the unplug request.
+ */
+ if (vdev->pending_deleted_event) {
+ error_setg(errp, "'%s' cannot be changed if the device is in the"
+ " process of unplug", name);
+ return;
+ }
+
+ object_property_set(OBJECT(&dev->vdev), name, v, errp);
+}
+
+static Property virtio_ccw_mem_properties[] = {
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
+ DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
+ VIRTIO_CCW_MAX_REV),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_ccw_mem_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
+ MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(klass);
+ VirtIOMDCcwClass *vmdc = VIRTIO_MD_CCW_CLASS(klass);
+
+ k->realize = virtio_ccw_mem_realize;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ device_class_set_props(dc, virtio_ccw_mem_properties);
+
+ mdc->get_addr = virtio_ccw_mem_get_addr;
+ mdc->set_addr = virtio_ccw_mem_set_addr;
+ mdc->get_plugged_size = virtio_ccw_mem_get_plugged_size;
+ mdc->get_memory_region = virtio_ccw_mem_get_memory_region;
+ mdc->decide_memslots = virtio_ccw_mem_decide_memslots;
+ mdc->get_memslots = virtio_ccw_mem_get_memslots;
+ mdc->fill_device_info = virtio_ccw_mem_fill_device_info;
+ mdc->get_min_alignment = virtio_ccw_mem_get_min_alignment;
+
+ vmdc->unplug_request_check = virtio_ccw_mem_unplug_request_check;
+}
+
+static void virtio_ccw_mem_instance_init(Object *obj)
+{
+ VirtIOMEMCcw *dev = VIRTIO_MEM_CCW(obj);
+ VirtIOMEMClass *vmc;
+ VirtIOMEM *vmem;
+
+ virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+ TYPE_VIRTIO_MEM);
+
+ dev->size_change_notifier.notify = virtio_ccw_mem_size_change_notify;
+ vmem = &dev->vdev;
+ vmc = VIRTIO_MEM_GET_CLASS(vmem);
+ /*
+ * We never remove the notifier again, as we expect both devices to
+ * disappear at the same time.
+ */
+ vmc->add_size_change_notifier(vmem, &dev->size_change_notifier);
+
+ object_property_add_alias(obj, VIRTIO_MEM_BLOCK_SIZE_PROP,
+ OBJECT(&dev->vdev), VIRTIO_MEM_BLOCK_SIZE_PROP);
+ object_property_add_alias(obj, VIRTIO_MEM_SIZE_PROP, OBJECT(&dev->vdev),
+ VIRTIO_MEM_SIZE_PROP);
+ object_property_add(obj, VIRTIO_MEM_REQUESTED_SIZE_PROP, "size",
+ virtio_ccw_mem_get_requested_size,
+ virtio_ccw_mem_set_requested_size, NULL, NULL);
+}
+
+static const TypeInfo virtio_ccw_mem = {
+ .name = TYPE_VIRTIO_MEM_CCW,
+ .parent = TYPE_VIRTIO_MD_CCW,
+ .instance_size = sizeof(VirtIOMEMCcw),
+ .instance_init = virtio_ccw_mem_instance_init,
+ .class_init = virtio_ccw_mem_class_init,
+};
+
+static void virtio_ccw_mem_register_types(void)
+{
+ type_register_static(&virtio_ccw_mem);
+}
+type_init(virtio_ccw_mem_register_types)
diff --git a/hw/s390x/virtio-ccw-mem.h b/hw/s390x/virtio-ccw-mem.h
new file mode 100644
index 0000000000..738ab2c744
--- /dev/null
+++ b/hw/s390x/virtio-ccw-mem.h
@@ -0,0 +1,34 @@
+/*
+ * Virtio MEM CCW device
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_S390X_VIRTIO_CCW_MEM_H
+#define HW_S390X_VIRTIO_CCW_MEM_H
+
+#include "virtio-ccw-md.h"
+#include "hw/virtio/virtio-mem.h"
+#include "qom/object.h"
+
+typedef struct VirtIOMEMCcw VirtIOMEMCcw;
+
+/*
+ * virtio-mem-ccw: This extends VirtIOMDCcw
+ */
+#define TYPE_VIRTIO_MEM_CCW "virtio-mem-ccw"
+DECLARE_INSTANCE_CHECKER(VirtIOMEMCcw, VIRTIO_MEM_CCW, TYPE_VIRTIO_MEM_CCW)
+
+struct VirtIOMEMCcw {
+ VirtIOMDCcw parent_obj;
+ VirtIOMEM vdev;
+ Notifier size_change_notifier;
+};
+
+#endif /* HW_S390X_VIRTIO_CCW_MEM_H */
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 00da98b6e1..c9f8a23bbc 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -61,6 +61,8 @@ static uint32_t virtio_mem_default_thp_size(void)
} else if (qemu_real_host_page_size() == 64 * KiB) {
default_thp_size = 512 * MiB;
}
+#elif defined(__s390x__)
+ default_thp_size = 1 * MiB;
#endif
return default_thp_size;
@@ -161,7 +163,7 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb)
* necessary (as the section size can change). But it's more likely that the
* section size will rather get smaller and not bigger over time.
*/
-#if defined(TARGET_X86_64) || defined(TARGET_I386)
+#if defined(TARGET_X86_64) || defined(TARGET_I386) || defined(TARGET_S390X)
#define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB))
#elif defined(TARGET_ARM)
#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB))
--
2.48.1

View File

@ -0,0 +1,284 @@
From 50c4cbbe0a8849dd0c720c6e706498cb0d46f5b3 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Fri, 13 Sep 2024 15:31:43 +0100
Subject: [PATCH 04/26] target/s390: Convert CPU to Resettable interface
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [4/26] 157b29ced6b92ecec5e69f8bc60d0183a0c88fa0 (thuth/qemu-kvm-cs)
Convert the s390 CPU to the Resettable interface. This is slightly
more involved than the other CPU types were (see commits
9130cade5fc22..d66e64dd006df) because S390 has its own set of
different kinds of reset with different behaviours that it needs to
trigger.
We handle this by adding these reset types to the Resettable
ResetType enum. Now instead of having an underlying implementation
of reset that is s390-specific and which might be called either
directly or via the DeviceClass::reset method, we can implement only
the Resettable hold phase method, and have the places that need to
trigger an s390-specific reset type do so by calling
resettable_reset().
The other option would have been to smuggle in the s390 reset
type via, for instance, a field in the CPU state that we set
in s390_do_cpu_initial_reset() etc and then examined in the
reset method, but doing it this way seems cleaner.
The motivation for this change is that this is the last caller
of the legacy device_class_set_parent_reset() function, and
removing that will let us clean up some glue code that we added
for the transition to three-phase reset.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-id: 20240830145812.1967042-4-peter.maydell@linaro.org
(cherry picked from commit cf7f61d13f28f32d0b14abb70ce1bd9e41623b2e)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
docs/devel/reset.rst | 10 ++++++++++
include/hw/resettable.h | 2 ++
target/s390x/cpu.c | 38 +++++++++++++++++---------------------
target/s390x/cpu.h | 21 ++++-----------------
target/s390x/sigp.c | 8 ++------
5 files changed, 35 insertions(+), 44 deletions(-)
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
index 24ab630465..d2799eba7a 100644
--- a/docs/devel/reset.rst
+++ b/docs/devel/reset.rst
@@ -44,6 +44,16 @@ The Resettable interface handles reset types with an enum ``ResetType``:
value on each cold reset, such as RNG seed information, and which they
must not reinitialize on a snapshot-load reset.
+``RESET_TYPE_S390_CPU_NORMAL``
+ This is only used for S390 CPU objects; it clears interrupts, stops
+ processing, and clears the TLB, but does not touch register contents.
+
+``RESET_TYPE_S390_CPU_INITIAL``
+ This is only used for S390 CPU objects; it does everything
+ ``RESET_TYPE_S390_CPU_NORMAL`` does and also clears the PSW, prefix,
+ FPC, timer and control registers. It does not touch gprs, fprs or acrs.
+
+
Devices which implement reset methods must treat any unknown ``ResetType``
as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
existing code we need to change if we add more types in future.
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
index 7e249deb8b..83b561fc83 100644
--- a/include/hw/resettable.h
+++ b/include/hw/resettable.h
@@ -36,6 +36,8 @@ typedef struct ResettableState ResettableState;
typedef enum ResetType {
RESET_TYPE_COLD,
RESET_TYPE_SNAPSHOT_LOAD,
+ RESET_TYPE_S390_CPU_INITIAL,
+ RESET_TYPE_S390_CPU_NORMAL,
} ResetType;
/*
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 0fbfcd35d8..4e41a3dff5 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -32,6 +32,7 @@
#include "sysemu/hw_accel.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
+#include "hw/resettable.h"
#include "fpu/softfloat-helpers.h"
#include "disas/capstone.h"
#include "sysemu/tcg.h"
@@ -162,23 +163,25 @@ static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value)
#endif
}
-/* S390CPUClass::reset() */
-static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
+/* S390CPUClass Resettable reset_hold phase method */
+static void s390_cpu_reset_hold(Object *obj, ResetType type)
{
- S390CPU *cpu = S390_CPU(s);
+ S390CPU *cpu = S390_CPU(obj);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
CPUS390XState *env = &cpu->env;
- DeviceState *dev = DEVICE(s);
- scc->parent_reset(dev);
+ if (scc->parent_phases.hold) {
+ scc->parent_phases.hold(obj, type);
+ }
cpu->env.sigp_order = 0;
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
switch (type) {
- case S390_CPU_RESET_CLEAR:
+ default:
+ /* RESET_TYPE_COLD: power on or "clear" reset */
memset(env, 0, offsetof(CPUS390XState, start_initial_reset_fields));
/* fall through */
- case S390_CPU_RESET_INITIAL:
+ case RESET_TYPE_S390_CPU_INITIAL:
/* initial reset does not clear everything! */
memset(&env->start_initial_reset_fields, 0,
offsetof(CPUS390XState, start_normal_reset_fields) -
@@ -203,7 +206,7 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
set_float_detect_tininess(float_tininess_before_rounding,
&env->fpu_status);
/* fall through */
- case S390_CPU_RESET_NORMAL:
+ case RESET_TYPE_S390_CPU_NORMAL:
env->psw.mask &= ~PSW_MASK_RI;
memset(&env->start_normal_reset_fields, 0,
offsetof(CPUS390XState, end_reset_fields) -
@@ -212,20 +215,18 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
env->pfault_token = -1UL;
env->bpbc = false;
break;
- default:
- g_assert_not_reached();
}
/* Reset state inside the kernel that we cannot access yet from QEMU. */
if (kvm_enabled()) {
switch (type) {
- case S390_CPU_RESET_CLEAR:
+ default:
kvm_s390_reset_vcpu_clear(cpu);
break;
- case S390_CPU_RESET_INITIAL:
+ case RESET_TYPE_S390_CPU_INITIAL:
kvm_s390_reset_vcpu_initial(cpu);
break;
- case S390_CPU_RESET_NORMAL:
+ case RESET_TYPE_S390_CPU_NORMAL:
kvm_s390_reset_vcpu_normal(cpu);
break;
}
@@ -315,12 +316,6 @@ static Property s390x_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST()
};
-static void s390_cpu_reset_full(DeviceState *dev)
-{
- CPUState *s = CPU(dev);
- return s390_cpu_reset(s, S390_CPU_RESET_CLEAR);
-}
-
#ifdef CONFIG_TCG
#include "hw/core/tcg-cpu-ops.h"
@@ -383,15 +378,16 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
S390CPUClass *scc = S390_CPU_CLASS(oc);
CPUClass *cc = CPU_CLASS(scc);
DeviceClass *dc = DEVICE_CLASS(oc);
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
device_class_set_parent_realize(dc, s390_cpu_realizefn,
&scc->parent_realize);
device_class_set_props(dc, s390x_cpu_properties);
dc->user_creatable = true;
- device_class_set_parent_reset(dc, s390_cpu_reset_full, &scc->parent_reset);
+ resettable_class_set_parent_phases(rc, NULL, s390_cpu_reset_hold, NULL,
+ &scc->parent_phases);
- scc->reset = s390_cpu_reset;
cc->class_by_name = s390_cpu_class_by_name,
cc->has_work = s390_cpu_has_work;
cc->mmu_index = s390x_cpu_mmu_index;
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index d6b75ad0e0..6a64472403 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -177,19 +177,11 @@ struct ArchCPU {
uint32_t irqstate_saved_size;
};
-typedef enum cpu_reset_type {
- S390_CPU_RESET_NORMAL,
- S390_CPU_RESET_INITIAL,
- S390_CPU_RESET_CLEAR,
-} cpu_reset_type;
-
/**
* S390CPUClass:
* @parent_realize: The parent class' realize handler.
- * @parent_reset: The parent class' reset handler.
+ * @parent_phases: The parent class' reset phase handlers.
* @load_normal: Performs a load normal.
- * @cpu_reset: Performs a CPU reset.
- * @initial_cpu_reset: Performs an initial CPU reset.
*
* An S/390 CPU model.
*/
@@ -203,9 +195,8 @@ struct S390CPUClass {
const char *desc;
DeviceRealize parent_realize;
- DeviceReset parent_reset;
+ ResettablePhases parent_phases;
void (*load_normal)(CPUState *cpu);
- void (*reset)(CPUState *cpu, cpu_reset_type type);
};
#ifndef CONFIG_USER_ONLY
@@ -872,16 +863,12 @@ static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg)
{
- S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
-
- scc->reset(cs, S390_CPU_RESET_NORMAL);
+ resettable_reset(OBJECT(cs), RESET_TYPE_S390_CPU_NORMAL);
}
static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg)
{
- S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
-
- scc->reset(cs, S390_CPU_RESET_INITIAL);
+ resettable_reset(OBJECT(cs), RESET_TYPE_S390_CPU_INITIAL);
}
static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index ad0ad61177..08aaecf12b 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -251,24 +251,20 @@ static void sigp_restart(CPUState *cs, run_on_cpu_data arg)
static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg)
{
- S390CPU *cpu = S390_CPU(cs);
- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
SigpInfo *si = arg.host_ptr;
cpu_synchronize_state(cs);
- scc->reset(cs, S390_CPU_RESET_INITIAL);
+ resettable_reset(OBJECT(cs), RESET_TYPE_S390_CPU_INITIAL);
cpu_synchronize_post_reset(cs);
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
}
static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg)
{
- S390CPU *cpu = S390_CPU(cs);
- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
SigpInfo *si = arg.host_ptr;
cpu_synchronize_state(cs);
- scc->reset(cs, S390_CPU_RESET_NORMAL);
+ resettable_reset(OBJECT(cs), RESET_TYPE_S390_CPU_NORMAL);
cpu_synchronize_post_reset(cs);
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
}
--
2.48.1

View File

@ -0,0 +1,87 @@
From a582cf6f68febba05e20548f643c8be637eab7b8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 6 Sep 2024 12:16:58 +0200
Subject: [PATCH 01/26] virtio: kconfig: memory devices are PCI only
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [1/26] 0f0eab06b6f79f84c2e8d4fee28309b3c7c57414 (thuth/qemu-kvm-cs)
Virtio memory devices rely on PCI BARs to expose the contents of memory.
Because of this they cannot be used (yet) with virtio-mmio or virtio-ccw.
In fact the code that is common to virtio-mem and virtio-pmem, which
is in hw/virtio/virtio-md-pci.c, is only included if CONFIG_VIRTIO_PCI
is set. Reproduce the same condition in the Kconfig file, only allowing
VIRTIO_MEM and VIRTIO_PMEM to be defined if the transport supports it.
Without this patch it is possible to create a configuration with
CONFIG_VIRTIO_PCI=n and CONFIG_VIRTIO_MEM=y, but that causes a
linking failure.
Message-ID: <20240906101658.514470-1-pbonzini@redhat.com>
Reported-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 8d018fe59a0beff580ac6b3399d642c4277d9dd0)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/virtio/Kconfig | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
index aa63ff7fd4..0afec2ae92 100644
--- a/hw/virtio/Kconfig
+++ b/hw/virtio/Kconfig
@@ -16,6 +16,7 @@ config VIRTIO_PCI
default y if PCI_DEVICES
depends on PCI
select VIRTIO
+ select VIRTIO_MD_SUPPORTED
config VIRTIO_MMIO
bool
@@ -35,10 +36,17 @@ config VIRTIO_CRYPTO
default y
depends on VIRTIO
+# not all virtio transports support memory devices; if none does,
+# no need to include the code
+config VIRTIO_MD_SUPPORTED
+ bool
+
config VIRTIO_MD
bool
+ depends on VIRTIO_MD_SUPPORTED
select MEM_DEVICE
+# selected by the board if it has the required support code
config VIRTIO_PMEM_SUPPORTED
bool
@@ -46,9 +54,11 @@ config VIRTIO_PMEM
bool
default y
depends on VIRTIO
+ depends on VIRTIO_MD_SUPPORTED
depends on VIRTIO_PMEM_SUPPORTED
select VIRTIO_MD
+# selected by the board if it has the required support code
config VIRTIO_MEM_SUPPORTED
bool
@@ -57,6 +67,7 @@ config VIRTIO_MEM
default y
depends on VIRTIO
depends on LINUX
+ depends on VIRTIO_MD_SUPPORTED
depends on VIRTIO_MEM_SUPPORTED
select VIRTIO_MD
--
2.48.1

View File

@ -0,0 +1,79 @@
From 001200670ce9076a34419828e7e7ba92f19a80b7 Mon Sep 17 00:00:00 2001
From: Juraj Marcin <jmarcin@redhat.com>
Date: Wed, 4 Sep 2024 12:37:15 +0200
Subject: [PATCH 08/26] virtio-mem: Add support for suspend+wake-up with
plugged memory
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [8/26] 08e25d41e32b3ac2bf5e0266f9c7e91739eda4d4 (thuth/qemu-kvm-cs)
Before, the virtio-mem device would unplug all the memory with any reset
of the device, including during the wake-up of the guest from a
suspended state. Due to this, the virtio-mem driver in the Linux kernel
disallowed suspend-to-ram requests in the guest when the
VIRTIO_MEM_F_PERSISTENT_SUSPEND feature is not exposed by QEMU.
This patch adds the code to skip the reset on wake-up and exposes
theVIRTIO_MEM_F_PERSISTENT_SUSPEND feature to the guest kernel driver
when suspending is possible in QEMU (currently only x86).
Message-ID: <20240904103722.946194-5-jmarcin@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 1f5f49056d0f140568805d66f33396ed5cd90369)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/virtio/virtio-mem.c | 10 ++++++++++
hw/virtio/virtio-qmp.c | 3 +++
2 files changed, 13 insertions(+)
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 025ae4abac..51642a15ef 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -883,6 +883,9 @@ static uint64_t virtio_mem_get_features(VirtIODevice *vdev, uint64_t features,
if (vmem->unplugged_inaccessible == ON_OFF_AUTO_ON) {
virtio_add_feature(&features, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE);
}
+ if (qemu_wakeup_suspend_enabled()) {
+ virtio_add_feature(&features, VIRTIO_MEM_F_PERSISTENT_SUSPEND);
+ }
return features;
}
@@ -1842,6 +1845,13 @@ static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
{
VirtIOMEM *vmem = VIRTIO_MEM(obj);
+ /*
+ * When waking up from standby/suspend-to-ram, do not unplug any memory.
+ */
+ if (type == RESET_TYPE_WAKEUP) {
+ return;
+ }
+
/*
* During usual resets, we will unplug all memory and shrink the usable
* region size. This is, however, not possible in all scenarios. Then,
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 1dd96ed20f..cccc6fe761 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -450,6 +450,9 @@ static const qmp_virtio_feature_map_t virtio_mem_feature_map[] = {
FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \
"VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be "
"accessed"),
+ FEATURE_ENTRY(VIRTIO_MEM_F_PERSISTENT_SUSPEND, \
+ "VIRTIO_MEM_F_PERSISTENT_SUSPND: Plugged memory will remain "
+ "plugged when suspending+resuming"),
{ -1, "" }
};
#endif
--
2.48.1

View File

@ -0,0 +1,141 @@
From 6bc0cdecdc736d642bb6c040e07d79a0a3e591ea Mon Sep 17 00:00:00 2001
From: Juraj Marcin <jmarcin@redhat.com>
Date: Wed, 4 Sep 2024 12:37:14 +0200
Subject: [PATCH 07/26] virtio-mem: Use new Resettable framework instead of
LegacyReset
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [7/26] 31fddbeb4aaf6794b83399a7e2996f01d918d748 (thuth/qemu-kvm-cs)
LegacyReset does not pass ResetType to the reset callback method, which
the new Resettable framework uses. Due to this, virtio-mem cannot use
the new RESET_TYPE_WAKEUP to skip the reset during wake-up from a
suspended state.
This patch adds overrides Resettable interface methods in VirtIOMEMClass
to use the new Resettable framework and replaces
qemu_[un]register_reset() calls with qemu_[un]register_resettable().
Message-ID: <20240904103722.946194-4-jmarcin@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit c009a311e93963860cfba917605a4bf903a06bce)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/virtio/virtio-mem.c | 38 +++++++++++++++++++++-------------
include/hw/virtio/virtio-mem.h | 4 ++++
2 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index ba11aa4646..025ae4abac 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -895,18 +895,6 @@ static int virtio_mem_validate_features(VirtIODevice *vdev)
return 0;
}
-static void virtio_mem_system_reset(void *opaque)
-{
- VirtIOMEM *vmem = VIRTIO_MEM(opaque);
-
- /*
- * During usual resets, we will unplug all memory and shrink the usable
- * region size. This is, however, not possible in all scenarios. Then,
- * the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
- */
- virtio_mem_unplug_all(vmem);
-}
-
static void virtio_mem_prepare_mr(VirtIOMEM *vmem)
{
const uint64_t region_size = memory_region_size(&vmem->memdev->mr);
@@ -1123,7 +1111,7 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
vmstate_register_any(VMSTATE_IF(vmem),
&vmstate_virtio_mem_device_early, vmem);
}
- qemu_register_reset(virtio_mem_system_reset, vmem);
+ qemu_register_resettable(OBJECT(vmem));
/*
* Set ourselves as RamDiscardManager before the plug handler maps the
@@ -1143,7 +1131,7 @@ static void virtio_mem_device_unrealize(DeviceState *dev)
* found via an address space anymore. Unset ourselves.
*/
memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
- qemu_unregister_reset(virtio_mem_system_reset, vmem);
+ qemu_unregister_resettable(OBJECT(vmem));
if (vmem->early_migration) {
vmstate_unregister(VMSTATE_IF(vmem), &vmstate_virtio_mem_device_early,
vmem);
@@ -1844,12 +1832,31 @@ static void virtio_mem_unplug_request_check(VirtIOMEM *vmem, Error **errp)
}
}
+static ResettableState *virtio_mem_get_reset_state(Object *obj)
+{
+ VirtIOMEM *vmem = VIRTIO_MEM(obj);
+ return &vmem->reset_state;
+}
+
+static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
+{
+ VirtIOMEM *vmem = VIRTIO_MEM(obj);
+
+ /*
+ * During usual resets, we will unplug all memory and shrink the usable
+ * region size. This is, however, not possible in all scenarios. Then,
+ * the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
+ */
+ virtio_mem_unplug_all(vmem);
+}
+
static void virtio_mem_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass);
RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
device_class_set_props(dc, virtio_mem_properties);
dc->vmsd = &vmstate_virtio_mem;
@@ -1876,6 +1883,9 @@ static void virtio_mem_class_init(ObjectClass *klass, void *data)
rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
rdmc->register_listener = virtio_mem_rdm_register_listener;
rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
+
+ rc->get_state = virtio_mem_get_reset_state;
+ rc->phases.hold = virtio_mem_system_reset_hold;
}
static const TypeInfo virtio_mem_info = {
diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index 5f5b02b8f9..a1af144c28 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -14,6 +14,7 @@
#define HW_VIRTIO_MEM_H
#include "standard-headers/linux/virtio_mem.h"
+#include "hw/resettable.h"
#include "hw/virtio/virtio.h"
#include "qapi/qapi-types-misc.h"
#include "sysemu/hostmem.h"
@@ -115,6 +116,9 @@ struct VirtIOMEM {
/* listeners to notify on plug/unplug activity. */
QLIST_HEAD(, RamDiscardListener) rdl_list;
+
+ /* State of the resettable container */
+ ResettableState reset_state;
};
struct VirtIOMEMClass {
--
2.48.1

View File

@ -0,0 +1,59 @@
From f4052d25199bfce8ce29a173934a805fe1cf7e3e Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Tue, 10 Sep 2024 18:34:33 +0200
Subject: [PATCH 25/26] virtio-mem: don't warn about THP sizes on a kernel
without THP support
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [25/26] 5dff17ef818722db8f1fa87cff5b7777afc3c814 (thuth/qemu-kvm-cs)
If the config directory in sysfs does not exist at all, we are dealing
with a system that does not support THPs. Simply use 1 MiB block size
then, instead of warning "Could not detect THP size, falling back to
..." and falling back to the default THP size.
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Gavin Shan <gshan@redhat.com>
Cc: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20240910163433.2100295-1-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 95b717a8154b955de2782305f305b63f357b0576)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/virtio/virtio-mem.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index c9f8a23bbc..4977658312 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -90,6 +90,7 @@ static uint32_t virtio_mem_default_thp_size(void)
static uint32_t thp_size;
#define HPAGE_PMD_SIZE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size"
+#define HPAGE_PATH "/sys/kernel/mm/transparent_hugepage/"
static uint32_t virtio_mem_thp_size(void)
{
gchar *content = NULL;
@@ -100,6 +101,12 @@ static uint32_t virtio_mem_thp_size(void)
return thp_size;
}
+ /* No THP -> no restrictions. */
+ if (!g_file_test(HPAGE_PATH, G_FILE_TEST_EXISTS)) {
+ thp_size = VIRTIO_MEM_MIN_BLOCK_SIZE;
+ return thp_size;
+ }
+
/*
* Try to probe the actual THP size, fallback to (sane but eventually
* incorrect) default sizes.
--
2.48.1

View File

@ -0,0 +1,258 @@
From e5f2bb584154eef665211228f1ac3113e2acc269 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Fri, 25 Oct 2024 12:41:03 +0200
Subject: [PATCH 09/26] virtio-mem: unplug memory only during system resets,
not device resets
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 351: Enable virtio-mem support on s390x
RH-Jira: RHEL-72977
RH-Acked-by: David Hildenbrand <david@redhat.com>
RH-Acked-by: Juraj Marcin <None>
RH-Commit: [9/26] 7c5ddd4d3fd0d19caa946bcbe98cb5732404978b (thuth/qemu-kvm-cs)
We recently converted from the LegacyReset to the new reset framework
in commit c009a311e939 ("virtio-mem: Use new Resettable framework instead
of LegacyReset") to be able to use the ResetType to filter out wakeup
resets.
However, this change had an undesired implications: as we override the
Resettable interface methods in VirtIOMEMClass, the reset handler will
not only get called during system resets (i.e., qemu_devices_reset())
but also during any direct or indirect device rests (e.g.,
device_cold_reset()).
Further, we might now receive two reset callbacks during
qemu_devices_reset(), first when reset by a parent and later when reset
directly.
The memory state of virtio-mem devices is rather special: it's supposed to
be persistent/unchanged during most resets (similar to resetting a hard
disk will not destroy the data), unless actually cold-resetting the whole
system (different to a hard disk where a reboot will not destroy the data):
ripping out system RAM is something guest OSes don't particularly enjoy,
but we want to detect when rebooting to an OS that does not support
virtio-mem and wouldn't be able to detect+use the memory -- and we want
to force-defragment hotplugged memory to also shrink the usable device
memory region. So we rally want to catch system resets to do that.
On supported targets (e.g., x86), getting a cold reset on the
device/parent triggers is not that easy (but looks like PCI code
might trigger it), so this implication went unnoticed.
However, with upcoming s390x support it is problematic: during
kdump, s390x triggers a subsystem reset, ending up in
s390_machine_reset() and calling only subsystem_reset() instead of
qemu_devices_reset() -- because it's not a full system reset.
In subsystem_reset(), s390x performs a device_cold_reset() of any
TYPE_VIRTUAL_CSS_BRIDGE device, which ends up resetting all children,
including the virtio-mem device. Consequently, we wrongly detect a system
reset and unplug all device memory, resulting in hotplugged memory not
getting included in the crash dump -- undesired.
We really must not mess with hotplugged memory state during simple
device resets. To fix, create+register a new reset object that will only
get triggered during qemu_devices_reset() calls, but not during any other
resets as it is logically not the child of any other object.
Message-ID: <20241025104103.342188-1-david@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Juraj Marcin <jmarcin@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 713484d0389c9d1cbb87eca060361281248b69f5)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/virtio/virtio-mem.c | 103 +++++++++++++++++++++++----------
include/hw/virtio/virtio-mem.h | 13 ++++-
2 files changed, 84 insertions(+), 32 deletions(-)
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 51642a15ef..00da98b6e1 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -949,6 +949,7 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
VirtIOMEM *vmem = VIRTIO_MEM(dev);
uint64_t page_size;
RAMBlock *rb;
+ Object *obj;
int ret;
if (!vmem->memdev) {
@@ -1114,7 +1115,28 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp)
vmstate_register_any(VMSTATE_IF(vmem),
&vmstate_virtio_mem_device_early, vmem);
}
- qemu_register_resettable(OBJECT(vmem));
+
+ /*
+ * We only want to unplug all memory to start with a clean slate when
+ * it is safe for the guest -- during system resets that call
+ * qemu_devices_reset().
+ *
+ * We'll filter out selected qemu_devices_reset() calls used for other
+ * purposes, like resetting all devices during wakeup from suspend on
+ * x86 based on the reset type passed to qemu_devices_reset().
+ *
+ * Unplugging all memory during simple device resets can result in the VM
+ * unexpectedly losing RAM, corrupting VM state.
+ *
+ * Simple device resets (or resets triggered by getting a parent device
+ * reset) must not change the state of plugged memory blocks. Therefore,
+ * we need a dedicated reset object that only gets called during
+ * qemu_devices_reset().
+ */
+ obj = object_new(TYPE_VIRTIO_MEM_SYSTEM_RESET);
+ vmem->system_reset = VIRTIO_MEM_SYSTEM_RESET(obj);
+ vmem->system_reset->vmem = vmem;
+ qemu_register_resettable(obj);
/*
* Set ourselves as RamDiscardManager before the plug handler maps the
@@ -1134,7 +1156,10 @@ static void virtio_mem_device_unrealize(DeviceState *dev)
* found via an address space anymore. Unset ourselves.
*/
memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL);
- qemu_unregister_resettable(OBJECT(vmem));
+
+ qemu_unregister_resettable(OBJECT(vmem->system_reset));
+ object_unref(OBJECT(vmem->system_reset));
+
if (vmem->early_migration) {
vmstate_unregister(VMSTATE_IF(vmem), &vmstate_virtio_mem_device_early,
vmem);
@@ -1835,38 +1860,12 @@ static void virtio_mem_unplug_request_check(VirtIOMEM *vmem, Error **errp)
}
}
-static ResettableState *virtio_mem_get_reset_state(Object *obj)
-{
- VirtIOMEM *vmem = VIRTIO_MEM(obj);
- return &vmem->reset_state;
-}
-
-static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
-{
- VirtIOMEM *vmem = VIRTIO_MEM(obj);
-
- /*
- * When waking up from standby/suspend-to-ram, do not unplug any memory.
- */
- if (type == RESET_TYPE_WAKEUP) {
- return;
- }
-
- /*
- * During usual resets, we will unplug all memory and shrink the usable
- * region size. This is, however, not possible in all scenarios. Then,
- * the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
- */
- virtio_mem_unplug_all(vmem);
-}
-
static void virtio_mem_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
VirtIOMEMClass *vmc = VIRTIO_MEM_CLASS(klass);
RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(klass);
- ResettableClass *rc = RESETTABLE_CLASS(klass);
device_class_set_props(dc, virtio_mem_properties);
dc->vmsd = &vmstate_virtio_mem;
@@ -1893,9 +1892,6 @@ static void virtio_mem_class_init(ObjectClass *klass, void *data)
rdmc->replay_discarded = virtio_mem_rdm_replay_discarded;
rdmc->register_listener = virtio_mem_rdm_register_listener;
rdmc->unregister_listener = virtio_mem_rdm_unregister_listener;
-
- rc->get_state = virtio_mem_get_reset_state;
- rc->phases.hold = virtio_mem_system_reset_hold;
}
static const TypeInfo virtio_mem_info = {
@@ -1918,3 +1914,48 @@ static void virtio_register_types(void)
}
type_init(virtio_register_types)
+
+OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(VirtioMemSystemReset, virtio_mem_system_reset, VIRTIO_MEM_SYSTEM_RESET, OBJECT, { TYPE_RESETTABLE_INTERFACE }, { })
+
+static void virtio_mem_system_reset_init(Object *obj)
+{
+}
+
+static void virtio_mem_system_reset_finalize(Object *obj)
+{
+}
+
+static ResettableState *virtio_mem_system_reset_get_state(Object *obj)
+{
+ VirtioMemSystemReset *vmem_reset = VIRTIO_MEM_SYSTEM_RESET(obj);
+
+ return &vmem_reset->reset_state;
+}
+
+static void virtio_mem_system_reset_hold(Object *obj, ResetType type)
+{
+ VirtioMemSystemReset *vmem_reset = VIRTIO_MEM_SYSTEM_RESET(obj);
+ VirtIOMEM *vmem = vmem_reset->vmem;
+
+ /*
+ * When waking up from standby/suspend-to-ram, do not unplug any memory.
+ */
+ if (type == RESET_TYPE_WAKEUP) {
+ return;
+ }
+
+ /*
+ * During usual resets, we will unplug all memory and shrink the usable
+ * region size. This is, however, not possible in all scenarios. Then,
+ * the guest has to deal with this manually (VIRTIO_MEM_REQ_UNPLUG_ALL).
+ */
+ virtio_mem_unplug_all(vmem);
+}
+
+static void virtio_mem_system_reset_class_init(ObjectClass *klass, void *data)
+{
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ rc->get_state = virtio_mem_system_reset_get_state;
+ rc->phases.hold = virtio_mem_system_reset_hold;
+}
diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h
index a1af144c28..550ce585b2 100644
--- a/include/hw/virtio/virtio-mem.h
+++ b/include/hw/virtio/virtio-mem.h
@@ -25,6 +25,10 @@
OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass,
VIRTIO_MEM)
+#define TYPE_VIRTIO_MEM_SYSTEM_RESET "virtio-mem-system-reset"
+
+OBJECT_DECLARE_SIMPLE_TYPE(VirtioMemSystemReset, VIRTIO_MEM_SYSTEM_RESET)
+
#define VIRTIO_MEM_MEMDEV_PROP "memdev"
#define VIRTIO_MEM_NODE_PROP "node"
#define VIRTIO_MEM_SIZE_PROP "size"
@@ -117,8 +121,15 @@ struct VirtIOMEM {
/* listeners to notify on plug/unplug activity. */
QLIST_HEAD(, RamDiscardListener) rdl_list;
- /* State of the resettable container */
+ /* Catch system resets -> qemu_devices_reset() only. */
+ VirtioMemSystemReset *system_reset;
+};
+
+struct VirtioMemSystemReset {
+ Object parent;
+
ResettableState reset_state;
+ VirtIOMEM *vmem;
};
struct VirtIOMEMClass {
--
2.48.1

View File

@ -149,7 +149,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \
Summary: QEMU is a machine emulator and virtualizer
Name: qemu-kvm
Version: 9.1.0
Release: 17%{?rcrel}%{?dist}%{?cc_suffix}
Release: 18%{?rcrel}%{?dist}%{?cc_suffix}
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
# Epoch 15 used for RHEL 8
# Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
@ -493,6 +493,58 @@ Patch160: kvm-vfio-pci-Delete-local-pm_cap.patch
Patch161: kvm-pcie-virtio-Remove-redundant-pm_cap.patch
# For RHEL-7301 - [intel iommu] VFIO_MAP_DMA failed: Bad address on system_powerdown
Patch162: kvm-hw-vfio-pci-Re-order-pre-reset.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch163: kvm-virtio-kconfig-memory-devices-are-PCI-only.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch164: kvm-hw-s390-ccw-device-Convert-to-three-phase-reset.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch165: kvm-hw-s390-virtio-ccw-Convert-to-three-phase-reset.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch166: kvm-target-s390-Convert-CPU-to-Resettable-interface.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch167: kvm-reset-Use-ResetType-for-qemu_devices_reset-and-Machi.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch168: kvm-reset-Add-RESET_TYPE_WAKEUP.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch169: kvm-virtio-mem-Use-new-Resettable-framework-instead-of-L.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch170: kvm-virtio-mem-Add-support-for-suspend-wake-up-with-plug.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch171: kvm-virtio-mem-unplug-memory-only-during-system-resets-n.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch172: kvm-s390x-s390-virtio-ccw-don-t-crash-on-weird-RAM-sizes.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch173: kvm-s390x-s390-virtio-hcall-remove-hypercall-registratio.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch174: kvm-s390x-s390-virtio-hcall-prepare-for-more-diag500-hyp.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch175: kvm-s390x-rename-s390-virtio-hcall-to-s390-hypercall.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch176: kvm-s390x-s390-virtio-ccw-move-setting-the-maximum-guest.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch177: kvm-s390x-introduce-s390_get_memory_limit.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch178: kvm-s390x-s390-hypercall-introduce-DIAG500-STORAGE_LIMIT.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch179: kvm-s390x-s390-stattrib-kvm-prepare-for-memory-devices-a.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch180: kvm-s390x-s390-skeys-prepare-for-memory-devices.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch181: kvm-s390x-s390-virtio-ccw-prepare-for-memory-devices.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch182: kvm-s390x-pv-prepare-for-memory-devices.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch183: kvm-s390x-remember-the-maximum-page-size.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch184: kvm-s390x-virtio-ccw-add-support-for-virtio-based-memory.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch185: kvm-s390x-virtio-mem-support.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch186: kvm-hw-virtio-Also-include-md-stubs-in-case-CONFIG_VIRTI.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch187: kvm-virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch
# For RHEL-72977 - [IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part
Patch188: kvm-redhat-Enable-virtio-mem-on-s390x.patch
%if %{have_clang}
BuildRequires: clang
@ -1561,6 +1613,36 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
%endif
%changelog
* Mon Apr 14 2025 Jon Maloy <jmaloy@redhat.com> - 9.1.0-18
- kvm-virtio-kconfig-memory-devices-are-PCI-only.patch [RHEL-72977]
- kvm-hw-s390-ccw-device-Convert-to-three-phase-reset.patch [RHEL-72977]
- kvm-hw-s390-virtio-ccw-Convert-to-three-phase-reset.patch [RHEL-72977]
- kvm-target-s390-Convert-CPU-to-Resettable-interface.patch [RHEL-72977]
- kvm-reset-Use-ResetType-for-qemu_devices_reset-and-Machi.patch [RHEL-72977]
- kvm-reset-Add-RESET_TYPE_WAKEUP.patch [RHEL-72977]
- kvm-virtio-mem-Use-new-Resettable-framework-instead-of-L.patch [RHEL-72977]
- kvm-virtio-mem-Add-support-for-suspend-wake-up-with-plug.patch [RHEL-72977]
- kvm-virtio-mem-unplug-memory-only-during-system-resets-n.patch [RHEL-72977]
- kvm-s390x-s390-virtio-ccw-don-t-crash-on-weird-RAM-sizes.patch [RHEL-72977]
- kvm-s390x-s390-virtio-hcall-remove-hypercall-registratio.patch [RHEL-72977]
- kvm-s390x-s390-virtio-hcall-prepare-for-more-diag500-hyp.patch [RHEL-72977]
- kvm-s390x-rename-s390-virtio-hcall-to-s390-hypercall.patch [RHEL-72977]
- kvm-s390x-s390-virtio-ccw-move-setting-the-maximum-guest.patch [RHEL-72977]
- kvm-s390x-introduce-s390_get_memory_limit.patch [RHEL-72977]
- kvm-s390x-s390-hypercall-introduce-DIAG500-STORAGE_LIMIT.patch [RHEL-72977]
- kvm-s390x-s390-stattrib-kvm-prepare-for-memory-devices-a.patch [RHEL-72977]
- kvm-s390x-s390-skeys-prepare-for-memory-devices.patch [RHEL-72977]
- kvm-s390x-s390-virtio-ccw-prepare-for-memory-devices.patch [RHEL-72977]
- kvm-s390x-pv-prepare-for-memory-devices.patch [RHEL-72977]
- kvm-s390x-remember-the-maximum-page-size.patch [RHEL-72977]
- kvm-s390x-virtio-ccw-add-support-for-virtio-based-memory.patch [RHEL-72977]
- kvm-s390x-virtio-mem-support.patch [RHEL-72977]
- kvm-hw-virtio-Also-include-md-stubs-in-case-CONFIG_VIRTI.patch [RHEL-72977]
- kvm-virtio-mem-don-t-warn-about-THP-sizes-on-a-kernel-wi.patch [RHEL-72977]
- kvm-redhat-Enable-virtio-mem-on-s390x.patch [RHEL-72977]
- Resolves: RHEL-72977
([IBM 9.7 FEAT] KVM: Enable virtio-mem support - qemu part)
* Mon Mar 31 2025 Jon Maloy <jmaloy@redhat.com> - 9.1.0-17
- kvm-hw-pci-Rename-has_power-to-enabled.patch [RHEL-7301]
- kvm-hw-pci-Basic-support-for-PCI-power-management.patch [RHEL-7301]