thebeanogamer / rpms / qemu-kvm

Forked from rpms/qemu-kvm 5 months ago
Clone
ed5979
From 9452246e59a5f16f44fdf9a7d514b947faf1d5fc Mon Sep 17 00:00:00 2001
ed5979
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
ed5979
Date: Mon, 16 Jan 2023 18:46:05 +0100
ed5979
Subject: [PATCH 5/9] s390x/pv: Implement a CGS check helper
ed5979
MIME-Version: 1.0
ed5979
Content-Type: text/plain; charset=UTF-8
ed5979
Content-Transfer-Encoding: 8bit
ed5979
ed5979
RH-Author: Cédric Le Goater <clg@redhat.com>
ed5979
RH-MergeRequest: 139: s390x/pv: Implement a CGS check helper
ed5979
RH-Bugzilla: 2122523
ed5979
RH-Acked-by: Thomas Huth <thuth@redhat.com>
ed5979
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
ed5979
RH-Acked-by: David Hildenbrand <david@redhat.com>
ed5979
RH-Commit: [1/1] 8551ce772b10de653b4e1c8be60aae60ec98b421 (clegoate/qemu-kvm-c9s)
ed5979
ed5979
When a protected VM is started with the maximum number of CPUs (248),
ed5979
the service call providing information on the CPUs requires more
ed5979
buffer space than allocated and QEMU disgracefully aborts :
ed5979
ed5979
    LOADPARM=[........]
ed5979
    Using virtio-blk.
ed5979
    Using SCSI scheme.
ed5979
    ...................................................................................
ed5979
    qemu-system-s390x: KVM_S390_MEM_OP failed: Argument list too long
ed5979
ed5979
When protected virtualization is initialized, compute the maximum
ed5979
number of vCPUs supported by the machine and return useful information
ed5979
to the user before the machine starts in case of error.
ed5979
ed5979
Suggested-by: Thomas Huth <thuth@redhat.com>
ed5979
Reviewed-by: Thomas Huth <thuth@redhat.com>
ed5979
Signed-off-by: Cédric Le Goater <clg@redhat.com>
ed5979
Message-Id: <20230116174607.2459498-2-clg@kaod.org>
ed5979
Signed-off-by: Thomas Huth <thuth@redhat.com>
ed5979
(cherry picked from commit 75d7150c636569f6687f7e70a33be893be43eb5f)
ed5979
Signed-off-by: Cédric Le Goater <clg@redhat.com>
ed5979
---
ed5979
 hw/s390x/pv.c | 40 ++++++++++++++++++++++++++++++++++++++++
ed5979
 1 file changed, 40 insertions(+)
ed5979
ed5979
diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c
ed5979
index 8dfe92d8df..8a1c71436b 100644
ed5979
--- a/hw/s390x/pv.c
ed5979
+++ b/hw/s390x/pv.c
ed5979
@@ -20,6 +20,7 @@
ed5979
 #include "exec/confidential-guest-support.h"
ed5979
 #include "hw/s390x/ipl.h"
ed5979
 #include "hw/s390x/pv.h"
ed5979
+#include "hw/s390x/sclp.h"
ed5979
 #include "target/s390x/kvm/kvm_s390x.h"
ed5979
 
ed5979
 static bool info_valid;
ed5979
@@ -249,6 +250,41 @@ struct S390PVGuestClass {
ed5979
     ConfidentialGuestSupportClass parent_class;
ed5979
 };
ed5979
 
ed5979
+/*
ed5979
+ * If protected virtualization is enabled, the amount of data that the
ed5979
+ * Read SCP Info Service Call can use is limited to one page. The
ed5979
+ * available space also depends on the Extended-Length SCCB (ELS)
ed5979
+ * feature which can take more buffer space to store feature
ed5979
+ * information. This impacts the maximum number of CPUs supported in
ed5979
+ * the machine.
ed5979
+ */
ed5979
+static uint32_t s390_pv_get_max_cpus(void)
ed5979
+{
ed5979
+    int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ?
ed5979
+        offsetof(ReadInfo, entries) : SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET;
ed5979
+
ed5979
+    return (TARGET_PAGE_SIZE - offset_cpu) / sizeof(CPUEntry);
ed5979
+}
ed5979
+
ed5979
+static bool s390_pv_check_cpus(Error **errp)
ed5979
+{
ed5979
+    MachineState *ms = MACHINE(qdev_get_machine());
ed5979
+    uint32_t pv_max_cpus = s390_pv_get_max_cpus();
ed5979
+
ed5979
+    if (ms->smp.max_cpus > pv_max_cpus) {
ed5979
+        error_setg(errp, "Protected VMs support a maximum of %d CPUs",
ed5979
+                   pv_max_cpus);
ed5979
+        return false;
ed5979
+    }
ed5979
+
ed5979
+    return true;
ed5979
+}
ed5979
+
ed5979
+static bool s390_pv_guest_check(ConfidentialGuestSupport *cgs, Error **errp)
ed5979
+{
ed5979
+    return s390_pv_check_cpus(errp);
ed5979
+}
ed5979
+
ed5979
 int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
ed5979
 {
ed5979
     if (!object_dynamic_cast(OBJECT(cgs), TYPE_S390_PV_GUEST)) {
ed5979
@@ -261,6 +297,10 @@ int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
ed5979
         return -1;
ed5979
     }
ed5979
 
ed5979
+    if (!s390_pv_guest_check(cgs, errp)) {
ed5979
+        return -1;
ed5979
+    }
ed5979
+
ed5979
     cgs->ready = true;
ed5979
 
ed5979
     return 0;
ed5979
-- 
ed5979
2.31.1
ed5979