public inbox for linux-s390@vger.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests
@ 2023-04-21 11:36 Janosch Frank
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function Janosch Frank
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

Extend the coverage of the UVC interface.
The patches might be a bit dusty, they've been on a branch for a while.

v3:
	- Reworked a large portion of the tests
	- Introduced a new function that checks for required
          facilities and memory for tests that start PV guests
	- Shortened snippet file names
	- Moved checks from report to asserts to decrease test noise
	- Introduced diag PV intercept data check function

v2:
	- Re-worked the cpu timer tests
	- Testing both pages for 112 intercept
	- Added skip on insufficient memory
	- Fixed comments in pv-ipl.c

Janosch Frank (7):
  lib: s390x: uv: Introduce UV validity function
  lib: s390x: uv: Add intercept data check library function
  s390x: pv-diags: Drop snippet from snippet names
  lib: s390x: uv: Add pv guest requirement check function
  s390x: pv: Add sie entry intercept and validity test
  s390x: pv: Add IPL reset tests
  s390x: pv-diags: Add the test to unittests.conf

 lib/s390x/pv_icptdata.h                       |  42 ++
 lib/s390x/snippet.h                           |   7 +
 lib/s390x/uv.c                                |  20 +
 lib/s390x/uv.h                                |   8 +
 s390x/Makefile                                |  13 +-
 s390x/pv-diags.c                              |  70 ++--
 s390x/pv-icptcode.c                           | 370 ++++++++++++++++++
 s390x/pv-ipl.c                                | 145 +++++++
 s390x/snippets/asm/icpt-loop.S                |  15 +
 s390x/snippets/asm/loop.S                     |  13 +
 .../{snippet-pv-diag-288.S => pv-diag-288.S}  |   0
 .../{snippet-pv-diag-500.S => pv-diag-500.S}  |   0
 ...nippet-pv-diag-yield.S => pv-diag-yield.S} |   0
 s390x/snippets/asm/pv-icpt-vir-timing.S       |  22 ++
 s390x/unittests.cfg                           |  13 +
 15 files changed, 696 insertions(+), 42 deletions(-)
 create mode 100644 lib/s390x/pv_icptdata.h
 create mode 100644 s390x/pv-icptcode.c
 create mode 100644 s390x/pv-ipl.c
 create mode 100644 s390x/snippets/asm/icpt-loop.S
 create mode 100644 s390x/snippets/asm/loop.S
 rename s390x/snippets/asm/{snippet-pv-diag-288.S => pv-diag-288.S} (100%)
 rename s390x/snippets/asm/{snippet-pv-diag-500.S => pv-diag-500.S} (100%)
 rename s390x/snippets/asm/{snippet-pv-diag-yield.S => pv-diag-yield.S} (100%)
 create mode 100644 s390x/snippets/asm/pv-icpt-vir-timing.S

-- 
2.34.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-05-31 13:36   ` Nico Boehr
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function Janosch Frank
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

PV related validities are in the 0x20** range but the last byte might
be implementation specific, so everytime we check for a UV validity we
need to mask the last byte.

Let's add a function that checks for a UV validity and returns a
boolean.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
---
 lib/s390x/uv.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lib/s390x/uv.h b/lib/s390x/uv.h
index 5fe29bda..78b979b7 100644
--- a/lib/s390x/uv.h
+++ b/lib/s390x/uv.h
@@ -35,4 +35,11 @@ static inline void uv_setup_asces(void)
 	lctlg(13, asce);
 }
 
+static inline bool uv_validity_check(struct vm *vm)
+{
+	uint16_t vir = sie_get_validity(vm);
+
+	return vm->sblk->icptcode == ICPT_VALIDITY && (vir & 0xff00) == 0x2000;
+}
+
 #endif /* UV_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-04-21 14:10   ` Claudio Imbrenda
  2023-04-26 11:22   ` Nico Boehr
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

When working with guests it's essential to check the SIE intercept
data for the correct values. Fortunately on PV guests these values are
constants so we can create check functions which test for the
constants.

While we're at it let's make pv-diags.c use this new function.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 lib/s390x/pv_icptdata.h | 42 +++++++++++++++++++++++++++++++++++++++++
 s390x/pv-diags.c        | 14 ++++++--------
 2 files changed, 48 insertions(+), 8 deletions(-)
 create mode 100644 lib/s390x/pv_icptdata.h

diff --git a/lib/s390x/pv_icptdata.h b/lib/s390x/pv_icptdata.h
new file mode 100644
index 00000000..4746117e
--- /dev/null
+++ b/lib/s390x/pv_icptdata.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Commonly used checks for PV SIE intercept data
+ *
+ * Copyright IBM Corp. 2023
+ * Author: Janosch Frank <frankja@linux.ibm.com>
+ */
+
+#ifndef _S390X_PV_ICPTDATA_H_
+#define _S390X_PV_ICPTDATA_H_
+
+#include <sie.h>
+
+/*
+ * Checks the diagnose instruction intercept data for consistency with
+ * the constants defined by the PV SIE architecture
+ *
+ * Supports: 0x44, 0x9c, 0x288, 0x308, 0x500
+ */
+static bool pv_icptdata_check_diag(struct vm *vm, int diag)
+{
+	int icptcode;
+
+	switch (diag) {
+	case 0x44:
+	case 0x9c:
+	case 0x288:
+	case 0x308:
+		icptcode = ICPT_PV_NOTIFY;
+		break;
+	case 0x500:
+		icptcode = ICPT_PV_INSTR;
+		break;
+	default:
+		/* If a new diag is introduced add it to the cases above! */
+		assert(0);
+	}
+
+	return vm->sblk->icptcode == icptcode && vm->sblk->ipa == 0x8302 &&
+	       vm->sblk->ipb == 0x50000000 && vm->save_area.guest.grs[5] == diag;
+}
+#endif
diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c
index 5165937a..096ac61f 100644
--- a/s390x/pv-diags.c
+++ b/s390x/pv-diags.c
@@ -9,6 +9,7 @@
  */
 #include <libcflat.h>
 #include <snippet.h>
+#include <pv_icptdata.h>
 #include <sie.h>
 #include <sclp.h>
 #include <asm/facility.h>
@@ -31,8 +32,7 @@ static void test_diag_500(void)
 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
 
 	sie(&vm);
-	report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 &&
-	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x500,
+	report(pv_icptdata_check_diag(&vm, 0x500),
 	       "intercept values");
 	report(vm.save_area.guest.grs[1] == 1 &&
 	       vm.save_area.guest.grs[2] == 2 &&
@@ -45,9 +45,8 @@ static void test_diag_500(void)
 	 */
 	vm.sblk->iictl = IICTL_CODE_OPERAND;
 	sie(&vm);
-	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
-	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
-	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND,
+	report(pv_icptdata_check_diag(&vm, 0x9c) &&
+	       vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND,
 	       "operand exception");
 
 	/*
@@ -58,9 +57,8 @@ static void test_diag_500(void)
 	vm.sblk->iictl = IICTL_CODE_SPECIFICATION;
 	/* Inject PGM, next exit should be 9c */
 	sie(&vm);
-	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
-	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
-	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
+	report(pv_icptdata_check_diag(&vm, 0x9c) &&
+	       vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
 	       "specification exception");
 
 	/* No need for cleanup, just tear down the VM */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function Janosch Frank
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-04-21 14:10   ` Claudio Imbrenda
  2023-04-26 11:24   ` Nico Boehr
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function Janosch Frank
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

It's a bit redundant.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 s390x/Makefile                                |  6 +--
 s390x/pv-diags.c                              | 48 +++++++++----------
 .../{snippet-pv-diag-288.S => pv-diag-288.S}  |  0
 .../{snippet-pv-diag-500.S => pv-diag-500.S}  |  0
 ...nippet-pv-diag-yield.S => pv-diag-yield.S} |  0
 5 files changed, 27 insertions(+), 27 deletions(-)
 rename s390x/snippets/asm/{snippet-pv-diag-288.S => pv-diag-288.S} (100%)
 rename s390x/snippets/asm/{snippet-pv-diag-500.S => pv-diag-500.S} (100%)
 rename s390x/snippets/asm/{snippet-pv-diag-yield.S => pv-diag-yield.S} (100%)

diff --git a/s390x/Makefile b/s390x/Makefile
index a80db538..8d1cfc7c 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -122,9 +122,9 @@ snippet_lib = $(snippet_asmlib) lib/auxinfo.o
 $(TEST_DIR)/mvpg-sie.elf: snippets = $(SNIPPET_DIR)/c/mvpg-snippet.gbin
 $(TEST_DIR)/spec_ex-sie.elf: snippets = $(SNIPPET_DIR)/c/spec_ex.gbin
 
-$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/snippet-pv-diag-yield.gbin
-$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/snippet-pv-diag-288.gbin
-$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/snippet-pv-diag-500.gbin
+$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-yield.gbin
+$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-288.gbin
+$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-500.gbin
 
 ifneq ($(GEN_SE_HEADER),)
 snippets += $(pv-snippets)
diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c
index 096ac61f..fa4e5532 100644
--- a/s390x/pv-diags.c
+++ b/s390x/pv-diags.c
@@ -18,17 +18,17 @@ static struct vm vm;
 
 static void test_diag_500(void)
 {
-	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_500)[];
-	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_500)[];
-	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_500)[];
-	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_500)[];
-	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_500);
-	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_500);
+	extern const char SNIPPET_NAME_START(asm, pv_diag_500)[];
+	extern const char SNIPPET_NAME_END(asm, pv_diag_500)[];
+	extern const char SNIPPET_HDR_START(asm, pv_diag_500)[];
+	extern const char SNIPPET_HDR_END(asm, pv_diag_500)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_500);
+	int size_gbin = SNIPPET_LEN(asm, pv_diag_500);
 
 	report_prefix_push("diag 0x500");
 
-	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_500),
-			SNIPPET_HDR_START(asm, snippet_pv_diag_500),
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_500),
+			SNIPPET_HDR_START(asm, pv_diag_500),
 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
 
 	sie(&vm);
@@ -70,17 +70,17 @@ static void test_diag_500(void)
 
 static void test_diag_288(void)
 {
-	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_288)[];
-	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_288)[];
-	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_288)[];
-	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_288)[];
-	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_288);
-	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_288);
+	extern const char SNIPPET_NAME_START(asm, pv_diag_288)[];
+	extern const char SNIPPET_NAME_END(asm, pv_diag_288)[];
+	extern const char SNIPPET_HDR_START(asm, pv_diag_288)[];
+	extern const char SNIPPET_HDR_END(asm, pv_diag_288)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_288);
+	int size_gbin = SNIPPET_LEN(asm, pv_diag_288);
 
 	report_prefix_push("diag 0x288");
 
-	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_288),
-			SNIPPET_HDR_START(asm, snippet_pv_diag_288),
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_288),
+			SNIPPET_HDR_START(asm, pv_diag_288),
 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
 
 	sie(&vm);
@@ -111,17 +111,17 @@ static void test_diag_288(void)
 
 static void test_diag_yield(void)
 {
-	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_yield)[];
-	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_yield)[];
-	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_yield)[];
-	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_yield)[];
-	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_yield);
-	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_yield);
+	extern const char SNIPPET_NAME_START(asm, pv_diag_yield)[];
+	extern const char SNIPPET_NAME_END(asm, pv_diag_yield)[];
+	extern const char SNIPPET_HDR_START(asm, pv_diag_yield)[];
+	extern const char SNIPPET_HDR_END(asm, pv_diag_yield)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_yield);
+	int size_gbin = SNIPPET_LEN(asm, pv_diag_yield);
 
 	report_prefix_push("diag yield");
 
-	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_yield),
-			SNIPPET_HDR_START(asm, snippet_pv_diag_yield),
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_yield),
+			SNIPPET_HDR_START(asm, pv_diag_yield),
 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
 
 	/* 0x44 */
diff --git a/s390x/snippets/asm/snippet-pv-diag-288.S b/s390x/snippets/asm/pv-diag-288.S
similarity index 100%
rename from s390x/snippets/asm/snippet-pv-diag-288.S
rename to s390x/snippets/asm/pv-diag-288.S
diff --git a/s390x/snippets/asm/snippet-pv-diag-500.S b/s390x/snippets/asm/pv-diag-500.S
similarity index 100%
rename from s390x/snippets/asm/snippet-pv-diag-500.S
rename to s390x/snippets/asm/pv-diag-500.S
diff --git a/s390x/snippets/asm/snippet-pv-diag-yield.S b/s390x/snippets/asm/pv-diag-yield.S
similarity index 100%
rename from s390x/snippets/asm/snippet-pv-diag-yield.S
rename to s390x/snippets/asm/pv-diag-yield.S
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (2 preceding siblings ...)
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-04-21 14:13   ` Claudio Imbrenda
  2023-04-26 11:27   ` Nico Boehr
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 5/7] s390x: pv: Add sie entry intercept and validity test Janosch Frank
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

When running PV guests some of the UV memory needs to be allocated
with > 31 bit addresses which means tests with PV guests will always
need a lot more memory than other tests.
Additionally facilities nr 158 and sclp.sief2 need to be available.

Let's add a function that checks for these requirements and prints a
helpful skip message.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 lib/s390x/snippet.h |  7 +++++++
 lib/s390x/uv.c      | 20 ++++++++++++++++++++
 lib/s390x/uv.h      |  1 +
 s390x/pv-diags.c    |  8 +-------
 4 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/lib/s390x/snippet.h b/lib/s390x/snippet.h
index 57045994..11ec54c3 100644
--- a/lib/s390x/snippet.h
+++ b/lib/s390x/snippet.h
@@ -30,6 +30,13 @@
 #define SNIPPET_HDR_LEN(type, file) \
 	((uintptr_t)SNIPPET_HDR_END(type, file) - (uintptr_t)SNIPPET_HDR_START(type, file))
 
+/*
+ * Some of the UV memory needs to be allocated with >31 bit
+ * addresses which means we need a lot more memory than other
+ * tests.
+ */
+#define SNIPPET_PV_MIN_MEM_SIZE	(SZ_1M * 2200UL)
+
 #define SNIPPET_PV_TWEAK0	0x42UL
 #define SNIPPET_PV_TWEAK1	0UL
 #define SNIPPET_UNPACK_OFF	0
diff --git a/lib/s390x/uv.c b/lib/s390x/uv.c
index 383271a5..db47536c 100644
--- a/lib/s390x/uv.c
+++ b/lib/s390x/uv.c
@@ -18,6 +18,7 @@
 #include <asm/uv.h>
 #include <uv.h>
 #include <sie.h>
+#include <snippet.h>
 
 static struct uv_cb_qui uvcb_qui = {
 	.header.cmd = UVC_CMD_QUI,
@@ -38,6 +39,25 @@ bool uv_os_is_host(void)
 	return test_facility(158) && uv_query_test_call(BIT_UVC_CMD_INIT_UV);
 }
 
+bool uv_guest_requirement_checks(void)
+{
+	if (!test_facility(158)) {
+		report_skip("UV Call facility unavailable");
+		return false;
+	}
+	if (!sclp_facilities.has_sief2) {
+		report_skip("SIEF2 facility unavailable");
+		return false;
+	}
+	if (get_ram_size() < SNIPPET_PV_MIN_MEM_SIZE) {
+		report_skip("Not enough memory. This test needs about %ld MB of memory",
+			    SNIPPET_PV_MIN_MEM_SIZE / 1024 / 1024);
+		return false;
+	}
+
+	return true;
+}
+
 bool uv_query_test_call(unsigned int nr)
 {
 	/* Query needs to be called first */
diff --git a/lib/s390x/uv.h b/lib/s390x/uv.h
index 78b979b7..d9af691a 100644
--- a/lib/s390x/uv.h
+++ b/lib/s390x/uv.h
@@ -7,6 +7,7 @@
 
 bool uv_os_is_guest(void);
 bool uv_os_is_host(void);
+bool uv_guest_requirement_checks(void);
 bool uv_query_test_call(unsigned int nr);
 const struct uv_cb_qui *uv_get_query_data(void);
 void uv_init(void);
diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c
index fa4e5532..1289a571 100644
--- a/s390x/pv-diags.c
+++ b/s390x/pv-diags.c
@@ -149,14 +149,8 @@ static void test_diag_yield(void)
 int main(void)
 {
 	report_prefix_push("pv-diags");
-	if (!test_facility(158)) {
-		report_skip("UV Call facility unavailable");
+	if (!uv_guest_requirement_checks())
 		goto done;
-	}
-	if (!sclp_facilities.has_sief2) {
-		report_skip("SIEF2 facility unavailable");
-		goto done;
-	}
 
 	uv_setup_asces();
 	snippet_setup_guest(&vm, true);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 5/7] s390x: pv: Add sie entry intercept and validity test
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (3 preceding siblings ...)
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-04-21 15:23   ` Claudio Imbrenda
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 6/7] s390x: pv: Add IPL reset tests Janosch Frank
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 7/7] s390x: pv-diags: Add the test to unittests.conf Janosch Frank
  6 siblings, 1 reply; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

The lowcore is an important part of any s390 cpu so we need to make
sure it's always available when we virtualize one. For non-PV guests
that would mean ensuring that the lowcore page is read and writable by
the guest.

For PV guests we additionally need to make sure that the page is owned
by the guest as it is only allowed to access them if that's the
case. The code 112 SIE intercept tells us if the lowcore pages aren't
secure anymore.

Let's check if that intercept is reported by SIE if we export the
lowcore pages. Additionally check if that's also the case if the guest
shares the lowcore which will make it readable to the host but
ownership of the page should not change.

Also we check for validities in these conditions:
     * Manipulated cpu timer
     * Double SIE for same vcpu
     * Re-use of VCPU handle from another secure configuration
     * ASCE re-use

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 s390x/Makefile                          |   5 +
 s390x/pv-icptcode.c                     | 370 ++++++++++++++++++++++++
 s390x/snippets/asm/icpt-loop.S          |  15 +
 s390x/snippets/asm/loop.S               |  13 +
 s390x/snippets/asm/pv-icpt-vir-timing.S |  22 ++
 s390x/unittests.cfg                     |   5 +
 6 files changed, 430 insertions(+)
 create mode 100644 s390x/pv-icptcode.c
 create mode 100644 s390x/snippets/asm/icpt-loop.S
 create mode 100644 s390x/snippets/asm/loop.S
 create mode 100644 s390x/snippets/asm/pv-icpt-vir-timing.S

diff --git a/s390x/Makefile b/s390x/Makefile
index 8d1cfc7c..67be5360 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -42,6 +42,7 @@ tests += $(TEST_DIR)/exittime.elf
 tests += $(TEST_DIR)/ex.elf
 
 pv-tests += $(TEST_DIR)/pv-diags.elf
+pv-tests += $(TEST_DIR)/pv-icptcode.elf
 
 ifneq ($(HOST_KEY_DOCUMENT),)
 ifneq ($(GEN_SE_HEADER),)
@@ -125,6 +126,10 @@ $(TEST_DIR)/spec_ex-sie.elf: snippets = $(SNIPPET_DIR)/c/spec_ex.gbin
 $(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-yield.gbin
 $(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-288.gbin
 $(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-500.gbin
+$(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-icpt-112.gbin
+$(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/icpt-loop.gbin
+$(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/loop.gbin
+$(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-icpt-vir-timing.gbin
 
 ifneq ($(GEN_SE_HEADER),)
 snippets += $(pv-snippets)
diff --git a/s390x/pv-icptcode.c b/s390x/pv-icptcode.c
new file mode 100644
index 00000000..38a8053a
--- /dev/null
+++ b/s390x/pv-icptcode.c
@@ -0,0 +1,370 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * PV virtualization interception tests for intercepts that are not
+ * caused by an instruction.
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+#include <libcflat.h>
+#include <sie.h>
+#include <smp.h>
+#include <sclp.h>
+#include <snippet.h>
+#include <pv_icptdata.h>
+#include <asm/facility.h>
+#include <asm/barrier.h>
+#include <asm/sigp.h>
+#include <asm/uv.h>
+#include <asm/time.h>
+
+static struct vm vm, vm2;
+
+/*
+ * The hypervisor should not be able to decrease the cpu timer by an
+ * amount that is higher than the amount of time spent outside of
+ * SIE.
+ *
+ * Warning: A lot of things influence time so decreasing the timer by
+ * a more significant amount than the difference to have a safety
+ * margin is advised.
+ */
+static void test_validity_timing(void)
+{
+	extern const char SNIPPET_NAME_START(asm, pv_icpt_vir_timing)[];
+	extern const char SNIPPET_NAME_END(asm, pv_icpt_vir_timing)[];
+	extern const char SNIPPET_HDR_START(asm, pv_icpt_vir_timing)[];
+	extern const char SNIPPET_HDR_END(asm, pv_icpt_vir_timing)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_icpt_vir_timing);
+	int size_gbin = SNIPPET_LEN(asm, pv_icpt_vir_timing);
+	uint64_t time_exit, time_entry;
+
+	report_prefix_push("manipulated cpu time");
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_icpt_vir_timing),
+			SNIPPET_HDR_START(asm, pv_icpt_vir_timing),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	sie(&vm);
+	report(pv_icptdata_check_diag(&vm, 0x44), "stp done");
+	stck(&time_exit);
+	mb();
+
+	/* Cpu timer counts down so adding a ms should lead to a validity */
+	vm.sblk->cputm += S390_CLOCK_SHIFT_US * 1000;
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity entry cput > exit cput");
+	vm.sblk->cputm -= S390_CLOCK_SHIFT_US;
+
+	/*
+	 * We are not allowed to decrement the timer more than the
+	 * time spent outside of SIE
+	 */
+	stck(&time_entry);
+	vm.sblk->cputm -= (time_entry - time_exit) + S390_CLOCK_SHIFT_US * 1000;
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity entry cput < time spent outside SIE");
+
+	uv_destroy_guest(&vm);
+	report_prefix_pop();
+}
+
+static void run_loop(void)
+{
+	sie(&vm);
+	sigp_retry(stap(), SIGP_STOP, 0, NULL);
+}
+
+static void test_validity_already_running(void)
+{
+	extern const char SNIPPET_NAME_START(asm, loop)[];
+	extern const char SNIPPET_NAME_END(asm, loop)[];
+	extern const char SNIPPET_HDR_START(asm, loop)[];
+	extern const char SNIPPET_HDR_END(asm, loop)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, loop);
+	int size_gbin = SNIPPET_LEN(asm, loop);
+	struct psw psw = {
+		.mask = PSW_MASK_64,
+		.addr = (uint64_t)run_loop,
+	};
+
+	report_prefix_push("already running");
+	if (smp_query_num_cpus() < 3) {
+		report_skip("need at least 3 cpus for this test");
+		goto out;
+	}
+
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, loop),
+			SNIPPET_HDR_START(asm, loop),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	sie_expect_validity(&vm);
+	smp_cpu_setup(1, psw);
+	smp_cpu_setup(2, psw);
+	while (vm.sblk->icptcode != ICPT_VALIDITY) {
+		mb();
+	}
+
+	/*
+	 * One cpu will enter SIE and one will receive the validity.
+	 * We rely on the expectation that the cpu in SIE won't exit
+	 * until we had a chance to observe the validity as the exit
+	 * would overwrite the validity.
+	 *
+	 * In general that expectation is valid but HW/FW can in
+	 * theory still exit to handle their interrupts.
+	 */
+	report(uv_validity_check(&vm), "validity");
+	smp_cpu_stop(1);
+	smp_cpu_stop(2);
+	uv_destroy_guest(&vm);
+
+out:
+	report_prefix_pop();
+}
+
+/* Tests if a vcpu handle from another configuration results in a validity intercept. */
+static void test_validity_handle_not_in_config(void)
+{
+	extern const char SNIPPET_NAME_START(asm, icpt_loop)[];
+	extern const char SNIPPET_NAME_END(asm, icpt_loop)[];
+	extern const char SNIPPET_HDR_START(asm, icpt_loop)[];
+	extern const char SNIPPET_HDR_END(asm, icpt_loop)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, icpt_loop);
+	int size_gbin = SNIPPET_LEN(asm, icpt_loop);
+
+	report_prefix_push("handle not in config");
+	/* Setup our primary vm */
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, icpt_loop),
+			SNIPPET_HDR_START(asm, icpt_loop),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	/* Setup secondary vm */
+	snippet_setup_guest(&vm2, true);
+	snippet_pv_init(&vm2, SNIPPET_NAME_START(asm, icpt_loop),
+			SNIPPET_HDR_START(asm, icpt_loop),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	vm.sblk->pv_handle_cpu = vm2.sblk->pv_handle_cpu;
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity");
+
+	/* Restore cpu handle and destroy the second vm */
+	vm.sblk->pv_handle_cpu = vm.uv.vcpu_handle;
+	uv_destroy_guest(&vm2);
+	sie_guest_destroy(&vm2);
+
+	uv_destroy_guest(&vm);
+	report_prefix_pop();
+}
+
+/* Tests if a wrong vm or vcpu handle results in a validity intercept. */
+static void test_validity_seid(void)
+{
+	extern const char SNIPPET_NAME_START(asm, icpt_loop)[];
+	extern const char SNIPPET_NAME_END(asm, icpt_loop)[];
+	extern const char SNIPPET_HDR_START(asm, icpt_loop)[];
+	extern const char SNIPPET_HDR_END(asm, icpt_loop)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, icpt_loop);
+	int size_gbin = SNIPPET_LEN(asm, icpt_loop);
+	int fails = 0;
+	int i;
+
+	report_prefix_push("handles");
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, icpt_loop),
+			SNIPPET_HDR_START(asm, icpt_loop),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	for (i = 0; i < 64; i++) {
+		vm.sblk->pv_handle_config ^= 1UL << i;
+		sie_expect_validity(&vm);
+		sie(&vm);
+		if (!uv_validity_check(&vm)) {
+			report_fail("SIE accepted wrong VM SEID, changed bit %d",
+				    63 - i);
+			fails++;
+		}
+		vm.sblk->pv_handle_config ^= 1UL << i;
+	}
+	report(!fails, "No wrong vm handle accepted");
+
+	fails = 0;
+	for (i = 0; i < 64; i++) {
+		vm.sblk->pv_handle_cpu ^= 1UL << i;
+		sie_expect_validity(&vm);
+		sie(&vm);
+		if (!uv_validity_check(&vm)) {
+			report_fail("SIE accepted wrong CPU SEID, changed bit %d",
+				    63 - i);
+			fails++;
+		}
+		vm.sblk->pv_handle_cpu ^= 1UL << i;
+	}
+	report(!fails, "No wrong cpu handle accepted");
+
+	uv_destroy_guest(&vm);
+	report_prefix_pop();
+}
+
+/*
+ * Tests if we get a validity intercept if the CR1 asce at SIE entry
+ * is not the same as the one given at the UV creation of the VM.
+ */
+static void test_validity_asce(void)
+{
+	extern const char SNIPPET_NAME_START(asm, pv_icpt_112)[];
+	extern const char SNIPPET_NAME_END(asm, pv_icpt_112)[];
+	extern const char SNIPPET_HDR_START(asm, pv_icpt_112)[];
+	extern const char SNIPPET_HDR_END(asm, pv_icpt_112)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_icpt_112);
+	int size_gbin = SNIPPET_LEN(asm, pv_icpt_112);
+	uint64_t asce_old, asce_new;
+	void *pgd_new, *pgd_old;
+
+	report_prefix_push("asce");
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_icpt_112),
+			SNIPPET_HDR_START(asm, pv_icpt_112),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	asce_old = vm.save_area.guest.asce;
+	pgd_new = memalign_pages_flags(PAGE_SIZE, PAGE_SIZE * 4, 0);
+	pgd_old = (void *)(asce_old & PAGE_MASK);
+
+	/* Copy the contents of the top most table */
+	memcpy(pgd_new, pgd_old, PAGE_SIZE * 4);
+
+	/* Create the replacement ASCE */
+	asce_new = __pa(pgd_new) | ASCE_DT_REGION1 | REGION_TABLE_LENGTH | ASCE_P;
+	vm.save_area.guest.asce = asce_new;
+
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "wrong CR1 validity");
+
+	/* Restore the old ASCE */
+	vm.save_area.guest.asce = asce_old;
+
+	/* Try if we can still do an entry with the correct asce */
+	sie(&vm);
+	report(pv_icptdata_check_diag(&vm, 0x44), "re-entry with valid CR1");
+	uv_destroy_guest(&vm);
+	free_pages(pgd_new);
+	report_prefix_pop();
+}
+
+static void run_icpt_122_tests(unsigned long lc_off)
+{
+	uv_export(vm.sblk->mso + lc_off);
+	sie(&vm);
+	report(vm.sblk->icptcode == ICPT_PV_PREF, "Intercept 112 for page 0");
+	uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off);
+
+	uv_export(vm.sblk->mso + lc_off + PAGE_SIZE);
+	report(vm.sblk->icptcode == ICPT_PV_PREF, "Intercept 112 for page 1");
+	uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off + PAGE_SIZE);
+}
+
+static void run_icpt_122_tests_prefix(unsigned long prefix)
+{
+	char prfxstr[7];
+	uint32_t *ptr = 0;
+
+	snprintf(prfxstr, sizeof(prfxstr), "0x%lx", prefix);
+
+	report_prefix_push(prfxstr);
+	report_prefix_push("unshared");
+	run_icpt_122_tests(prefix);
+	report_prefix_pop();
+
+	/*
+	 * Guest will share the lowcore and we need to check if that
+	 * makes a difference (which it should not).
+	 */
+	report_prefix_push("shared");
+
+	sie(&vm);
+	/* Guest indicates that it has been setup via the diag 0x44 */
+	assert(pv_icptdata_check_diag(&vm, 0x44));
+	/* If the pages have not been shared these writes will cause exceptions */
+	ptr = (uint32_t *)prefix;
+	WRITE_ONCE(ptr, 0);
+	ptr = (uint32_t *)(prefix + offsetof(struct lowcore, ars_sa[0]));
+	WRITE_ONCE(ptr, 0);
+
+	run_icpt_122_tests(prefix);
+
+	/* shared*/
+	report_prefix_pop();
+	/* prefix hex value */
+	report_prefix_pop();
+}
+
+static void test_icpt_112(void)
+{
+	extern const char SNIPPET_NAME_START(asm, pv_icpt_112)[];
+	extern const char SNIPPET_NAME_END(asm, pv_icpt_112)[];
+	extern const char SNIPPET_HDR_START(asm, pv_icpt_112)[];
+	extern const char SNIPPET_HDR_END(asm, pv_icpt_112)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_icpt_112);
+	int size_gbin = SNIPPET_LEN(asm, pv_icpt_112);
+
+	unsigned long lc_off = 0;
+
+	report_prefix_push("prefix");
+
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_icpt_112),
+			SNIPPET_HDR_START(asm, pv_icpt_112),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	/* Setup of the guest's state for 0x0 prefix */
+	sie(&vm);
+	assert(pv_icptdata_check_diag(&vm, 0x44));
+
+	/* Test on standard 0x0 prefix */
+	run_icpt_122_tests_prefix(0);
+
+	/* Setup of the guest's state for 0x8000 prefix */
+	lc_off = 0x8000;
+	uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off);
+	uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off + PAGE_SIZE);
+	/* Guest will set prefix to 0x8000 */
+	sie(&vm);
+	/* SPX generates a PV instruction notification */
+	assert(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0xb210);
+	assert(*(u32 *)vm.sblk->sidad == 0x8000);
+
+	/* Test on 0x8000 prefix */
+	run_icpt_122_tests_prefix(0x8000);
+
+	/* Try a re-entry after everything has been imported again */
+	sie(&vm);
+	report(pv_icptdata_check_diag(&vm, 0x9c) &&
+	       vm.save_area.guest.grs[0] == 42,
+	       "re-entry successful");
+	report_prefix_pop();
+	uv_destroy_guest(&vm);
+}
+
+int main(void)
+{
+	report_prefix_push("pv-icpts");
+	if (!uv_guest_requirement_checks())
+		goto done;
+
+	snippet_setup_guest(&vm, true);
+	test_icpt_112();
+	test_validity_asce();
+	test_validity_seid();
+	test_validity_handle_not_in_config();
+	test_validity_already_running();
+	test_validity_timing();
+	sie_guest_destroy(&vm);
+
+done:
+	report_prefix_pop();
+	return report_summary();
+}
diff --git a/s390x/snippets/asm/icpt-loop.S b/s390x/snippets/asm/icpt-loop.S
new file mode 100644
index 00000000..2aa59c01
--- /dev/null
+++ b/s390x/snippets/asm/icpt-loop.S
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Infinite loop snippet which can be used to test manipulated SIE
+ * control block intercepts. E.g. when manipulating the PV handles.
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+.section .text
+xgr	%r0, %r0
+retry:
+diag	0,0,0x44
+j 	retry
diff --git a/s390x/snippets/asm/loop.S b/s390x/snippets/asm/loop.S
new file mode 100644
index 00000000..a75bf00d
--- /dev/null
+++ b/s390x/snippets/asm/loop.S
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Infinite loop snippet with no exit
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+.section .text
+
+retry:
+j 	retry
diff --git a/s390x/snippets/asm/pv-icpt-vir-timing.S b/s390x/snippets/asm/pv-icpt-vir-timing.S
new file mode 100644
index 00000000..b35f02c9
--- /dev/null
+++ b/s390x/snippets/asm/pv-icpt-vir-timing.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Sets a cpu timer which the host can manipulate to check if it will
+ * receive a validity
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+.section .text
+larl	%r1, time_val
+spt	0 (%r1)
+diag    0, 0, 0x44
+xgr	%r1, %r1
+lghi	%r1, 42
+diag	1, 0, 0x9c
+
+
+.align 8
+time_val:
+	.quad 0x280de80000
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index b61faf07..e2d3478e 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -218,3 +218,8 @@ extra_params = -append '--parallel'
 
 [execute]
 file = ex.elf
+
+[pv-icptcode]
+file = pv-icptcode.elf
+smp = 3
+extra_params = -m 2200
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 6/7] s390x: pv: Add IPL reset tests
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (4 preceding siblings ...)
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 5/7] s390x: pv: Add sie entry intercept and validity test Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-04-21 15:32   ` Claudio Imbrenda
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 7/7] s390x: pv-diags: Add the test to unittests.conf Janosch Frank
  6 siblings, 1 reply; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

The diag308 requires extensive cooperation between the hypervisor and
the Ultravisor so the Ultravisor can make sure all necessary reset
steps have been done.

Let's check if we get the correct validity errors.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 s390x/Makefile      |   2 +
 s390x/pv-ipl.c      | 145 ++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg |   4 ++
 3 files changed, 151 insertions(+)
 create mode 100644 s390x/pv-ipl.c

diff --git a/s390x/Makefile b/s390x/Makefile
index 67be5360..b5b94810 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -43,6 +43,7 @@ tests += $(TEST_DIR)/ex.elf
 
 pv-tests += $(TEST_DIR)/pv-diags.elf
 pv-tests += $(TEST_DIR)/pv-icptcode.elf
+pv-tests += $(TEST_DIR)/pv-ipl.elf
 
 ifneq ($(HOST_KEY_DOCUMENT),)
 ifneq ($(GEN_SE_HEADER),)
@@ -130,6 +131,7 @@ $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-icpt-112.gbin
 $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/icpt-loop.gbin
 $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/loop.gbin
 $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-icpt-vir-timing.gbin
+$(TEST_DIR)/pv-ipl.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-308.gbin
 
 ifneq ($(GEN_SE_HEADER),)
 snippets += $(pv-snippets)
diff --git a/s390x/pv-ipl.c b/s390x/pv-ipl.c
new file mode 100644
index 00000000..aad1275e
--- /dev/null
+++ b/s390x/pv-ipl.c
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * PV diagnose 308 (IPL) tests
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+#include <libcflat.h>
+#include <sie.h>
+#include <sclp.h>
+#include <snippet.h>
+#include <pv_icptdata.h>
+#include <asm/facility.h>
+#include <asm/uv.h>
+
+static struct vm vm;
+
+static void test_diag_308(int subcode)
+{
+	extern const char SNIPPET_NAME_START(asm, pv_diag_308)[];
+	extern const char SNIPPET_NAME_END(asm, pv_diag_308)[];
+	extern const char SNIPPET_HDR_START(asm, pv_diag_308)[];
+	extern const char SNIPPET_HDR_END(asm, pv_diag_308)[];
+	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_308);
+	int size_gbin = SNIPPET_LEN(asm, pv_diag_308);
+	uint16_t rc, rrc;
+	char prefix[10];
+	int cc;
+
+	snprintf(prefix, sizeof(prefix), "subcode %d", subcode);
+
+	report_prefix_push(prefix);
+	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_308),
+			SNIPPET_HDR_START(asm, pv_diag_308),
+			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
+
+	/* First exit is a diag 0x500 */
+	sie(&vm);
+	assert(pv_icptdata_check_diag(&vm, 0x500));
+
+	/*
+	 * The snippet asked us for the subcode and we answer with 0 in gr2
+	 * SIE will copy gr2 to the guest
+	 */
+	vm.save_area.guest.grs[2] = subcode;
+
+	/* Continue after diag 0x500, next icpt should be the 0x308 */
+	sie(&vm);
+	assert(pv_icptdata_check_diag(&vm, 0x308));
+	assert(vm.save_area.guest.grs[2] == subcode);
+
+	/*
+	 * We need to perform several UV calls to emulate the subcode
+	 * 0/1. Failing to do that should result in a validity.
+	 *
+	 * - Mark all cpus as stopped
+	 * - Unshare all memory
+	 * - Prepare the reset
+	 * - Reset the cpus
+	 * - Load the reset PSW
+	 */
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity, no action");
+
+	/* Mark the CPU as stopped so we can unshare and reset */
+	cc = uv_set_cpu_state(vm.sblk->pv_handle_cpu, PV_CPU_STATE_STP);
+	report(!cc, "Set cpu stopped");
+
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity, stopped");
+
+	/* Unshare all memory */
+	cc = uv_cmd_nodata(vm.sblk->pv_handle_config,
+			   UVC_CMD_SET_UNSHARED_ALL, &rc, &rrc);
+	report(cc == 0 && rc == 1, "Unshare all");
+
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity, stopped, unshared");
+
+	/* Prepare the CPU reset */
+	cc = uv_cmd_nodata(vm.sblk->pv_handle_config,
+			   UVC_CMD_PREPARE_RESET, &rc, &rrc);
+	report(cc == 0 && rc == 1, "Prepare reset call");
+
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity, stopped, unshared, prep reset");
+
+	/*
+	 * Do the reset on the initiating cpu
+	 *
+	 * Reset clear for subcode 0
+	 * Reset initial for subcode 1
+	 */
+	if (subcode == 0) {
+		cc = uv_cmd_nodata(vm.sblk->pv_handle_cpu,
+				   UVC_CMD_CPU_RESET_CLEAR, &rc, &rrc);
+		report(cc == 0 && rc == 1, "Clear reset cpu");
+	} else {
+		cc = uv_cmd_nodata(vm.sblk->pv_handle_cpu,
+				   UVC_CMD_CPU_RESET_INITIAL, &rc, &rrc);
+		report(cc == 0 && rc == 1, "Initial reset cpu");
+	}
+
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "validity, stopped, unshared, prep reset, cpu reset");
+
+	/* Load the PSW from 0x0 */
+	cc = uv_set_cpu_state(vm.sblk->pv_handle_cpu, PV_CPU_STATE_OPR_LOAD);
+	report(!cc, "Set cpu load");
+
+	/*
+	 * Check if we executed the iaddr of the reset PSW, we should
+	 * see a diagnose 0x9c PV instruction notification.
+	 */
+	sie(&vm);
+	report(pv_icptdata_check_diag(&vm, 0x9c) &&
+	       vm.save_area.guest.grs[0] == 42,
+	       "continue after load");
+
+	uv_destroy_guest(&vm);
+	report_prefix_pop();
+}
+
+int main(void)
+{
+	report_prefix_push("uv-sie");
+	if (!uv_guest_requirement_checks())
+		goto done;
+
+	snippet_setup_guest(&vm, true);
+	test_diag_308(0);
+	test_diag_308(1);
+	sie_guest_destroy(&vm);
+
+done:
+	report_prefix_pop();
+	return report_summary();
+}
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index e2d3478e..e08e5c84 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -223,3 +223,7 @@ file = ex.elf
 file = pv-icptcode.elf
 smp = 3
 extra_params = -m 2200
+
+[pv-ipl]
+file = pv-ipl.elf
+extra_params = -m 2200
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [kvm-unit-tests PATCH v3 7/7] s390x: pv-diags: Add the test to unittests.conf
  2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (5 preceding siblings ...)
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 6/7] s390x: pv: Add IPL reset tests Janosch Frank
@ 2023-04-21 11:36 ` Janosch Frank
  2023-04-21 14:10   ` Claudio Imbrenda
  6 siblings, 1 reply; 19+ messages in thread
From: Janosch Frank @ 2023-04-21 11:36 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, nrb, david

Better to have it run into a skip than to not run it at all.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 s390x/unittests.cfg | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index e08e5c84..d6e7b170 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -227,3 +227,7 @@ extra_params = -m 2200
 [pv-ipl]
 file = pv-ipl.elf
 extra_params = -m 2200
+
+[pv-diags]
+file = pv-diags.elf
+extra_params = -m 2200
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function Janosch Frank
@ 2023-04-21 14:10   ` Claudio Imbrenda
  2023-04-26 11:22   ` Nico Boehr
  1 sibling, 0 replies; 19+ messages in thread
From: Claudio Imbrenda @ 2023-04-21 14:10 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, thuth, nrb, david

On Fri, 21 Apr 2023 11:36:42 +0000
Janosch Frank <frankja@linux.ibm.com> wrote:

> When working with guests it's essential to check the SIE intercept
> data for the correct values. Fortunately on PV guests these values are
> constants so we can create check functions which test for the
> constants.
> 
> While we're at it let's make pv-diags.c use this new function.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

> ---
>  lib/s390x/pv_icptdata.h | 42 +++++++++++++++++++++++++++++++++++++++++
>  s390x/pv-diags.c        | 14 ++++++--------
>  2 files changed, 48 insertions(+), 8 deletions(-)
>  create mode 100644 lib/s390x/pv_icptdata.h
> 
> diff --git a/lib/s390x/pv_icptdata.h b/lib/s390x/pv_icptdata.h
> new file mode 100644
> index 00000000..4746117e
> --- /dev/null
> +++ b/lib/s390x/pv_icptdata.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Commonly used checks for PV SIE intercept data
> + *
> + * Copyright IBM Corp. 2023
> + * Author: Janosch Frank <frankja@linux.ibm.com>
> + */
> +
> +#ifndef _S390X_PV_ICPTDATA_H_
> +#define _S390X_PV_ICPTDATA_H_
> +
> +#include <sie.h>
> +
> +/*
> + * Checks the diagnose instruction intercept data for consistency with
> + * the constants defined by the PV SIE architecture
> + *
> + * Supports: 0x44, 0x9c, 0x288, 0x308, 0x500
> + */
> +static bool pv_icptdata_check_diag(struct vm *vm, int diag)
> +{
> +	int icptcode;
> +
> +	switch (diag) {
> +	case 0x44:
> +	case 0x9c:
> +	case 0x288:
> +	case 0x308:
> +		icptcode = ICPT_PV_NOTIFY;
> +		break;
> +	case 0x500:
> +		icptcode = ICPT_PV_INSTR;
> +		break;
> +	default:
> +		/* If a new diag is introduced add it to the cases above! */
> +		assert(0);
> +	}
> +
> +	return vm->sblk->icptcode == icptcode && vm->sblk->ipa == 0x8302 &&
> +	       vm->sblk->ipb == 0x50000000 && vm->save_area.guest.grs[5] == diag;
> +}
> +#endif
> diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c
> index 5165937a..096ac61f 100644
> --- a/s390x/pv-diags.c
> +++ b/s390x/pv-diags.c
> @@ -9,6 +9,7 @@
>   */
>  #include <libcflat.h>
>  #include <snippet.h>
> +#include <pv_icptdata.h>
>  #include <sie.h>
>  #include <sclp.h>
>  #include <asm/facility.h>
> @@ -31,8 +32,7 @@ static void test_diag_500(void)
>  			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
>  
>  	sie(&vm);
> -	report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 &&
> -	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x500,
> +	report(pv_icptdata_check_diag(&vm, 0x500),
>  	       "intercept values");
>  	report(vm.save_area.guest.grs[1] == 1 &&
>  	       vm.save_area.guest.grs[2] == 2 &&
> @@ -45,9 +45,8 @@ static void test_diag_500(void)
>  	 */
>  	vm.sblk->iictl = IICTL_CODE_OPERAND;
>  	sie(&vm);
> -	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
> -	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
> -	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND,
> +	report(pv_icptdata_check_diag(&vm, 0x9c) &&
> +	       vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND,
>  	       "operand exception");
>  
>  	/*
> @@ -58,9 +57,8 @@ static void test_diag_500(void)
>  	vm.sblk->iictl = IICTL_CODE_SPECIFICATION;
>  	/* Inject PGM, next exit should be 9c */
>  	sie(&vm);
> -	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
> -	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
> -	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
> +	report(pv_icptdata_check_diag(&vm, 0x9c) &&
> +	       vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
>  	       "specification exception");
>  
>  	/* No need for cleanup, just tear down the VM */


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
@ 2023-04-21 14:10   ` Claudio Imbrenda
  2023-04-26 11:24   ` Nico Boehr
  1 sibling, 0 replies; 19+ messages in thread
From: Claudio Imbrenda @ 2023-04-21 14:10 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, thuth, nrb, david

On Fri, 21 Apr 2023 11:36:43 +0000
Janosch Frank <frankja@linux.ibm.com> wrote:

> It's a bit redundant.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

> ---
>  s390x/Makefile                                |  6 +--
>  s390x/pv-diags.c                              | 48 +++++++++----------
>  .../{snippet-pv-diag-288.S => pv-diag-288.S}  |  0
>  .../{snippet-pv-diag-500.S => pv-diag-500.S}  |  0
>  ...nippet-pv-diag-yield.S => pv-diag-yield.S} |  0
>  5 files changed, 27 insertions(+), 27 deletions(-)
>  rename s390x/snippets/asm/{snippet-pv-diag-288.S => pv-diag-288.S} (100%)
>  rename s390x/snippets/asm/{snippet-pv-diag-500.S => pv-diag-500.S} (100%)
>  rename s390x/snippets/asm/{snippet-pv-diag-yield.S => pv-diag-yield.S} (100%)
> 
> diff --git a/s390x/Makefile b/s390x/Makefile
> index a80db538..8d1cfc7c 100644
> --- a/s390x/Makefile
> +++ b/s390x/Makefile
> @@ -122,9 +122,9 @@ snippet_lib = $(snippet_asmlib) lib/auxinfo.o
>  $(TEST_DIR)/mvpg-sie.elf: snippets = $(SNIPPET_DIR)/c/mvpg-snippet.gbin
>  $(TEST_DIR)/spec_ex-sie.elf: snippets = $(SNIPPET_DIR)/c/spec_ex.gbin
>  
> -$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/snippet-pv-diag-yield.gbin
> -$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/snippet-pv-diag-288.gbin
> -$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/snippet-pv-diag-500.gbin
> +$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-yield.gbin
> +$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-288.gbin
> +$(TEST_DIR)/pv-diags.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-500.gbin
>  
>  ifneq ($(GEN_SE_HEADER),)
>  snippets += $(pv-snippets)
> diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c
> index 096ac61f..fa4e5532 100644
> --- a/s390x/pv-diags.c
> +++ b/s390x/pv-diags.c
> @@ -18,17 +18,17 @@ static struct vm vm;
>  
>  static void test_diag_500(void)
>  {
> -	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_500)[];
> -	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_500)[];
> -	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_500)[];
> -	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_500)[];
> -	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_500);
> -	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_500);
> +	extern const char SNIPPET_NAME_START(asm, pv_diag_500)[];
> +	extern const char SNIPPET_NAME_END(asm, pv_diag_500)[];
> +	extern const char SNIPPET_HDR_START(asm, pv_diag_500)[];
> +	extern const char SNIPPET_HDR_END(asm, pv_diag_500)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_500);
> +	int size_gbin = SNIPPET_LEN(asm, pv_diag_500);
>  
>  	report_prefix_push("diag 0x500");
>  
> -	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_500),
> -			SNIPPET_HDR_START(asm, snippet_pv_diag_500),
> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_500),
> +			SNIPPET_HDR_START(asm, pv_diag_500),
>  			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
>  
>  	sie(&vm);
> @@ -70,17 +70,17 @@ static void test_diag_500(void)
>  
>  static void test_diag_288(void)
>  {
> -	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_288)[];
> -	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_288)[];
> -	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_288)[];
> -	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_288)[];
> -	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_288);
> -	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_288);
> +	extern const char SNIPPET_NAME_START(asm, pv_diag_288)[];
> +	extern const char SNIPPET_NAME_END(asm, pv_diag_288)[];
> +	extern const char SNIPPET_HDR_START(asm, pv_diag_288)[];
> +	extern const char SNIPPET_HDR_END(asm, pv_diag_288)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_288);
> +	int size_gbin = SNIPPET_LEN(asm, pv_diag_288);
>  
>  	report_prefix_push("diag 0x288");
>  
> -	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_288),
> -			SNIPPET_HDR_START(asm, snippet_pv_diag_288),
> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_288),
> +			SNIPPET_HDR_START(asm, pv_diag_288),
>  			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
>  
>  	sie(&vm);
> @@ -111,17 +111,17 @@ static void test_diag_288(void)
>  
>  static void test_diag_yield(void)
>  {
> -	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_yield)[];
> -	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_yield)[];
> -	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_yield)[];
> -	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_yield)[];
> -	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_yield);
> -	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_yield);
> +	extern const char SNIPPET_NAME_START(asm, pv_diag_yield)[];
> +	extern const char SNIPPET_NAME_END(asm, pv_diag_yield)[];
> +	extern const char SNIPPET_HDR_START(asm, pv_diag_yield)[];
> +	extern const char SNIPPET_HDR_END(asm, pv_diag_yield)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_yield);
> +	int size_gbin = SNIPPET_LEN(asm, pv_diag_yield);
>  
>  	report_prefix_push("diag yield");
>  
> -	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_yield),
> -			SNIPPET_HDR_START(asm, snippet_pv_diag_yield),
> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_yield),
> +			SNIPPET_HDR_START(asm, pv_diag_yield),
>  			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
>  
>  	/* 0x44 */
> diff --git a/s390x/snippets/asm/snippet-pv-diag-288.S b/s390x/snippets/asm/pv-diag-288.S
> similarity index 100%
> rename from s390x/snippets/asm/snippet-pv-diag-288.S
> rename to s390x/snippets/asm/pv-diag-288.S
> diff --git a/s390x/snippets/asm/snippet-pv-diag-500.S b/s390x/snippets/asm/pv-diag-500.S
> similarity index 100%
> rename from s390x/snippets/asm/snippet-pv-diag-500.S
> rename to s390x/snippets/asm/pv-diag-500.S
> diff --git a/s390x/snippets/asm/snippet-pv-diag-yield.S b/s390x/snippets/asm/pv-diag-yield.S
> similarity index 100%
> rename from s390x/snippets/asm/snippet-pv-diag-yield.S
> rename to s390x/snippets/asm/pv-diag-yield.S


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 7/7] s390x: pv-diags: Add the test to unittests.conf
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 7/7] s390x: pv-diags: Add the test to unittests.conf Janosch Frank
@ 2023-04-21 14:10   ` Claudio Imbrenda
  0 siblings, 0 replies; 19+ messages in thread
From: Claudio Imbrenda @ 2023-04-21 14:10 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, thuth, nrb, david

On Fri, 21 Apr 2023 11:36:47 +0000
Janosch Frank <frankja@linux.ibm.com> wrote:

> Better to have it run into a skip than to not run it at all.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

> ---
>  s390x/unittests.cfg | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index e08e5c84..d6e7b170 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -227,3 +227,7 @@ extra_params = -m 2200
>  [pv-ipl]
>  file = pv-ipl.elf
>  extra_params = -m 2200
> +
> +[pv-diags]
> +file = pv-diags.elf
> +extra_params = -m 2200


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function Janosch Frank
@ 2023-04-21 14:13   ` Claudio Imbrenda
  2023-04-24  8:26     ` Janosch Frank
  2023-04-26 11:27   ` Nico Boehr
  1 sibling, 1 reply; 19+ messages in thread
From: Claudio Imbrenda @ 2023-04-21 14:13 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, thuth, nrb, david

On Fri, 21 Apr 2023 11:36:44 +0000
Janosch Frank <frankja@linux.ibm.com> wrote:

> When running PV guests some of the UV memory needs to be allocated
> with > 31 bit addresses which means tests with PV guests will always
> need a lot more memory than other tests.
> Additionally facilities nr 158 and sclp.sief2 need to be available.
> 
> Let's add a function that checks for these requirements and prints a
> helpful skip message.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
>  lib/s390x/snippet.h |  7 +++++++
>  lib/s390x/uv.c      | 20 ++++++++++++++++++++
>  lib/s390x/uv.h      |  1 +
>  s390x/pv-diags.c    |  8 +-------
>  4 files changed, 29 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/s390x/snippet.h b/lib/s390x/snippet.h
> index 57045994..11ec54c3 100644
> --- a/lib/s390x/snippet.h
> +++ b/lib/s390x/snippet.h
> @@ -30,6 +30,13 @@
>  #define SNIPPET_HDR_LEN(type, file) \
>  	((uintptr_t)SNIPPET_HDR_END(type, file) - (uintptr_t)SNIPPET_HDR_START(type, file))
>  
> +/*
> + * Some of the UV memory needs to be allocated with >31 bit
> + * addresses which means we need a lot more memory than other
> + * tests.
> + */
> +#define SNIPPET_PV_MIN_MEM_SIZE	(SZ_1M * 2200UL)
> +
>  #define SNIPPET_PV_TWEAK0	0x42UL
>  #define SNIPPET_PV_TWEAK1	0UL
>  #define SNIPPET_UNPACK_OFF	0
> diff --git a/lib/s390x/uv.c b/lib/s390x/uv.c
> index 383271a5..db47536c 100644
> --- a/lib/s390x/uv.c
> +++ b/lib/s390x/uv.c
> @@ -18,6 +18,7 @@
>  #include <asm/uv.h>
>  #include <uv.h>
>  #include <sie.h>
> +#include <snippet.h>
>  
>  static struct uv_cb_qui uvcb_qui = {
>  	.header.cmd = UVC_CMD_QUI,
> @@ -38,6 +39,25 @@ bool uv_os_is_host(void)
>  	return test_facility(158) && uv_query_test_call(BIT_UVC_CMD_INIT_UV);
>  }
>  
> +bool uv_guest_requirement_checks(void)

I would call it uv_host_requirement_checks since it will run on the
host to check if the host meets certain requirements

> +{
> +	if (!test_facility(158)) {
> +		report_skip("UV Call facility unavailable");
> +		return false;
> +	}
> +	if (!sclp_facilities.has_sief2) {
> +		report_skip("SIEF2 facility unavailable");
> +		return false;
> +	}
> +	if (get_ram_size() < SNIPPET_PV_MIN_MEM_SIZE) {
> +		report_skip("Not enough memory. This test needs about %ld MB of memory",
> +			    SNIPPET_PV_MIN_MEM_SIZE / 1024 / 1024);

a better way to do this would be to check the amount of memory needed
by the Ultravisor and check if that size + 2GB is available

of course in that case unittest.cfg would also need to be adjusted

> +		return false;
> +	}
> +
> +	return true;
> +}
> +
>  bool uv_query_test_call(unsigned int nr)
>  {
>  	/* Query needs to be called first */
> diff --git a/lib/s390x/uv.h b/lib/s390x/uv.h
> index 78b979b7..d9af691a 100644
> --- a/lib/s390x/uv.h
> +++ b/lib/s390x/uv.h
> @@ -7,6 +7,7 @@
>  
>  bool uv_os_is_guest(void);
>  bool uv_os_is_host(void);
> +bool uv_guest_requirement_checks(void);
>  bool uv_query_test_call(unsigned int nr);
>  const struct uv_cb_qui *uv_get_query_data(void);
>  void uv_init(void);
> diff --git a/s390x/pv-diags.c b/s390x/pv-diags.c
> index fa4e5532..1289a571 100644
> --- a/s390x/pv-diags.c
> +++ b/s390x/pv-diags.c
> @@ -149,14 +149,8 @@ static void test_diag_yield(void)
>  int main(void)
>  {
>  	report_prefix_push("pv-diags");
> -	if (!test_facility(158)) {
> -		report_skip("UV Call facility unavailable");
> +	if (!uv_guest_requirement_checks())
>  		goto done;
> -	}
> -	if (!sclp_facilities.has_sief2) {
> -		report_skip("SIEF2 facility unavailable");
> -		goto done;
> -	}
>  
>  	uv_setup_asces();
>  	snippet_setup_guest(&vm, true);


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 5/7] s390x: pv: Add sie entry intercept and validity test
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 5/7] s390x: pv: Add sie entry intercept and validity test Janosch Frank
@ 2023-04-21 15:23   ` Claudio Imbrenda
  0 siblings, 0 replies; 19+ messages in thread
From: Claudio Imbrenda @ 2023-04-21 15:23 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, thuth, nrb, david

On Fri, 21 Apr 2023 11:36:45 +0000
Janosch Frank <frankja@linux.ibm.com> wrote:

[...]

> +static void run_loop(void)
> +{
> +	sie(&vm);
> +	sigp_retry(stap(), SIGP_STOP, 0, NULL);
> +}
> +
> +static void test_validity_already_running(void)
> +{
> +	extern const char SNIPPET_NAME_START(asm, loop)[];
> +	extern const char SNIPPET_NAME_END(asm, loop)[];
> +	extern const char SNIPPET_HDR_START(asm, loop)[];
> +	extern const char SNIPPET_HDR_END(asm, loop)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, loop);
> +	int size_gbin = SNIPPET_LEN(asm, loop);
> +	struct psw psw = {
> +		.mask = PSW_MASK_64,
> +		.addr = (uint64_t)run_loop,
> +	};
> +
> +	report_prefix_push("already running");
> +	if (smp_query_num_cpus() < 3) {
> +		report_skip("need at least 3 cpus for this test");
> +		goto out;
> +	}
> +
> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, loop),
> +			SNIPPET_HDR_START(asm, loop),
> +			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
> +
> +	sie_expect_validity(&vm);
> +	smp_cpu_setup(1, psw);

I would expect the validity here instead (one CPU should run fine)

> +	smp_cpu_setup(2, psw);
> +	while (vm.sblk->icptcode != ICPT_VALIDITY) {
> +		mb();
> +	}
> +
> +	/*
> +	 * One cpu will enter SIE and one will receive the validity.
> +	 * We rely on the expectation that the cpu in SIE won't exit
> +	 * until we had a chance to observe the validity as the exit
> +	 * would overwrite the validity.
> +	 *
> +	 * In general that expectation is valid but HW/FW can in
> +	 * theory still exit to handle their interrupts.
> +	 */
> +	report(uv_validity_check(&vm), "validity");
> +	smp_cpu_stop(1);
> +	smp_cpu_stop(2);
> +	uv_destroy_guest(&vm);
> +
> +out:
> +	report_prefix_pop();
> +}
> +
> +/* Tests if a vcpu handle from another configuration results in a validity intercept. */
> +static void test_validity_handle_not_in_config(void)
> +{
> +	extern const char SNIPPET_NAME_START(asm, icpt_loop)[];
> +	extern const char SNIPPET_NAME_END(asm, icpt_loop)[];
> +	extern const char SNIPPET_HDR_START(asm, icpt_loop)[];
> +	extern const char SNIPPET_HDR_END(asm, icpt_loop)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, icpt_loop);
> +	int size_gbin = SNIPPET_LEN(asm, icpt_loop);
> +
> +	report_prefix_push("handle not in config");
> +	/* Setup our primary vm */
> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, icpt_loop),
> +			SNIPPET_HDR_START(asm, icpt_loop),
> +			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
> +
> +	/* Setup secondary vm */
> +	snippet_setup_guest(&vm2, true);
> +	snippet_pv_init(&vm2, SNIPPET_NAME_START(asm, icpt_loop),
> +			SNIPPET_HDR_START(asm, icpt_loop),
> +			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
> +
> +	vm.sblk->pv_handle_cpu = vm2.sblk->pv_handle_cpu;
> +	sie_expect_validity(&vm);
> +	sie(&vm);
> +	report(uv_validity_check(&vm), "validity");

you tested the case where you have the right sie control block but with
the wrong cpu handle, could you also do the other way around? (put the
config handle of the wrong VM)

> +
> +	/* Restore cpu handle and destroy the second vm */
> +	vm.sblk->pv_handle_cpu = vm.uv.vcpu_handle;
> +	uv_destroy_guest(&vm2);
> +	sie_guest_destroy(&vm2);
> +
> +	uv_destroy_guest(&vm);
> +	report_prefix_pop();
> +}
> +
> +/* Tests if a wrong vm or vcpu handle results in a validity intercept. */
> +static void test_validity_seid(void)
> +{
> +	extern const char SNIPPET_NAME_START(asm, icpt_loop)[];
> +	extern const char SNIPPET_NAME_END(asm, icpt_loop)[];
> +	extern const char SNIPPET_HDR_START(asm, icpt_loop)[];
> +	extern const char SNIPPET_HDR_END(asm, icpt_loop)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, icpt_loop);
> +	int size_gbin = SNIPPET_LEN(asm, icpt_loop);
> +	int fails = 0;
> +	int i;
> +
> +	report_prefix_push("handles");
> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, icpt_loop),
> +			SNIPPET_HDR_START(asm, icpt_loop),
> +			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
> +
> +	for (i = 0; i < 64; i++) {
> +		vm.sblk->pv_handle_config ^= 1UL << i;
> +		sie_expect_validity(&vm);
> +		sie(&vm);
> +		if (!uv_validity_check(&vm)) {
> +			report_fail("SIE accepted wrong VM SEID, changed bit %d",
> +				    63 - i);
> +			fails++;
> +		}
> +		vm.sblk->pv_handle_config ^= 1UL << i;
> +	}
> +	report(!fails, "No wrong vm handle accepted");
> +
> +	fails = 0;
> +	for (i = 0; i < 64; i++) {
> +		vm.sblk->pv_handle_cpu ^= 1UL << i;
> +		sie_expect_validity(&vm);
> +		sie(&vm);
> +		if (!uv_validity_check(&vm)) {
> +			report_fail("SIE accepted wrong CPU SEID, changed bit %d",
> +				    63 - i);
> +			fails++;
> +		}
> +		vm.sblk->pv_handle_cpu ^= 1UL << i;
> +	}
> +	report(!fails, "No wrong cpu handle accepted");
> +
> +	uv_destroy_guest(&vm);
> +	report_prefix_pop();
> +}

[...]

> +static void run_icpt_122_tests_prefix(unsigned long prefix)
> +{
> +	char prfxstr[7];
> +	uint32_t *ptr = 0;
> +
> +	snprintf(prfxstr, sizeof(prfxstr), "0x%lx", prefix);
> +
> +	report_prefix_push(prfxstr);

report_prefix_pushf ?

> +	report_prefix_push("unshared");
> +	run_icpt_122_tests(prefix);
> +	report_prefix_pop();
> +
> +	/*
> +	 * Guest will share the lowcore and we need to check if that
> +	 * makes a difference (which it should not).
> +	 */
> +	report_prefix_push("shared");
> +
> +	sie(&vm);
> +	/* Guest indicates that it has been setup via the diag 0x44 */
> +	assert(pv_icptdata_check_diag(&vm, 0x44));
> +	/* If the pages have not been shared these writes will cause exceptions */
> +	ptr = (uint32_t *)prefix;
> +	WRITE_ONCE(ptr, 0);
> +	ptr = (uint32_t *)(prefix + offsetof(struct lowcore, ars_sa[0]));
> +	WRITE_ONCE(ptr, 0);
> +
> +	run_icpt_122_tests(prefix);
> +
> +	/* shared*/
> +	report_prefix_pop();
> +	/* prefix hex value */
> +	report_prefix_pop();
> +}

[...]

> diff --git a/s390x/snippets/asm/pv-icpt-vir-timing.S b/s390x/snippets/asm/pv-icpt-vir-timing.S
> new file mode 100644
> index 00000000..b35f02c9
> --- /dev/null
> +++ b/s390x/snippets/asm/pv-icpt-vir-timing.S
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Sets a cpu timer which the host can manipulate to check if it will
> + * receive a validity
> + *
> + * Copyright (c) 2023 IBM Corp
> + *
> + * Authors:
> + *  Janosch Frank <frankja@linux.ibm.com>
> + */
> +.section .text
> +larl	%r1, time_val
> +spt	0 (%r1)
> +diag    0, 0, 0x44
> +xgr	%r1, %r1

why do you need the xgr?

> +lghi	%r1, 42

you're overwriting the whole register here

> +diag	1, 0, 0x9c
> +
> +
> +.align 8
> +time_val:
> +	.quad 0x280de80000
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index b61faf07..e2d3478e 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -218,3 +218,8 @@ extra_params = -append '--parallel'
>  
>  [execute]
>  file = ex.elf
> +
> +[pv-icptcode]
> +file = pv-icptcode.elf
> +smp = 3
> +extra_params = -m 2200


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 6/7] s390x: pv: Add IPL reset tests
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 6/7] s390x: pv: Add IPL reset tests Janosch Frank
@ 2023-04-21 15:32   ` Claudio Imbrenda
  0 siblings, 0 replies; 19+ messages in thread
From: Claudio Imbrenda @ 2023-04-21 15:32 UTC (permalink / raw)
  To: Janosch Frank; +Cc: kvm, linux-s390, thuth, nrb, david

On Fri, 21 Apr 2023 11:36:46 +0000
Janosch Frank <frankja@linux.ibm.com> wrote:

> The diag308 requires extensive cooperation between the hypervisor and
> the Ultravisor so the Ultravisor can make sure all necessary reset
> steps have been done.
> 
> Let's check if we get the correct validity errors.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
>  s390x/Makefile      |   2 +
>  s390x/pv-ipl.c      | 145 ++++++++++++++++++++++++++++++++++++++++++++
>  s390x/unittests.cfg |   4 ++
>  3 files changed, 151 insertions(+)
>  create mode 100644 s390x/pv-ipl.c
> 
> diff --git a/s390x/Makefile b/s390x/Makefile
> index 67be5360..b5b94810 100644
> --- a/s390x/Makefile
> +++ b/s390x/Makefile
> @@ -43,6 +43,7 @@ tests += $(TEST_DIR)/ex.elf
>  
>  pv-tests += $(TEST_DIR)/pv-diags.elf
>  pv-tests += $(TEST_DIR)/pv-icptcode.elf
> +pv-tests += $(TEST_DIR)/pv-ipl.elf
>  
>  ifneq ($(HOST_KEY_DOCUMENT),)
>  ifneq ($(GEN_SE_HEADER),)
> @@ -130,6 +131,7 @@ $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-icpt-112.gbin
>  $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/icpt-loop.gbin
>  $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/loop.gbin
>  $(TEST_DIR)/pv-icptcode.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-icpt-vir-timing.gbin
> +$(TEST_DIR)/pv-ipl.elf: pv-snippets += $(SNIPPET_DIR)/asm/pv-diag-308.gbin
>  
>  ifneq ($(GEN_SE_HEADER),)
>  snippets += $(pv-snippets)
> diff --git a/s390x/pv-ipl.c b/s390x/pv-ipl.c
> new file mode 100644
> index 00000000..aad1275e
> --- /dev/null
> +++ b/s390x/pv-ipl.c
> @@ -0,0 +1,145 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * PV diagnose 308 (IPL) tests
> + *
> + * Copyright (c) 2023 IBM Corp
> + *
> + * Authors:
> + *  Janosch Frank <frankja@linux.ibm.com>
> + */
> +#include <libcflat.h>
> +#include <sie.h>
> +#include <sclp.h>
> +#include <snippet.h>
> +#include <pv_icptdata.h>
> +#include <asm/facility.h>
> +#include <asm/uv.h>
> +
> +static struct vm vm;
> +
> +static void test_diag_308(int subcode)
> +{
> +	extern const char SNIPPET_NAME_START(asm, pv_diag_308)[];
> +	extern const char SNIPPET_NAME_END(asm, pv_diag_308)[];
> +	extern const char SNIPPET_HDR_START(asm, pv_diag_308)[];
> +	extern const char SNIPPET_HDR_END(asm, pv_diag_308)[];
> +	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_308);
> +	int size_gbin = SNIPPET_LEN(asm, pv_diag_308);
> +	uint16_t rc, rrc;
> +	char prefix[10];
> +	int cc;
> +
> +	snprintf(prefix, sizeof(prefix), "subcode %d", subcode);
> +
> +	report_prefix_push(prefix);

report_prefix_pushf

> +	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_308),
> +			SNIPPET_HDR_START(asm, pv_diag_308),
> +			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
> +
> +	/* First exit is a diag 0x500 */
> +	sie(&vm);
> +	assert(pv_icptdata_check_diag(&vm, 0x500));
> +
> +	/*
> +	 * The snippet asked us for the subcode and we answer with 0 in gr2

not always 0 I guess?

> +	 * SIE will copy gr2 to the guest
> +	 */
> +	vm.save_area.guest.grs[2] = subcode;
> +
> +	/* Continue after diag 0x500, next icpt should be the 0x308 */
> +	sie(&vm);
> +	assert(pv_icptdata_check_diag(&vm, 0x308));
> +	assert(vm.save_area.guest.grs[2] == subcode);
> +
> +	/*
> +	 * We need to perform several UV calls to emulate the subcode
> +	 * 0/1. Failing to do that should result in a validity.
> +	 *
> +	 * - Mark all cpus as stopped
> +	 * - Unshare all memory
> +	 * - Prepare the reset
> +	 * - Reset the cpus
> +	 * - Load the reset PSW
> +	 */
> +	sie_expect_validity(&vm);
> +	sie(&vm);
> +	report(uv_validity_check(&vm), "validity, no action");
> +
> +	/* Mark the CPU as stopped so we can unshare and reset */
> +	cc = uv_set_cpu_state(vm.sblk->pv_handle_cpu, PV_CPU_STATE_STP);
> +	report(!cc, "Set cpu stopped");
> +
> +	sie_expect_validity(&vm);
> +	sie(&vm);
> +	report(uv_validity_check(&vm), "validity, stopped");
> +
> +	/* Unshare all memory */
> +	cc = uv_cmd_nodata(vm.sblk->pv_handle_config,
> +			   UVC_CMD_SET_UNSHARED_ALL, &rc, &rrc);
> +	report(cc == 0 && rc == 1, "Unshare all");
> +
> +	sie_expect_validity(&vm);
> +	sie(&vm);
> +	report(uv_validity_check(&vm), "validity, stopped, unshared");
> +
> +	/* Prepare the CPU reset */
> +	cc = uv_cmd_nodata(vm.sblk->pv_handle_config,
> +			   UVC_CMD_PREPARE_RESET, &rc, &rrc);
> +	report(cc == 0 && rc == 1, "Prepare reset call");
> +
> +	sie_expect_validity(&vm);
> +	sie(&vm);
> +	report(uv_validity_check(&vm), "validity, stopped, unshared, prep reset");
> +
> +	/*
> +	 * Do the reset on the initiating cpu
> +	 *
> +	 * Reset clear for subcode 0
> +	 * Reset initial for subcode 1
> +	 */
> +	if (subcode == 0) {
> +		cc = uv_cmd_nodata(vm.sblk->pv_handle_cpu,
> +				   UVC_CMD_CPU_RESET_CLEAR, &rc, &rrc);
> +		report(cc == 0 && rc == 1, "Clear reset cpu");
> +	} else {
> +		cc = uv_cmd_nodata(vm.sblk->pv_handle_cpu,
> +				   UVC_CMD_CPU_RESET_INITIAL, &rc, &rrc);
> +		report(cc == 0 && rc == 1, "Initial reset cpu");
> +	}
> +
> +	sie_expect_validity(&vm);
> +	sie(&vm);
> +	report(uv_validity_check(&vm), "validity, stopped, unshared, prep reset, cpu reset");
> +
> +	/* Load the PSW from 0x0 */
> +	cc = uv_set_cpu_state(vm.sblk->pv_handle_cpu, PV_CPU_STATE_OPR_LOAD);
> +	report(!cc, "Set cpu load");
> +
> +	/*
> +	 * Check if we executed the iaddr of the reset PSW, we should
> +	 * see a diagnose 0x9c PV instruction notification.
> +	 */
> +	sie(&vm);
> +	report(pv_icptdata_check_diag(&vm, 0x9c) &&
> +	       vm.save_area.guest.grs[0] == 42,
> +	       "continue after load");
> +
> +	uv_destroy_guest(&vm);
> +	report_prefix_pop();
> +}
> +
> +int main(void)
> +{
> +	report_prefix_push("uv-sie");
> +	if (!uv_guest_requirement_checks())
> +		goto done;
> +
> +	snippet_setup_guest(&vm, true);
> +	test_diag_308(0);
> +	test_diag_308(1);
> +	sie_guest_destroy(&vm);
> +
> +done:
> +	report_prefix_pop();
> +	return report_summary();
> +}
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index e2d3478e..e08e5c84 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -223,3 +223,7 @@ file = ex.elf
>  file = pv-icptcode.elf
>  smp = 3
>  extra_params = -m 2200
> +
> +[pv-ipl]
> +file = pv-ipl.elf
> +extra_params = -m 2200


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function
  2023-04-21 14:13   ` Claudio Imbrenda
@ 2023-04-24  8:26     ` Janosch Frank
  0 siblings, 0 replies; 19+ messages in thread
From: Janosch Frank @ 2023-04-24  8:26 UTC (permalink / raw)
  To: Claudio Imbrenda; +Cc: kvm, linux-s390, thuth, nrb, david

On 4/21/23 16:13, Claudio Imbrenda wrote:
> On Fri, 21 Apr 2023 11:36:44 +0000
> Janosch Frank <frankja@linux.ibm.com> wrote:
> 
>> When running PV guests some of the UV memory needs to be allocated
>> with > 31 bit addresses which means tests with PV guests will always
>> need a lot more memory than other tests.
>> Additionally facilities nr 158 and sclp.sief2 need to be available.
>>
>> Let's add a function that checks for these requirements and prints a
>> helpful skip message.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> ---
>>   lib/s390x/snippet.h |  7 +++++++
>>   lib/s390x/uv.c      | 20 ++++++++++++++++++++
>>   lib/s390x/uv.h      |  1 +
>>   s390x/pv-diags.c    |  8 +-------
>>   4 files changed, 29 insertions(+), 7 deletions(-)
>>
>> diff --git a/lib/s390x/snippet.h b/lib/s390x/snippet.h
>> index 57045994..11ec54c3 100644
>> --- a/lib/s390x/snippet.h
>> +++ b/lib/s390x/snippet.h
>> @@ -30,6 +30,13 @@
>>   #define SNIPPET_HDR_LEN(type, file) \
>>   	((uintptr_t)SNIPPET_HDR_END(type, file) - (uintptr_t)SNIPPET_HDR_START(type, file))
>>   
>> +/*
>> + * Some of the UV memory needs to be allocated with >31 bit
>> + * addresses which means we need a lot more memory than other
>> + * tests.
>> + */
>> +#define SNIPPET_PV_MIN_MEM_SIZE	(SZ_1M * 2200UL)
>> +
>>   #define SNIPPET_PV_TWEAK0	0x42UL
>>   #define SNIPPET_PV_TWEAK1	0UL
>>   #define SNIPPET_UNPACK_OFF	0
>> diff --git a/lib/s390x/uv.c b/lib/s390x/uv.c
>> index 383271a5..db47536c 100644
>> --- a/lib/s390x/uv.c
>> +++ b/lib/s390x/uv.c
>> @@ -18,6 +18,7 @@
>>   #include <asm/uv.h>
>>   #include <uv.h>
>>   #include <sie.h>
>> +#include <snippet.h>
>>   
>>   static struct uv_cb_qui uvcb_qui = {
>>   	.header.cmd = UVC_CMD_QUI,
>> @@ -38,6 +39,25 @@ bool uv_os_is_host(void)
>>   	return test_facility(158) && uv_query_test_call(BIT_UVC_CMD_INIT_UV);
>>   }
>>   
>> +bool uv_guest_requirement_checks(void)
> 
> I would call it uv_host_requirement_checks since it will run on the
> host to check if the host meets certain requirements

Sure
If someone has a shorter suggestion I'd also be happy to hear it.

> 
>> +{
>> +	if (!test_facility(158)) {
>> +		report_skip("UV Call facility unavailable");
>> +		return false;
>> +	}
>> +	if (!sclp_facilities.has_sief2) {
>> +		report_skip("SIEF2 facility unavailable");
>> +		return false;
>> +	}
>> +	if (get_ram_size() < SNIPPET_PV_MIN_MEM_SIZE) {
>> +		report_skip("Not enough memory. This test needs about %ld MB of memory",
>> +			    SNIPPET_PV_MIN_MEM_SIZE / 1024 / 1024);
> 
> a better way to do this would be to check the amount of memory needed
> by the Ultravisor and check if that size + 2GB is available
> 
> of course in that case unittest.cfg would also need to be adjusted

Could do, but in this case I opted for simplicity.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function Janosch Frank
  2023-04-21 14:10   ` Claudio Imbrenda
@ 2023-04-26 11:22   ` Nico Boehr
  1 sibling, 0 replies; 19+ messages in thread
From: Nico Boehr @ 2023-04-26 11:22 UTC (permalink / raw)
  To: Janosch Frank, kvm; +Cc: linux-s390, imbrenda, thuth, david

Quoting Janosch Frank (2023-04-21 13:36:42)
> When working with guests it's essential to check the SIE intercept
> data for the correct values. Fortunately on PV guests these values are
> constants so we can create check functions which test for the
> constants.
> 
> While we're at it let's make pv-diags.c use this new function.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

Reviewed-by: Nico Boehr <nrb@linux.ibm.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
  2023-04-21 14:10   ` Claudio Imbrenda
@ 2023-04-26 11:24   ` Nico Boehr
  1 sibling, 0 replies; 19+ messages in thread
From: Nico Boehr @ 2023-04-26 11:24 UTC (permalink / raw)
  To: Janosch Frank, kvm; +Cc: linux-s390, imbrenda, thuth, david

Quoting Janosch Frank (2023-04-21 13:36:43)
> It's a bit redundant.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

Yes, this has confused me before!

Acked-by: Nico Boehr <nrb@linux.ibm.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function Janosch Frank
  2023-04-21 14:13   ` Claudio Imbrenda
@ 2023-04-26 11:27   ` Nico Boehr
  1 sibling, 0 replies; 19+ messages in thread
From: Nico Boehr @ 2023-04-26 11:27 UTC (permalink / raw)
  To: Janosch Frank, kvm; +Cc: linux-s390, imbrenda, thuth, david

Quoting Janosch Frank (2023-04-21 13:36:44)
> When running PV guests some of the UV memory needs to be allocated
> with > 31 bit addresses which means tests with PV guests will always
> need a lot more memory than other tests.
> Additionally facilities nr 158 and sclp.sief2 need to be available.
> 
> Let's add a function that checks for these requirements and prints a
> helpful skip message.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

with Claudios renaming suggestion:
Reviewed-by: Nico Boehr <nrb@linux.ibm.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function
  2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function Janosch Frank
@ 2023-05-31 13:36   ` Nico Boehr
  0 siblings, 0 replies; 19+ messages in thread
From: Nico Boehr @ 2023-05-31 13:36 UTC (permalink / raw)
  To: Janosch Frank, kvm; +Cc: linux-s390, imbrenda, thuth, david

Quoting Janosch Frank (2023-04-21 13:36:41)
> PV related validities are in the 0x20** range but the last byte might
> be implementation specific, so everytime we check for a UV validity we
> need to mask the last byte.
> 
> Let's add a function that checks for a UV validity and returns a
> boolean.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
> ---
>  lib/s390x/uv.h | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/lib/s390x/uv.h b/lib/s390x/uv.h
> index 5fe29bda..78b979b7 100644
> --- a/lib/s390x/uv.h
> +++ b/lib/s390x/uv.h
> @@ -35,4 +35,11 @@ static inline void uv_setup_asces(void)
>         lctlg(13, asce);
>  }
>  
> +static inline bool uv_validity_check(struct vm *vm)
> +{
> +       uint16_t vir = sie_get_validity(vm);
> +
> +       return vm->sblk->icptcode == ICPT_VALIDITY && (vir & 0xff00) == 0x2000;
> +}
> +

I noticed a small issue with this. If no intercept occurs, we sie_get_validity()
will be called which will assert() when there's none.

Please consider the following fixup (broken whitespace ahead):

 static inline bool uv_validity_check(struct vm *vm)
 {
-       uint16_t vir = sie_get_validity(vm);
+       uint16_t vir;

-       return vm->sblk->icptcode == ICPT_VALIDITY && (vir & 0xff00) == 0x2000;
+       /* must not use sie_get_validity() when there's no validity */
+       if (vm->sblk->icptcode != ICPT_VALIDITY)
+               return false;
+       vir = sie_get_validity(vm);
+
+       return (vir & 0xff00) == 0x2000;
 }


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2023-05-31 13:36 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-21 11:36 [kvm-unit-tests PATCH v3 0/7] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 1/7] lib: s390x: uv: Introduce UV validity function Janosch Frank
2023-05-31 13:36   ` Nico Boehr
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 2/7] lib: s390x: uv: Add intercept data check library function Janosch Frank
2023-04-21 14:10   ` Claudio Imbrenda
2023-04-26 11:22   ` Nico Boehr
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 3/7] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
2023-04-21 14:10   ` Claudio Imbrenda
2023-04-26 11:24   ` Nico Boehr
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 4/7] lib: s390x: uv: Add pv guest requirement check function Janosch Frank
2023-04-21 14:13   ` Claudio Imbrenda
2023-04-24  8:26     ` Janosch Frank
2023-04-26 11:27   ` Nico Boehr
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 5/7] s390x: pv: Add sie entry intercept and validity test Janosch Frank
2023-04-21 15:23   ` Claudio Imbrenda
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 6/7] s390x: pv: Add IPL reset tests Janosch Frank
2023-04-21 15:32   ` Claudio Imbrenda
2023-04-21 11:36 ` [kvm-unit-tests PATCH v3 7/7] s390x: pv-diags: Add the test to unittests.conf Janosch Frank
2023-04-21 14:10   ` Claudio Imbrenda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox