qemu-kvm/kvm-s390x-s390-stattrib-kvm-prepare-for-memory-devices-a.patch
Jon Maloy eace179c9a * 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)
2025-04-14 18:57:58 -04:00

156 lines
6.0 KiB
Diff

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