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