mbox series

[kvm-unit-tests,v6,0/2] Add specification exception tests

Message ID 20220826161112.3786131-1-scgl@linux.ibm.com (mailing list archive)
Headers show
Series Add specification exception tests | expand

Message

Janis Schoetterl-Glausch Aug. 26, 2022, 4:11 p.m. UTC
Test that specification exceptions cause the correct interruption code
during both normal and transactional execution.

TCG fails the tests setting an invalid PSW bit.
I had a look at how best to fix it, but where best to check for early
PSW exceptions was not immediately clear to me. Ideas welcome.

v5 -> b6
	rebased onto master
	comments and style changes

v4 -> v5
	add lpsw with invalid bit 12 test
		TCG fails as with lpswe but must also invert bit 12
	update copyright statement
	add comments
	cleanups and style fixes

v3 -> v4
	remove iterations argument in order to simplify the code
		for manual performance testing adding a for loop is easy
	move report out of fixup_invalid_psw
	simplify/improve readability of triggers
	use positive error values

v2 -> v3
	remove non-ascii symbol
	clean up load_psw
	fix nits

v1 -> v2
	Add license and test description
	Split test patch into normal test and transactional execution test
	Add comments to
		invalid PSW fixup function
		with_transaction
	Rename some variables/functions
	Pass mask as single parameter to asm
	Get rid of report_info_if macro
	Introduce report_pass/fail and use them

Janis Schoetterl-Glausch (2):
  s390x: Add specification exception test
  s390x: Test specification exceptions during transaction

 s390x/Makefile           |   1 +
 lib/s390x/asm/arch_def.h |   6 +
 s390x/spec_ex.c          | 383 +++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg      |   3 +
 4 files changed, 393 insertions(+)
 create mode 100644 s390x/spec_ex.c

Range-diff against v5:
1:  fd9780d8 ! 1:  bbfb5d40 s390x: Add specification exception test
    @@ lib/s390x/asm/arch_def.h: struct psw {
     +	uint32_t	addr;
     +};
     +
    - #define AS_PRIM				0
    - #define AS_ACCR				1
    - #define AS_SECN				2
    + struct cpu {
    + 	struct lowcore *lowcore;
    + 	uint64_t *stack;
     
      ## s390x/spec_ex.c (new) ##
     @@
    @@ s390x/spec_ex.c (new)
     + */
     +#include <stdlib.h>
     +#include <libcflat.h>
    ++#include <bitops.h>
     +#include <asm/interrupt.h>
     +
    ++/* toggled to signal occurrence of invalid psw fixup */
     +static bool invalid_psw_expected;
     +static struct psw expected_psw;
     +static struct psw invalid_psw;
    @@ s390x/spec_ex.c (new)
     + * 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)
    ++static void fixup_invalid_psw(struct stack_frame_int *stack)
     +{
     +	/* signal occurrence of invalid psw fixup */
     +	invalid_psw_expected = false;
    @@ s390x/spec_ex.c (new)
     +{
     +	uint64_t scratch;
     +
    ++	/*
    ++	 * The fixup psw is current psw with the instruction address replaced by
    ++	 * the address of the nop following the instruction loading the new psw.
    ++	 */
     +	fixup_psw.mask = extract_psw_mask();
     +	asm volatile ( "larl	%[scratch],0f\n"
    -+		"	stg	%[scratch],%[addr]\n"
    ++		"	stg	%[scratch],%[fixup_addr]\n"
     +		"	lpswe	%[psw]\n"
     +		"0:	nop\n"
    -+		: [scratch] "=&d"(scratch),
    -+		  [addr] "=&T"(fixup_psw.addr)
    -+		: [psw] "Q"(psw)
    ++		: [scratch] "=&d" (scratch),
    ++		  [fixup_addr] "=&T" (fixup_psw.addr)
    ++		: [psw] "Q" (psw)
     +		: "cc", "memory"
     +	);
     +}
    @@ s390x/spec_ex.c (new)
     +
     +	fixup_psw.mask = extract_psw_mask();
     +	asm volatile ( "larl	%[scratch],0f\n"
    -+		"	stg	%[scratch],%[addr]\n"
    ++		"	stg	%[scratch],%[fixup_addr]\n"
     +		"	lpsw	%[psw]\n"
     +		"0:	nop\n"
    -+		: [scratch] "=&d"(scratch),
    -+		  [addr] "=&T"(fixup_psw.addr)
    -+		: [psw] "Q"(psw)
    ++		: [scratch] "=&d" (scratch),
    ++		  [fixup_addr] "=&T" (fixup_psw.addr)
    ++		: [psw] "Q" (psw)
     +		: "cc", "memory"
     +	);
     +}
    @@ s390x/spec_ex.c (new)
     +
     +static int check_invalid_psw(void)
     +{
    -+	/* toggled to signal occurrence of invalid psw fixup */
     +	if (!invalid_psw_expected) {
     +		if (expected_psw.mask == invalid_psw.mask &&
     +		    expected_psw.addr == invalid_psw.addr)
    @@ s390x/spec_ex.c (new)
     +	return 1;
     +}
     +
    ++/* For normal PSWs bit 12 has to be 0 to be a valid PSW*/
     +static int psw_bit_12_is_1(void)
     +{
    -+	struct psw invalid = { .mask = 0x0008000000000000, .addr = 0x00000000deadbeee};
    ++	struct psw invalid = {
    ++		.mask = BIT(63 - 12),
    ++		.addr = 0x00000000deadbeee
    ++	};
     +
     +	expect_invalid_psw(invalid);
     +	load_psw(invalid);
     +	return check_invalid_psw();
     +}
     +
    ++/* A short PSW needs to have bit 12 set to be valid. */
     +static int short_psw_bit_12_is_0(void)
     +{
    -+	struct short_psw short_invalid = { .mask = 0x00000000, .addr = 0xdeadbeee};
    ++	struct short_psw short_invalid = {
    ++		.mask = 0x0,
    ++		.addr = 0xdeadbeee
    ++	};
     +
     +	/*
     +	 * lpsw may optionally check bit 12 before loading the new psw
    @@ s390x/spec_ex.c (new)
     +	uint32_t words[5] __attribute__((aligned(16)));
     +	uint32_t (*bad_aligned)[4] = (uint32_t (*)[4])&words[1];
     +
    ++	/* LOAD PAIR FROM QUADWORD (LPQ) requires quadword alignment */
     +	asm volatile ("lpq %%r6,%[bad]"
    -+		      : : [bad] "T"(*bad_aligned)
    ++		      : : [bad] "T" (*bad_aligned)
     +		      : "%r6", "%r7"
     +	);
     +	return 0;
    @@ s390x/spec_ex.c (new)
     +	uint64_t quad[2] __attribute__((aligned(16))) = {0};
     +
     +	asm volatile (".insn	rxy,0xe3000000008f,%%r7,%[quad]" /* lpq %%r7,%[quad] */
    -+		      : : [quad] "T"(quad)
    ++		      : : [quad] "T" (quad)
     +		      : "%r7", "%r8"
     +	);
     +	return 0;
    @@ s390x/spec_ex.c (new)
     +struct spec_ex_trigger {
     +	const char *name;
     +	int (*func)(void);
    -+	void (*fixup)(void);
    ++	void (*fixup)(struct stack_frame_int *stack);
     +};
     +
     +/* List of all tests to execute */
2:  c14092a3 ! 2:  0f19be7d s390x: Test specification exceptions during transaction
    @@ Commit message
         Signed-off-by: Janis Schoetterl-Glausch <scgl@linux.ibm.com>
     
      ## lib/s390x/asm/arch_def.h ##
    -@@ lib/s390x/asm/arch_def.h: struct short_psw {
    +@@ lib/s390x/asm/arch_def.h: struct cpu {
      #define PSW_MASK_BA			0x0000000080000000UL
      #define PSW_MASK_64			(PSW_MASK_BA | PSW_MASK_EA)
      
    @@ s390x/spec_ex.c
      #include <stdlib.h>
     +#include <htmintrin.h>
      #include <libcflat.h>
    + #include <bitops.h>
     +#include <asm/barrier.h>
      #include <asm/interrupt.h>
     +#include <asm/facility.h>
      
    + /* toggled to signal occurrence of invalid psw fixup */
      static bool invalid_psw_expected;
    - static struct psw expected_psw;
     @@ s390x/spec_ex.c: static int not_even(void)
      /*
       * Harness for specification exception testing.
    @@ s390x/spec_ex.c: static int not_even(void)
      	const char *name;
      	int (*func)(void);
     +	bool transactable;
    - 	void (*fixup)(void);
    + 	void (*fixup)(struct stack_frame_int *stack);
      };
      
      /* List of all tests to execute */

base-commit: 7362976db651a2142ec64b5cea2029ab77a5b157