From: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
To: Thomas Huth <thuth@redhat.com>, Janosch Frank <frankja@linux.ibm.com>
Cc: Janis Schoetterl-Glausch <scgl@linux.ibm.com>,
Claudio Imbrenda <imbrenda@linux.ibm.com>,
David Hildenbrand <david@redhat.com>,
kvm@vger.kernel.org, linux-s390@vger.kernel.org
Subject: [kvm-unit-tests PATCH v3 1/2] s390x: Add specification exception test
Date: Fri, 22 Oct 2021 14:01:55 +0200 [thread overview]
Message-ID: <20211022120156.281567-2-scgl@linux.ibm.com> (raw)
In-Reply-To: <20211022120156.281567-1-scgl@linux.ibm.com>
Generate specification exceptions and check that they occur.
With the iterations argument one can check if specification
exception interpretation occurs, e.g. by using a high value and
checking that the debugfs counters are substantially lower.
The argument is also useful for estimating the performance benefit
of interpretation.
Signed-off-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
---
s390x/Makefile | 1 +
s390x/spec_ex.c | 181 ++++++++++++++++++++++++++++++++++++++++++++
s390x/unittests.cfg | 3 +
3 files changed, 185 insertions(+)
create mode 100644 s390x/spec_ex.c
diff --git a/s390x/Makefile b/s390x/Makefile
index d18b08b..3e42784 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -24,6 +24,7 @@ tests += $(TEST_DIR)/mvpg.elf
tests += $(TEST_DIR)/uv-host.elf
tests += $(TEST_DIR)/edat.elf
tests += $(TEST_DIR)/mvpg-sie.elf
+tests += $(TEST_DIR)/spec_ex.elf
tests_binary = $(patsubst %.elf,%.bin,$(tests))
ifneq ($(HOST_KEY_DOCUMENT),)
diff --git a/s390x/spec_ex.c b/s390x/spec_ex.c
new file mode 100644
index 0000000..ec3322a
--- /dev/null
+++ b/s390x/spec_ex.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright IBM Corp. 2021
+ *
+ * Specification exception test.
+ * Tests that specification exceptions occur when expected.
+ */
+#include <stdlib.h>
+#include <libcflat.h>
+#include <asm/interrupt.h>
+#include <asm/facility.h>
+
+static struct lowcore *lc = (struct lowcore *) 0;
+
+static bool expect_invalid_psw;
+static struct psw expected_psw;
+static struct psw fixup_psw;
+
+/* The standard program exception handler cannot deal with invalid old PSWs,
+ * especially not invalid instruction addresses, as in that case one cannot
+ * find the instruction following the faulting one from the old PSW.
+ * The PSW to return to is set by load_psw.
+ */
+static void fixup_invalid_psw(void)
+{
+ if (expect_invalid_psw) {
+ report(expected_psw.mask == lc->pgm_old_psw.mask
+ && expected_psw.addr == lc->pgm_old_psw.addr,
+ "Invalid program new PSW as expected");
+ expect_invalid_psw = false;
+ }
+ lc->pgm_old_psw = fixup_psw;
+}
+
+/* Load possibly invalid psw, but setup fixup_psw before,
+ * so that *fixup_invalid_psw() can bring us back onto the right track.
+ */
+static void load_psw(struct psw psw)
+{
+ uint64_t scratch;
+
+ fixup_psw.mask = extract_psw_mask();
+ asm volatile (
+ " larl %[scratch],nop%=\n"
+ " stg %[scratch],%[addr]\n"
+ " lpswe %[psw]\n"
+ "nop%=: nop\n"
+ : [scratch] "=&r"(scratch),
+ [addr] "=&T"(fixup_psw.addr)
+ : [psw] "Q"(psw)
+ : "cc", "memory"
+ );
+}
+
+static void psw_bit_12_is_1(void)
+{
+ expected_psw.mask = 0x0008000000000000;
+ expected_psw.addr = 0x00000000deadbeee;
+ expect_invalid_psw = true;
+ load_psw(expected_psw);
+}
+
+static void bad_alignment(void)
+{
+ uint32_t words[5] = {0, 0, 0};
+ uint32_t (*bad_aligned)[4];
+
+ register uint64_t r1 asm("6");
+ register uint64_t r2 asm("7");
+ if (((uintptr_t)&words[0]) & 0xf)
+ bad_aligned = (uint32_t (*)[4])&words[0];
+ else
+ bad_aligned = (uint32_t (*)[4])&words[1];
+ asm volatile ("lpq %0,%2"
+ : "=r"(r1), "=r"(r2)
+ : "T"(*bad_aligned)
+ );
+}
+
+static void not_even(void)
+{
+ uint64_t quad[2];
+
+ register uint64_t r1 asm("7");
+ register uint64_t r2 asm("8");
+ asm volatile (".insn rxy,0xe3000000008f,%0,%2" //lpq %0,%2
+ : "=r"(r1), "=r"(r2)
+ : "T"(quad)
+ );
+}
+
+struct spec_ex_trigger {
+ const char *name;
+ void (*func)(void);
+ void (*fixup)(void);
+};
+
+static const struct spec_ex_trigger spec_ex_triggers[] = {
+ { "psw_bit_12_is_1", &psw_bit_12_is_1, &fixup_invalid_psw},
+ { "bad_alignment", &bad_alignment, NULL},
+ { "not_even", ¬_even, NULL},
+ { NULL, NULL, NULL},
+};
+
+struct args {
+ uint64_t iterations;
+};
+
+static void test_spec_ex(struct args *args,
+ const struct spec_ex_trigger *trigger)
+{
+ uint16_t expected_pgm = PGM_INT_CODE_SPECIFICATION;
+ uint16_t pgm;
+ unsigned int i;
+
+ for (i = 0; i < args->iterations; i++) {
+ expect_pgm_int();
+ register_pgm_cleanup_func(trigger->fixup);
+ trigger->func();
+ register_pgm_cleanup_func(NULL);
+ pgm = clear_pgm_int();
+ if (pgm != expected_pgm) {
+ report_fail("Program interrupt: expected(%d) == received(%d)",
+ expected_pgm,
+ pgm);
+ return;
+ }
+ }
+ report_pass("Program interrupt: always expected(%d) == received(%d)",
+ expected_pgm,
+ expected_pgm);
+}
+
+static struct args parse_args(int argc, char **argv)
+{
+ struct args args = {
+ .iterations = 1,
+ };
+ unsigned int i;
+ long arg;
+ bool no_arg;
+ char *end;
+
+ for (i = 1; i < argc; i++) {
+ no_arg = true;
+ if (i < argc - 1) {
+ no_arg = *argv[i + 1] == '\0';
+ arg = strtol(argv[i + 1], &end, 10);
+ no_arg |= *end != '\0';
+ no_arg |= arg < 0;
+ }
+
+ if (!strcmp("--iterations", argv[i])) {
+ if (no_arg)
+ report_abort("--iterations needs a positive parameter");
+ args.iterations = arg;
+ ++i;
+ } else {
+ report_abort("Unsupported parameter '%s'",
+ argv[i]);
+ }
+ }
+ return args;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int i;
+
+ struct args args = parse_args(argc, argv);
+
+ report_prefix_push("specification exception");
+ for (i = 0; spec_ex_triggers[i].name; i++) {
+ report_prefix_push(spec_ex_triggers[i].name);
+ test_spec_ex(&args, &spec_ex_triggers[i]);
+ report_prefix_pop();
+ }
+ report_prefix_pop();
+
+ return report_summary();
+}
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 9e1802f..5f43d52 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -109,3 +109,6 @@ file = edat.elf
[mvpg-sie]
file = mvpg-sie.elf
+
+[spec_ex]
+file = spec_ex.elf
--
2.31.1
next prev parent reply other threads:[~2021-10-22 12:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-22 12:01 [kvm-unit-tests PATCH v3 0/2] Add specification exception tests Janis Schoetterl-Glausch
2021-10-22 12:01 ` Janis Schoetterl-Glausch [this message]
2021-10-25 17:17 ` [kvm-unit-tests PATCH v3 1/2] s390x: Add specification exception test Claudio Imbrenda
2021-10-26 12:00 ` Janis Schoetterl-Glausch
2021-10-26 13:41 ` Claudio Imbrenda
2021-10-27 10:00 ` Janis Schoetterl-Glausch
2021-10-27 12:08 ` Thomas Huth
2021-10-22 12:01 ` [kvm-unit-tests PATCH v3 2/2] s390x: Test specification exceptions during transaction Janis Schoetterl-Glausch
2021-10-25 17:30 ` Claudio Imbrenda
2021-10-25 18:28 ` Christian Borntraeger
2021-10-26 14:22 ` Janis Schoetterl-Glausch
2021-10-26 14:55 ` Claudio Imbrenda
2021-10-27 10:05 ` Janis Schoetterl-Glausch
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211022120156.281567-2-scgl@linux.ibm.com \
--to=scgl@linux.ibm.com \
--cc=david@redhat.com \
--cc=frankja@linux.ibm.com \
--cc=imbrenda@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.