- 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)
156 lines
6.0 KiB
Diff
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
|
|
|