All of lore.kernel.org
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests
@ 2023-06-19  8:33 Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling Janosch Frank
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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

v5:
	- Added "lib: s390x: uv: Introduce UV validity function"
	- Added "groups = pv-host" to unittests.cfg entries
	- Added pv-icptcode wrong vm handle test
	- Smaller fixes due to review
	- Added revs/acks
v4:
	- Renamed uv_guest_requirement_checks() to uv_host_requirement_checks()
	- Now using report_prefix_pushf()
	- Smaller fixes due to review
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 (8):
  lib: s390x: sie: Fix sie_get_validity() no validity handling
  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 host 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/sie.c                               |   8 +-
 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                           | 376 ++++++++++++++++++
 s390x/pv-ipl.c                                | 143 +++++++
 s390x/snippets/asm/icpt-loop.S                |  15 +
 s390x/snippets/asm/loop.S                     |  13 +
 .../{snippet-pv-diag-288.S => pv-diag-288.S}  |   0
 s390x/snippets/asm/pv-diag-308.S              |  51 +++
 .../{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-112.S              |  81 ++++
 s390x/snippets/asm/pv-icpt-vir-timing.S       |  21 +
 s390x/unittests.cfg                           |  16 +
 18 files changed, 841 insertions(+), 43 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%)
 create mode 100644 s390x/snippets/asm/pv-diag-308.S
 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-112.S
 create mode 100644 s390x/snippets/asm/pv-icpt-vir-timing.S

-- 
2.34.1


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

* [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-20 15:12   ` Nico Boehr
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 2/8] lib: s390x: uv: Introduce UV validity function Janosch Frank
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

Rather than asserting, we can return a value that's designated as a
programming only value to indicate that there has been no validity.

The SIE instruction will never write 0xffff as a validity code so
let's just use that constant.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 lib/s390x/sie.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/s390x/sie.c b/lib/s390x/sie.c
index 9241b4b4..b44febde 100644
--- a/lib/s390x/sie.c
+++ b/lib/s390x/sie.c
@@ -23,7 +23,13 @@ void sie_expect_validity(struct vm *vm)
 
 uint16_t sie_get_validity(struct vm *vm)
 {
-	assert(vm->sblk->icptcode == ICPT_VALIDITY);
+	/*
+	 * 0xffff will never be returned by SIE, so we can indicate a
+	 * missing validity via this value.
+	 */
+	if (vm->sblk->icptcode != ICPT_VALIDITY)
+		return 0xffff;
+
 	return vm->sblk->ipb >> 16;
 }
 
-- 
2.34.1


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

* [kvm-unit-tests PATCH v5 2/8] lib: s390x: uv: Introduce UV validity function
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 3/8] lib: s390x: uv: Add intercept data check library function Janosch Frank
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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] 11+ messages in thread

* [kvm-unit-tests PATCH v5 3/8] lib: s390x: uv: Add intercept data check library function
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 2/8] lib: s390x: uv: Introduce UV validity function Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 4/8] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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 */
-- 
2.34.1


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

* [kvm-unit-tests PATCH v5 4/8] s390x: pv-diags: Drop snippet from snippet names
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (2 preceding siblings ...)
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 3/8] lib: s390x: uv: Add intercept data check library function Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 5/8] lib: s390x: uv: Add pv host requirement check function Janosch Frank
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

It's a bit redundant.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Acked-by: Nico Boehr <nrb@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] 11+ messages in thread

* [kvm-unit-tests PATCH v5 5/8] lib: s390x: uv: Add pv host requirement check function
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (3 preceding siblings ...)
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 4/8] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-20 14:13   ` Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 6/8] s390x: pv: Add sie entry intercept and validity test Janosch Frank
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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>
Reviewed-by: Nico Boehr <nrb@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..4ccb7bde 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_host_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..286933ca 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_host_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..3193ad99 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_host_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] 11+ messages in thread

* [kvm-unit-tests PATCH v5 6/8] s390x: pv: Add sie entry intercept and validity test
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (4 preceding siblings ...)
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 5/8] lib: s390x: uv: Add pv host requirement check function Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 7/8] s390x: pv: Add IPL reset tests Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 8/8] s390x: pv-diags: Add the test to unittests.conf Janosch Frank
  7 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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>
Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
---
 s390x/Makefile                          |   5 +
 s390x/pv-icptcode.c                     | 376 ++++++++++++++++++++++++
 s390x/snippets/asm/icpt-loop.S          |  15 +
 s390x/snippets/asm/loop.S               |  13 +
 s390x/snippets/asm/pv-icpt-112.S        |  81 +++++
 s390x/snippets/asm/pv-icpt-vir-timing.S |  21 ++
 s390x/unittests.cfg                     |   6 +
 7 files changed, 517 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-112.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..d7c47d6f
--- /dev/null
+++ b/s390x/pv-icptcode.c
@@ -0,0 +1,376 @@
+/* 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, tmp;
+
+	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), "spt done");
+	stck(&time_exit);
+	tmp = vm.sblk->cputm;
+	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 = tmp;
+
+	/*
+	 * 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");
+	vm.sblk->cputm = tmp;
+
+	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);
+
+	smp_cpu_setup(1, psw);
+	sie_expect_validity(&vm);
+	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), "switched cpu handle");
+	vm.sblk->pv_handle_cpu = vm.uv.vcpu_handle;
+
+	vm.sblk->pv_handle_config = vm2.uv.vm_handle;
+	sie_expect_validity(&vm);
+	sie(&vm);
+	report(uv_validity_check(&vm), "switched configuration handle");
+	vm.sblk->pv_handle_config = vm.uv.vm_handle;
+
+	/* Destroy the second vm, since we don't need it for further tests */
+	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);
+	sie(&vm);
+	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)
+{
+	uint32_t *ptr = 0;
+
+	report_prefix_pushf("0x%lx", prefix);
+	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_host_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-112.S b/s390x/snippets/asm/pv-icpt-112.S
new file mode 100644
index 00000000..d9545fff
--- /dev/null
+++ b/s390x/snippets/asm/pv-icpt-112.S
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Intercept 112 PV snippet
+ *
+ * We setup and share a prefix at 0x0 and 0x8000 which the hypervisor
+ * test will try to export and then execute a SIE entry which
+ * should result in a 112 SIE intercept.
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+#include <asm/asm-offsets.h>
+
+.section .text
+xgr	%r0, %r0
+xgr	%r1, %r1
+
+/* Let's tell the hypervisor we're ready to start */
+diag	0,0,0x44
+
+/*
+ * Hypervisor will export the lowcore and try a SIE entry which should
+ * result in a 112. It will then import the lowcore again and we
+ * should continue with the code below.
+ */
+
+/* Share the lowcore */
+larl	%r1, share
+.insn rrf,0xB9A40000,0,1,0,0
+xgr	%r1, %r1
+
+/*  Let's tell the hypervisor we're ready to start shared testing */
+diag	0,0,0x44
+
+/* Host: icpt:  PV instruction diag 0x44 */
+/* Host: icpt:  112 */
+
+/* Copy the invalid PGM new PSW to the new lowcore */
+larl	%r1, prfx
+l	%r2, 0(%r1)
+mvc     GEN_LC_PGM_NEW_PSW(16, %r2), GEN_LC_PGM_NEW_PSW(%r0)
+
+/* Change the prefix to 0x8000 and re-try */
+xgr	%r1, %r1
+xgr	%r2, %r2
+larl	%r2, prfx
+spx	0(%r2)
+
+/* Host: icpt:  PV instruction notification SPX*/
+/* Host: icpt:  112 */
+
+/* Share the new lowcore */
+larl	%r3, share_addr
+stg	%r2, 0(%r3)
+larl	%r2, share
+.insn rrf,0xB9A40000,0,2,0,0
+
+/* Let's tell the hypervisor we're ready to start shared testing */
+diag	0,0,0x44
+
+/* Host: icpt:  PV instruction diag 0x44 */
+/* Host: icpt:  112 */
+
+/* Test re-entry */
+lghi	%r1, 42
+diag	1,0,0x9c
+
+/* Host: icpt:  PV instruction diag 0x9c */
+
+.align 8
+share:
+	.quad 0x0030100000000000
+	.quad 0x0, 0x0, 0x0
+share_addr:
+	.quad 0x0
+	.quad 0x0
+.align 4
+prfx:
+	.long 0x00008000
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..939134a2
--- /dev/null
+++ b/s390x/snippets/asm/pv-icpt-vir-timing.S
@@ -0,0 +1,21 @@
+/* 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
+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..df25b483 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -218,3 +218,9 @@ extra_params = -append '--parallel'
 
 [execute]
 file = ex.elf
+
+[pv-icptcode]
+file = pv-icptcode.elf
+smp = 3
+groups = pv-host
+extra_params = -m 2200
-- 
2.34.1


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

* [kvm-unit-tests PATCH v5 7/8] s390x: pv: Add IPL reset tests
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (5 preceding siblings ...)
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 6/8] s390x: pv: Add sie entry intercept and validity test Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 8/8] s390x: pv-diags: Add the test to unittests.conf Janosch Frank
  7 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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>
Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
---
 s390x/Makefile                   |   2 +
 s390x/pv-ipl.c                   | 143 +++++++++++++++++++++++++++++++
 s390x/snippets/asm/pv-diag-308.S |  51 +++++++++++
 s390x/unittests.cfg              |   5 ++
 4 files changed, 201 insertions(+)
 create mode 100644 s390x/pv-ipl.c
 create mode 100644 s390x/snippets/asm/pv-diag-308.S

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..cc46e7f7
--- /dev/null
+++ b/s390x/pv-ipl.c
@@ -0,0 +1,143 @@
+/* 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;
+	int cc;
+
+	report_prefix_pushf("subcode %d", subcode);
+	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 by
+	 * putting the value 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_host_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/snippets/asm/pv-diag-308.S b/s390x/snippets/asm/pv-diag-308.S
new file mode 100644
index 00000000..70aea589
--- /dev/null
+++ b/s390x/snippets/asm/pv-diag-308.S
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Diagnose 0x308 snippet used for PV IPL and reset testing
+ *
+ * Copyright (c) 2023 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.ibm.com>
+ */
+#include <asm/asm-offsets.h>
+.section .text
+
+/*
+ * Entry
+ * Execute the diag500 which will set the diag 308 subcode in gr2
+ */
+diag	0, 0, 0x500
+
+/*
+ * A valid PGM new PSW can be a real problem since we never fall out
+ * of SIE and therefore effectively loop forever. 0 is a valid PSW
+ * therefore we re-use the reset_psw as this has the short PSW
+ * bit set which is invalid for a long PSW like the exception new
+ * PSWs.
+ *
+ * For subcode 0/1 there are no PGMs to consider.
+ */
+lgrl   %r5, reset_psw
+stg    %r5, GEN_LC_PGM_NEW_PSW
+
+/* Set up the reset psw at 0x0 */
+lgrl	%r5, reset_psw
+larl	%r6, done
+ogr	%r5, %r6
+stg	%r5, 0
+
+/* Diag 308, subcode is in gr2 */
+diag	%r0, %r2, 0x308
+
+/* Should never be executed because of the reset PSW */
+diag	0, 0, 0x44
+
+/* Pass on a special value indicating success */
+done:
+lghi	%r1, 42
+diag	%r1, 0, 0x9c
+
+
+	.align	8
+reset_psw:
+	.quad	0x0008000180000000
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index df25b483..26bab34a 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -224,3 +224,8 @@ file = pv-icptcode.elf
 smp = 3
 groups = pv-host
 extra_params = -m 2200
+
+[pv-ipl]
+file = pv-ipl.elf
+groups = pv-host
+extra_params = -m 2200
-- 
2.34.1


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

* [kvm-unit-tests PATCH v5 8/8] s390x: pv-diags: Add the test to unittests.conf
  2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
                   ` (6 preceding siblings ...)
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 7/8] s390x: pv: Add IPL reset tests Janosch Frank
@ 2023-06-19  8:33 ` Janosch Frank
  7 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-19  8:33 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

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: Nico Boehr <nrb@linux.ibm.com>
---
 s390x/unittests.cfg | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 26bab34a..49b3cee4 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -229,3 +229,8 @@ extra_params = -m 2200
 file = pv-ipl.elf
 groups = pv-host
 extra_params = -m 2200
+
+[pv-diags]
+file = pv-diags.elf
+groups = pv-host
+extra_params = -m 2200
-- 
2.34.1


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

* Re: [kvm-unit-tests PATCH v5 5/8] lib: s390x: uv: Add pv host requirement check function
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 5/8] lib: s390x: uv: Add pv host requirement check function Janosch Frank
@ 2023-06-20 14:13   ` Janosch Frank
  0 siblings, 0 replies; 11+ messages in thread
From: Janosch Frank @ 2023-06-20 14:13 UTC (permalink / raw)
  To: kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg, nrb

On 6/19/23 10:33, Janosch Frank 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>
> Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
[...]
> +bool uv_host_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);

I've just replaced the 1024 divisions with SZ_1M i nthe second series. 
Feel free to do that here when picking if I don't need to send a new 
version.

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

* Re: [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling
  2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling Janosch Frank
@ 2023-06-20 15:12   ` Nico Boehr
  0 siblings, 0 replies; 11+ messages in thread
From: Nico Boehr @ 2023-06-20 15:12 UTC (permalink / raw)
  To: Janosch Frank, kvm; +Cc: linux-s390, imbrenda, thuth, david, nsg

Quoting Janosch Frank (2023-06-19 10:33:22)
> Rather than asserting, we can return a value that's designated as a
> programming only value to indicate that there has been no validity.
> 
> The SIE instruction will never write 0xffff as a validity code so
> let's just use that constant.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>

That's a good solution.

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

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

end of thread, other threads:[~2023-06-20 15:12 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-19  8:33 [kvm-unit-tests PATCH v5 0/8] s390x: Add PV SIE intercepts and ipl tests Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 1/8] lib: s390x: sie: Fix sie_get_validity() no validity handling Janosch Frank
2023-06-20 15:12   ` Nico Boehr
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 2/8] lib: s390x: uv: Introduce UV validity function Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 3/8] lib: s390x: uv: Add intercept data check library function Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 4/8] s390x: pv-diags: Drop snippet from snippet names Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 5/8] lib: s390x: uv: Add pv host requirement check function Janosch Frank
2023-06-20 14:13   ` Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 6/8] s390x: pv: Add sie entry intercept and validity test Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 7/8] s390x: pv: Add IPL reset tests Janosch Frank
2023-06-19  8:33 ` [kvm-unit-tests PATCH v5 8/8] s390x: pv-diags: Add the test to unittests.conf Janosch Frank

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.