From: Janosch Frank <frankja@linux.ibm.com>
Date: Mon, 17 Oct 2022 08:38:19 +0000
Subject: s390x: Introduce PV query interface
Git-commit: 03d83ecfae46bf5e0074cb5808043b30df34064b
References: jsc#PED-1716
Introduce an interface over which we can get information about UV data.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20221017083822.43118-8-frankja@linux.ibm.com>
Signed-off-by: Li Zhang <lizhang@suse.de>
---
hw/s390x/pv.c | 61 ++++++++++++++++++++++++++++++++++++++
hw/s390x/s390-virtio-ccw.c | 6 ++++
include/hw/s390x/pv.h | 10 +++++++
3 files changed, 77 insertions(+)
diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c
index 401b63d6cb659c412f4f34d2d05d..4c012f2eebd596ec86397350c9b7 100644
--- a/hw/s390x/pv.c
+++ b/hw/s390x/pv.c
@@ -20,6 +20,11 @@
#include "exec/confidential-guest-support.h"
#include "hw/s390x/ipl.h"
#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/kvm_s390x.h"
+
+static bool info_valid;
+static struct kvm_s390_pv_info_vm info_vm;
+static struct kvm_s390_pv_info_dump info_dump;
static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
{
@@ -56,6 +61,42 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
} \
}
+int s390_pv_query_info(void)
+{
+ struct kvm_s390_pv_info info = {
+ .header.id = KVM_PV_INFO_VM,
+ .header.len_max = sizeof(info.header) + sizeof(info.vm),
+ };
+ int rc;
+
+ /* Info API's first user is dump so they are bundled */
+ if (!kvm_s390_get_protected_dump()) {
+ return 0;
+ }
+
+ rc = s390_pv_cmd(KVM_PV_INFO, &info);
+ if (rc) {
+ error_report("KVM PV INFO cmd %x failed: %s",
+ info.header.id, strerror(-rc));
+ return rc;
+ }
+ memcpy(&info_vm, &info.vm, sizeof(info.vm));
+
+ info.header.id = KVM_PV_INFO_DUMP;
+ info.header.len_max = sizeof(info.header) + sizeof(info.dump);
+ rc = s390_pv_cmd(KVM_PV_INFO, &info);
+ if (rc) {
+ error_report("KVM PV INFO cmd %x failed: %s",
+ info.header.id, strerror(-rc));
+ return rc;
+ }
+
+ memcpy(&info_dump, &info.dump, sizeof(info.dump));
+ info_valid = true;
+
+ return rc;
+}
+
int s390_pv_vm_enable(void)
{
return s390_pv_cmd(KVM_PV_ENABLE, NULL);
@@ -114,6 +155,26 @@ void s390_pv_inject_reset_error(CPUState *cs)
env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
}
+uint64_t kvm_s390_pv_dmp_get_size_cpu(void)
+{
+ return info_dump.dump_cpu_buffer_len;
+}
+
+uint64_t kvm_s390_pv_dmp_get_size_completion_data(void)
+{
+ return info_dump.dump_config_finalize_len;
+}
+
+uint64_t kvm_s390_pv_dmp_get_size_mem_state(void)
+{
+ return info_dump.dump_config_mem_buffer_per_1m;
+}
+
+bool kvm_s390_pv_info_basic_valid(void)
+{
+ return info_valid;
+}
+
#define TYPE_S390_PV_GUEST "s390-pv-guest"
OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index cc3097bfee8073bd2b08d58a50d9..7982f7973fce7c411efc3095e9be 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -366,6 +366,12 @@ static int s390_machine_protect(S390CcwMachineState *ms)
ms->pv = true;
+ /* Will return 0 if API is not available since it's not vital */
+ rc = s390_pv_query_info();
+ if (rc) {
+ goto out_err;
+ }
+
/* Set SE header and unpack */
rc = s390_ipl_prepare_pv_header();
if (rc) {
diff --git a/include/hw/s390x/pv.h b/include/hw/s390x/pv.h
index 1f1f545bfc20231604b119783ef6..e5ea0eca16c946e30ecfb0aa1c28 100644
--- a/include/hw/s390x/pv.h
+++ b/include/hw/s390x/pv.h
@@ -38,6 +38,7 @@ static inline bool s390_is_pv(void)
return ccw->pv;
}
+int s390_pv_query_info(void);
int s390_pv_vm_enable(void);
void s390_pv_vm_disable(void);
int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
@@ -46,8 +47,13 @@ void s390_pv_prep_reset(void);
int s390_pv_verify(void);
void s390_pv_unshare(void);
void s390_pv_inject_reset_error(CPUState *cs);
+uint64_t kvm_s390_pv_dmp_get_size_cpu(void);
+uint64_t kvm_s390_pv_dmp_get_size_mem_state(void);
+uint64_t kvm_s390_pv_dmp_get_size_completion_data(void);
+bool kvm_s390_pv_info_basic_valid(void);
#else /* CONFIG_KVM */
static inline bool s390_is_pv(void) { return false; }
+static inline int s390_pv_query_info(void) { return 0; }
static inline int s390_pv_vm_enable(void) { return 0; }
static inline void s390_pv_vm_disable(void) {}
static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; }
@@ -56,6 +62,10 @@ static inline void s390_pv_prep_reset(void) {}
static inline int s390_pv_verify(void) { return 0; }
static inline void s390_pv_unshare(void) {}
static inline void s390_pv_inject_reset_error(CPUState *cs) {};
+static inline uint64_t kvm_s390_pv_dmp_get_size_cpu(void) { return 0; }
+static inline uint64_t kvm_s390_pv_dmp_get_size_mem_state(void) { return 0; }
+static inline uint64_t kvm_s390_pv_dmp_get_size_completion_data(void) { return 0; }
+static inline bool kvm_s390_pv_info_basic_valid(void) { return false; }
#endif /* CONFIG_KVM */
int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);