diff --git a/qclib-sles15-fix-mismatch-case-with-STHYI.patch b/qclib-sles15-fix-mismatch-case-with-STHYI.patch new file mode 100644 index 0000000..9cf019d --- /dev/null +++ b/qclib-sles15-fix-mismatch-case-with-STHYI.patch @@ -0,0 +1,147 @@ +commit 13d7aafb0cb8946880abbb73725b0340bec1cd3a +Author: Stefan Raspl +Date: Fri Dec 8 22:11:29 2017 +0100 + + STHYI: Fix mismatch case with STHYI and /proc/sysinfo data + + Reported via Bz162324. Symptom was that qclib wouldn't work on a z/VM 5.4. + Analysis revealed that although the STHYI instruction wasn't available, the + newly added STHYI syscall would work, but (as intended) reported only layers + up to LPAR. In contrast, /proc/sysinfo would report all layers, including the + z/VM layer. Some detection logic kicked in and reported an error. + The problem was rooted in a bizarr combination of multiple glitches: + * An (unnecessary) extra handling for z/VM that was previously added would + raise an error on mismatching layer counts in STHYI and /proc/sysinfo. This + was to detect cases with more than 3 levels of nested virtualization. But the + check just was for mismatching counts and didn't check for the 3 layers + reported by STHYI at all. + * Furthermore, the check mentioned above was unnecessary to begin with: When + STHYI reports data for 3 VM layers, and /proc/sysinfo for more, then the + extra layers will simply not get any data from STHYI - no harm done. + * STHYI in KVM worked like a charm ever since, though it is supposed to fail + with the same error as z/VM since STHYI in KVM (and likewise the syscall in + LPARs) cannot report data beyond the LPAR layer - it should result in the + same mismatch that z/VM experienced. However, the respective routines would + only ever consider VM layers in z/VM and ignore the ones in KVM! Hence all + layers beyond LPAR wouldn't be accounted for on KVM! + To fix, we're ripping out the extra check, and rewrite the remaining code to + handle z/VM and KVM alike. + Furthermore, we rename "STHYI@VM" to "STHYI instruction", and "STHYI@LPAR" to + "STHYI syscall" for improved clarity. + +diff --git a/query_capacity_sthyi.c b/query_capacity_sthyi.c +index b3bd9e8..688062f 100644 +--- a/query_capacity_sthyi.c ++++ b/query_capacity_sthyi.c +@@ -91,16 +91,16 @@ static int qc_sthyi_lpar(struct qc_handle *hdl, struct sthyi_priv *priv) { + #ifdef __NR_s390_sthyi + sthyi = __NR_s390_sthyi + #endif +- qc_debug(hdl, "Try STHYI@LPAR\n"); ++ qc_debug(hdl, "Try STHYI syscall\n"); + if (syscall(sthyi, 0, priv->data, &cc, 0) || cc) { + if (errno == ENOSYS) { +- qc_debug(hdl, "STHYI@LPAR is not available\n"); ++ qc_debug(hdl, "STHYI syscall is not available\n"); + return 0; + } +- qc_debug(hdl, "Error: STHYI@LPAR execution failed: errno='%s', cc=%" PRIu64 "\n", strerror(errno), cc); ++ qc_debug(hdl, "Error: STHYI syscall execution failed: errno='%s', cc=%" PRIu64 "\n", strerror(errno), cc); + return -1; + } +- qc_debug(hdl, "STHYI@LPAR succeeded\n"); ++ qc_debug(hdl, "STHYI syscall succeeded\n"); + priv->avail = STHYI_AVAILABLE; + #endif + +@@ -281,25 +281,15 @@ static int qc_parse_sthyi_guest(struct qc_handle *gst, struct inf0gst *guest) { + return 0; + } + +-static int qc_get_num_vm_layers(struct qc_handle *hdl, int *rc) { +- int i; +- +- for (hdl = hdl->root, i = 0; hdl != NULL; hdl = hdl->next) { +- if (*(int *)(hdl->layer) == QC_LAYER_TYPE_ZVM_HYPERVISOR) +- i++; +- } +- +- return i; +-} +- + /* Returns pointer to the n-th hypervisor handle. num starts at 0, and handles + are returned in sequence from handle linked list */ + static struct qc_handle *qc_get_HV_layer(struct qc_handle *hdl, int num) { + struct qc_handle *h = hdl; +- int i; ++ int i, type; + + for (hdl = hdl->root, i = 0, num++; hdl != NULL; hdl = hdl->next) { +- if (*(int *)(hdl->layer) == QC_LAYER_TYPE_ZVM_HYPERVISOR && ++i == num) ++ type = *(int *)(hdl->layer); ++ if ((type == QC_LAYER_TYPE_ZVM_HYPERVISOR || type == QC_LAYER_TYPE_KVM_HYPERVISOR) && ++i == num) + return hdl; + } + qc_debug(h, "Error: Couldn't find HV layer %d, only %d layer(s) found\n", num, i); +@@ -309,7 +299,7 @@ static struct qc_handle *qc_get_HV_layer(struct qc_handle *hdl, int num) { + + static int qc_sthyi_process(struct qc_handle *hdl, char *buf) { + struct sthyi_priv *priv = (struct sthyi_priv *)buf; +- int no_hyp_gst, num_vm_layers, i, rc = 0; ++ int no_hyp_gst, i, rc = 0; + struct inf0gst *guest[INF0YGMX]; + struct inf0hyp *hv[INF0YGMX]; + struct inf0par *partition; +@@ -371,30 +361,14 @@ static int qc_sthyi_process(struct qc_handle *hdl, char *buf) { + goto out; + } + +- num_vm_layers = qc_get_num_vm_layers(hdl, &rc); +- if (rc != 0) { +- rc = -2; +- goto out; +- } +- +- if (num_vm_layers != no_hyp_gst) { +- /* STHYI doesn't support more than 3rd level z/VM */ +- qc_debug(hdl, "Error: /proc/sysinfo reported %d layers, but STHYI only " +- "covers %d\n", num_vm_layers, no_hyp_gst); +- rc = -6; +- goto out; +- } +- + for (i = 0; i < no_hyp_gst; i++) { + if ((hdl = qc_get_HV_layer(hdl, i)) == NULL) { + rc = -7; + goto out; + } +- if (*(int *)(hdl->layer) == QC_LAYER_TYPE_ZVM_HYPERVISOR) { +- if (qc_parse_sthyi_hypervisor(hdl, hv[i]) || qc_parse_sthyi_guest(hdl->next, guest[i])) { +- rc = -9; +- goto out; +- } ++ if (qc_parse_sthyi_hypervisor(hdl, hv[i]) || qc_parse_sthyi_guest(hdl->next, guest[i])) { ++ rc = -9; ++ goto out; + } + } + out: +@@ -508,15 +482,15 @@ static int qc_sthyi_open(struct qc_handle *hdl, char **buf) { + /* There is no way for us to check programmatically whether + we're in an LPAR or in a VM, so we simply try out both */ + if (qc_is_sthyi_available_vm(hdl)) { +- qc_debug(hdl, "Executing STHYI@VM\n"); ++ qc_debug(hdl, "Executing STHYI instruction\n"); + /* we assume we are not relocated at this spot, between STFLE and STHYI */ + if (qc_sthyi_vm(priv)) { +- qc_debug(hdl, "Error: STHYI@VM execution failed\n"); ++ qc_debug(hdl, "Error: STHYI instruction execution failed\n"); + rc = -3; + goto out; + } + } else { +- qc_debug(hdl, "STHYI@VM is not available\n"); ++ qc_debug(hdl, "STHYI instruction is not available\n"); + rc = qc_sthyi_lpar(hdl, priv); + } + } diff --git a/qclib.changes b/qclib.changes index 38a1d2b..2b37ba8 100644 --- a/qclib.changes +++ b/qclib.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Dec 8 22:07:04 UTC 2017 - mpost@suse.com + +- Added qclib-sles15-fix-mismatch-case-with-STHYI.patch (bsc#1071687). + ------------------------------------------------------------------- Thu Nov 2 20:03:27 UTC 2017 - mpost@suse.com diff --git a/qclib.spec b/qclib.spec index 66f17d8..4a4e177 100644 --- a/qclib.spec +++ b/qclib.spec @@ -26,6 +26,7 @@ Url: http://www.ibm.com/developerworks/linux/linux390/qclib.html Source: %{name}-%{version}.tgz Source1: %{name}-rpmlintrc Patch1: qclib.makefile.libdir.patch +Patch2: qclib-sles15-fix-mismatch-case-with-STHYI.patch BuildRequires: doxygen BuildRequires: gcc-c++ BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -96,6 +97,7 @@ Systems. %prep %setup -q %patch1 -p1 +%patch2 -p1 %build MYCFLAGS=$(grep ^CFLAGS Makefile | cut -f2 -d=)