221 lines
9.2 KiB
Diff
221 lines
9.2 KiB
Diff
From e1a3684f9b08fa9db35331b5c5ad11879f512e90 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Huth <thuth@redhat.com>
|
|
Date: Wed, 11 Nov 2020 12:03:11 -0500
|
|
Subject: [PATCH 11/18] s390/sclp: add extended-length sccb support for kvm
|
|
guest
|
|
|
|
RH-Author: Thomas Huth <thuth@redhat.com>
|
|
Message-id: <20201111120316.707489-8-thuth@redhat.com>
|
|
Patchwork-id: 99504
|
|
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 07/12] s390/sclp: add extended-length sccb support for kvm guest
|
|
Bugzilla: 1798506
|
|
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
|
|
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
|
RH-Acked-by: David Hildenbrand <david@redhat.com>
|
|
|
|
From: Collin Walling <walling@linux.ibm.com>
|
|
|
|
As more features and facilities are added to the Read SCP Info (RSCPI)
|
|
response, more space is required to store them. The space used to store
|
|
these new features intrudes on the space originally used to store CPU
|
|
entries. This means as more features and facilities are added to the
|
|
RSCPI response, less space can be used to store CPU entries.
|
|
|
|
With the Extended-Length SCCB (ELS) facility, a KVM guest can execute
|
|
the RSCPI command and determine if the SCCB is large enough to store a
|
|
complete reponse. If it is not large enough, then the required length
|
|
will be set in the SCCB header.
|
|
|
|
The caller of the SCLP command is responsible for creating a
|
|
large-enough SCCB to store a complete response. Proper checking should
|
|
be in place, and the caller should execute the command once-more with
|
|
the large-enough SCCB.
|
|
|
|
This facility also enables an extended SCCB for the Read CPU Info
|
|
(RCPUI) command.
|
|
|
|
When this facility is enabled, the boundary violation response cannot
|
|
be a result from the RSCPI, RSCPI Forced, or RCPUI commands.
|
|
|
|
In order to tolerate kernels that do not yet have full support for this
|
|
feature, a "fixed" offset to the start of the CPU Entries within the
|
|
Read SCP Info struct is set to allow for the original 248 max entries
|
|
when this feature is disabled.
|
|
|
|
Additionally, this is introduced as a CPU feature to protect the guest
|
|
from migrating to a machine that does not support storing an extended
|
|
SCCB. This could otherwise hinder the VM from being able to read all
|
|
available CPU entries after migration (such as during re-ipl).
|
|
|
|
Signed-off-by: Collin Walling <walling@linux.ibm.com>
|
|
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
|
Acked-by: Cornelia Huck <cohuck@redhat.com>
|
|
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
|
|
Message-Id: <20200915194416.107460-7-walling@linux.ibm.com>
|
|
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
|
|
(cherry picked from commit 1ecd6078f587cfadda8edc93d45b5072e35f2d17)
|
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
---
|
|
hw/s390x/sclp.c | 43 +++++++++++++++++++++++++----
|
|
include/hw/s390x/sclp.h | 1 +
|
|
target/s390x/cpu_features_def.inc.h | 1 +
|
|
target/s390x/gen-features.c | 1 +
|
|
target/s390x/kvm.c | 8 ++++++
|
|
5 files changed, 48 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
|
|
index 017989b3888..8d111628e04 100644
|
|
--- a/hw/s390x/sclp.c
|
|
+++ b/hw/s390x/sclp.c
|
|
@@ -49,13 +49,30 @@ static inline bool sclp_command_code_valid(uint32_t code)
|
|
return false;
|
|
}
|
|
|
|
-static bool sccb_verify_boundary(uint64_t sccb_addr, uint16_t sccb_len)
|
|
+static bool sccb_verify_boundary(uint64_t sccb_addr, uint16_t sccb_len,
|
|
+ uint32_t code)
|
|
{
|
|
uint64_t sccb_max_addr = sccb_addr + sccb_len - 1;
|
|
uint64_t sccb_boundary = (sccb_addr & PAGE_MASK) + PAGE_SIZE;
|
|
|
|
- if (sccb_max_addr < sccb_boundary) {
|
|
- return true;
|
|
+ switch (code & SCLP_CMD_CODE_MASK) {
|
|
+ case SCLP_CMDW_READ_SCP_INFO:
|
|
+ case SCLP_CMDW_READ_SCP_INFO_FORCED:
|
|
+ case SCLP_CMDW_READ_CPU_INFO:
|
|
+ /*
|
|
+ * An extended-length SCCB is only allowed for Read SCP/CPU Info and
|
|
+ * is allowed to exceed the 4k boundary. The respective commands will
|
|
+ * set the length field to the required length if an insufficient
|
|
+ * SCCB length is provided.
|
|
+ */
|
|
+ if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
|
|
+ return true;
|
|
+ }
|
|
+ /* fallthrough */
|
|
+ default:
|
|
+ if (sccb_max_addr < sccb_boundary) {
|
|
+ return true;
|
|
+ }
|
|
}
|
|
|
|
return false;
|
|
@@ -80,6 +97,12 @@ static void prepare_cpu_entries(MachineState *ms, CPUEntry *entry, int *count)
|
|
|
|
#define SCCB_REQ_LEN(s, max_cpus) (sizeof(s) + max_cpus * sizeof(CPUEntry))
|
|
|
|
+static inline bool ext_len_sccb_supported(SCCBHeader header)
|
|
+{
|
|
+ return s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) &&
|
|
+ header.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE;
|
|
+}
|
|
+
|
|
/* Provide information about the configuration, CPUs and storage */
|
|
static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
|
{
|
|
@@ -89,10 +112,15 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
|
int rnsize, rnmax;
|
|
IplParameterBlock *ipib = s390_ipl_get_iplb();
|
|
int required_len = SCCB_REQ_LEN(ReadInfo, machine->possible_cpus->len);
|
|
- int offset_cpu = offsetof(ReadInfo, entries);
|
|
+ int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ?
|
|
+ offsetof(ReadInfo, entries) :
|
|
+ SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET;
|
|
CPUEntry *entries_start = (void *)sccb + offset_cpu;
|
|
|
|
if (be16_to_cpu(sccb->h.length) < required_len) {
|
|
+ if (ext_len_sccb_supported(sccb->h)) {
|
|
+ sccb->h.length = cpu_to_be16(required_len);
|
|
+ }
|
|
sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
|
|
return;
|
|
}
|
|
@@ -153,6 +181,9 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
|
|
int required_len = SCCB_REQ_LEN(ReadCpuInfo, machine->possible_cpus->len);
|
|
|
|
if (be16_to_cpu(sccb->h.length) < required_len) {
|
|
+ if (ext_len_sccb_supported(sccb->h)) {
|
|
+ sccb->h.length = cpu_to_be16(required_len);
|
|
+ }
|
|
sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
|
|
return;
|
|
}
|
|
@@ -249,7 +280,7 @@ int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
|
|
goto out_write;
|
|
}
|
|
|
|
- if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length))) {
|
|
+ if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
|
|
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
|
|
goto out_write;
|
|
}
|
|
@@ -302,7 +333,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
|
|
goto out_write;
|
|
}
|
|
|
|
- if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length))) {
|
|
+ if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
|
|
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
|
|
goto out_write;
|
|
}
|
|
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
|
|
index 55f53a46540..df2fa4169b0 100644
|
|
--- a/include/hw/s390x/sclp.h
|
|
+++ b/include/hw/s390x/sclp.h
|
|
@@ -110,6 +110,7 @@ typedef struct CPUEntry {
|
|
uint8_t reserved1;
|
|
} QEMU_PACKED CPUEntry;
|
|
|
|
+#define SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET 128
|
|
typedef struct ReadInfo {
|
|
SCCBHeader h;
|
|
uint16_t rnmax;
|
|
diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h
|
|
index 60db28351d0..3548d65a69a 100644
|
|
--- a/target/s390x/cpu_features_def.inc.h
|
|
+++ b/target/s390x/cpu_features_def.inc.h
|
|
@@ -97,6 +97,7 @@ DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage facility")
|
|
DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility")
|
|
DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility")
|
|
DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility")
|
|
+DEF_FEAT(EXTENDED_LENGTH_SCCB, "els", STFL, 140, "Extended-length SCCB facility")
|
|
DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility")
|
|
DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility")
|
|
DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)")
|
|
diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
|
|
index 8ddeebc5441..6857f657fba 100644
|
|
--- a/target/s390x/gen-features.c
|
|
+++ b/target/s390x/gen-features.c
|
|
@@ -522,6 +522,7 @@ static uint16_t full_GEN12_GA1[] = {
|
|
S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL,
|
|
S390_FEAT_AP_FACILITIES_TEST,
|
|
S390_FEAT_AP,
|
|
+ S390_FEAT_EXTENDED_LENGTH_SCCB,
|
|
};
|
|
|
|
static uint16_t full_GEN12_GA2[] = {
|
|
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
|
|
index 0bbf8f81b09..ef437acb5c1 100644
|
|
--- a/target/s390x/kvm.c
|
|
+++ b/target/s390x/kvm.c
|
|
@@ -2441,6 +2441,14 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
|
|
KVM_S390_VM_CRYPTO_ENABLE_APIE)) {
|
|
set_bit(S390_FEAT_AP, model->features);
|
|
}
|
|
+
|
|
+ /*
|
|
+ * Extended-Length SCCB is handled entirely within QEMU.
|
|
+ * For PV guests this is completely fenced by the Ultravisor, as Service
|
|
+ * Call error checking and STFLE interpretation are handled via SIE.
|
|
+ */
|
|
+ set_bit(S390_FEAT_EXTENDED_LENGTH_SCCB, model->features);
|
|
+
|
|
/* strip of features that are not part of the maximum model */
|
|
bitmap_and(model->features, model->features, model->def->full_feat,
|
|
S390_FEAT_MAX);
|
|
--
|
|
2.27.0
|
|
|