kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v1 0/2] s390x: Add misaligned instruction tests
@ 2023-02-15 17:18 Nina Schoetterl-Glausch
  2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW Nina Schoetterl-Glausch
  2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 2/2] s390x/spec_ex: Add test of EXECUTE with odd target address Nina Schoetterl-Glausch
  0 siblings, 2 replies; 6+ messages in thread
From: Nina Schoetterl-Glausch @ 2023-02-15 17:18 UTC (permalink / raw)
  To: Claudio Imbrenda, Janosch Frank, Thomas Huth
  Cc: Nina Schoetterl-Glausch, David Hildenbrand, kvm, linux-s390

Instructions on s390 must be halfword aligned.
Add two tests for that.
These currently fail when using TCG.

Nina Schoetterl-Glausch (2):
  s390x/spec_ex: Add test introducing odd address into PSW
  s390x/spec_ex: Add test of EXECUTE with odd target address

 s390x/spec_ex.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 94 insertions(+), 4 deletions(-)


base-commit: 7e9737739f738c9a2e555947082a59edbc5b49b9
-- 
2.36.1


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

* [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW
  2023-02-15 17:18 [kvm-unit-tests PATCH v1 0/2] s390x: Add misaligned instruction tests Nina Schoetterl-Glausch
@ 2023-02-15 17:18 ` Nina Schoetterl-Glausch
  2023-02-17 11:05   ` Claudio Imbrenda
  2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 2/2] s390x/spec_ex: Add test of EXECUTE with odd target address Nina Schoetterl-Glausch
  1 sibling, 1 reply; 6+ messages in thread
From: Nina Schoetterl-Glausch @ 2023-02-15 17:18 UTC (permalink / raw)
  To: Thomas Huth, Janosch Frank, Claudio Imbrenda
  Cc: Nina Schoetterl-Glausch, David Hildenbrand, kvm, linux-s390

Instructions on s390 must be halfword aligned.
Introducing an odd instruction address into the PSW leads to a
specification exception when attempting to execute the instruction at
the odd address.
Add a test for this.

Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
---
 s390x/spec_ex.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 69 insertions(+), 4 deletions(-)

diff --git a/s390x/spec_ex.c b/s390x/spec_ex.c
index 42ecaed3..b6764677 100644
--- a/s390x/spec_ex.c
+++ b/s390x/spec_ex.c
@@ -44,9 +44,10 @@ static void fixup_invalid_psw(struct stack_frame_int *stack)
 /*
  * Load possibly invalid psw, but setup fixup_psw before,
  * so that fixup_invalid_psw() can bring us back onto the right track.
+ * The provided argument is loaded into register 1.
  * Also acts as compiler barrier, -> none required in expect/check_invalid_psw
  */
-static void load_psw(struct psw psw)
+static void load_psw_with_arg(struct psw psw, uint64_t arg)
 {
 	uint64_t scratch;
 
@@ -57,15 +58,22 @@ static void load_psw(struct psw psw)
 	fixup_psw.mask = extract_psw_mask();
 	asm volatile ( "larl	%[scratch],0f\n"
 		"	stg	%[scratch],%[fixup_addr]\n"
+		"	lgr	%%r1,%[arg]\n"
 		"	lpswe	%[psw]\n"
 		"0:	nop\n"
 		: [scratch] "=&d" (scratch),
 		  [fixup_addr] "=&T" (fixup_psw.addr)
-		: [psw] "Q" (psw)
-		: "cc", "memory"
+		: [psw] "Q" (psw),
+		  [arg] "d" (arg)
+		: "cc", "memory", "%r1"
 	);
 }
 
+static void load_psw(struct psw psw)
+{
+	load_psw_with_arg(psw, 0);
+}
+
 static void load_short_psw(struct short_psw psw)
 {
 	uint64_t scratch;
@@ -88,12 +96,18 @@ static void expect_invalid_psw(struct psw psw)
 	invalid_psw_expected = true;
 }
 
+static void clear_invalid_psw(void)
+{
+	expected_psw = (struct psw){0};
+	invalid_psw_expected = false;
+}
+
 static int check_invalid_psw(void)
 {
 	/* Since the fixup sets this to false we check for false here. */
 	if (!invalid_psw_expected) {
 		if (expected_psw.mask == invalid_psw.mask &&
-		    expected_psw.addr == invalid_psw.addr)
+		    expected_psw.addr == invalid_psw.addr - lowcore.pgm_int_id)
 			return 0;
 		report_fail("Wrong invalid PSW");
 	} else {
@@ -115,6 +129,56 @@ static int psw_bit_12_is_1(void)
 	return check_invalid_psw();
 }
 
+static int psw_odd_address(void)
+{
+	struct psw odd = {
+		.mask = extract_psw_mask(),
+	};
+	uint64_t regs[16];
+	int r;
+
+	/*
+	 * This asm is reentered at an odd address, which should cause a specification
+	 * exception before the first unaligned instruction is executed.
+	 * In this case, the interrupt handler fixes the address and the test succeeds.
+	 * If, however, unaligned instructions *are* executed, they are jumped to
+	 * from somewhere, with unknown registers, so save and restore those before.
+	 */
+	asm volatile ( "stmg	%%r0,%%r15,%[regs]\n"
+		//can only offset by even number when using larl -> increment by one
+		"	larl	%[r],0f\n"
+		"	aghi	%[r],1\n"
+		"	stg	%[r],%[addr]\n"
+		"	xr	%[r],%[r]\n"
+		"	brc	0xf,1f\n"
+		"0:	. = . + 1\n"
+		"	lmg	%%r0,%%r15,0(%%r1)\n"
+		//address of the instruction itself, should be odd, store for assert
+		"	larl	%[r],0\n"
+		"	stg	%[r],%[addr]\n"
+		"	larl	%[r],0f\n"
+		"	aghi	%[r],1\n"
+		"	bcr	0xf,%[r]\n"
+		"0:	. = . + 1\n"
+		"1:\n"
+	: [addr] "=T" (odd.addr),
+	  [regs] "=Q" (regs),
+	  [r] "=d" (r)
+	: : "cc", "memory"
+	);
+
+	if (!r) {
+		expect_invalid_psw(odd);
+		load_psw_with_arg(odd, (uint64_t)&regs);
+		return check_invalid_psw();
+	} else {
+		assert(odd.addr & 1);
+		clear_invalid_psw();
+		report_fail("executed unaligned instructions");
+		return 1;
+	}
+}
+
 /* A short PSW needs to have bit 12 set to be valid. */
 static int short_psw_bit_12_is_0(void)
 {
@@ -176,6 +240,7 @@ struct spec_ex_trigger {
 static const struct spec_ex_trigger spec_ex_triggers[] = {
 	{ "psw_bit_12_is_1", &psw_bit_12_is_1, false, &fixup_invalid_psw },
 	{ "short_psw_bit_12_is_0", &short_psw_bit_12_is_0, false, &fixup_invalid_psw },
+	{ "psw_odd_address", &psw_odd_address, false, &fixup_invalid_psw },
 	{ "bad_alignment", &bad_alignment, true, NULL },
 	{ "not_even", &not_even, true, NULL },
 	{ NULL, NULL, false, NULL },
-- 
2.36.1


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

* [kvm-unit-tests PATCH v1 2/2] s390x/spec_ex: Add test of EXECUTE with odd target address
  2023-02-15 17:18 [kvm-unit-tests PATCH v1 0/2] s390x: Add misaligned instruction tests Nina Schoetterl-Glausch
  2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW Nina Schoetterl-Glausch
@ 2023-02-15 17:18 ` Nina Schoetterl-Glausch
  2023-02-17 10:01   ` Claudio Imbrenda
  1 sibling, 1 reply; 6+ messages in thread
From: Nina Schoetterl-Glausch @ 2023-02-15 17:18 UTC (permalink / raw)
  To: Thomas Huth, Janosch Frank, Claudio Imbrenda
  Cc: Nina Schoetterl-Glausch, David Hildenbrand, kvm, linux-s390

The EXECUTE instruction executes the instruction at the given target
address. This address must be halfword aligned, otherwise a
specification exception occurs.
Add a test for this.

Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
---
 s390x/spec_ex.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/s390x/spec_ex.c b/s390x/spec_ex.c
index b6764677..0cd3174f 100644
--- a/s390x/spec_ex.c
+++ b/s390x/spec_ex.c
@@ -200,6 +200,30 @@ static int short_psw_bit_12_is_0(void)
 	return 0;
 }
 
+static int odd_ex_target(void)
+{
+	uint64_t target_addr_pre;
+	int to = 0, from = 0x0dd;
+
+	asm volatile ( ".pushsection .rodata\n"
+		"odd_ex_target_pre_insn:\n"
+		"	.balign 2\n"
+		"	. = . + 1\n"
+		"	lr	%[to],%[from]\n"
+		"	.popsection\n"
+
+		"	larl	%[target_addr_pre],odd_ex_target_pre_insn\n"
+		"	ex	0,1(%[target_addr_pre])\n"
+		: [target_addr_pre] "=&a" (target_addr_pre),
+		  [to] "+d" (to)
+		: [from] "d" (from)
+	);
+
+	assert((target_addr_pre + 1) & 1);
+	report(to != from, "did not perform ex with odd target");
+	return 0;
+}
+
 static int bad_alignment(void)
 {
 	uint32_t words[5] __attribute__((aligned(16)));
@@ -241,6 +265,7 @@ static const struct spec_ex_trigger spec_ex_triggers[] = {
 	{ "psw_bit_12_is_1", &psw_bit_12_is_1, false, &fixup_invalid_psw },
 	{ "short_psw_bit_12_is_0", &short_psw_bit_12_is_0, false, &fixup_invalid_psw },
 	{ "psw_odd_address", &psw_odd_address, false, &fixup_invalid_psw },
+	{ "odd_ex_target", &odd_ex_target, true, NULL },
 	{ "bad_alignment", &bad_alignment, true, NULL },
 	{ "not_even", &not_even, true, NULL },
 	{ NULL, NULL, false, NULL },
-- 
2.36.1


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

* Re: [kvm-unit-tests PATCH v1 2/2] s390x/spec_ex: Add test of EXECUTE with odd target address
  2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 2/2] s390x/spec_ex: Add test of EXECUTE with odd target address Nina Schoetterl-Glausch
@ 2023-02-17 10:01   ` Claudio Imbrenda
  0 siblings, 0 replies; 6+ messages in thread
From: Claudio Imbrenda @ 2023-02-17 10:01 UTC (permalink / raw)
  To: Nina Schoetterl-Glausch
  Cc: Thomas Huth, Janosch Frank, David Hildenbrand, kvm, linux-s390

On Wed, 15 Feb 2023 18:18:52 +0100
Nina Schoetterl-Glausch <nsg@linux.ibm.com> wrote:

> The EXECUTE instruction executes the instruction at the given target
> address. This address must be halfword aligned, otherwise a
> specification exception occurs.
> Add a test for this.
> 
> Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>

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

> ---
>  s390x/spec_ex.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/s390x/spec_ex.c b/s390x/spec_ex.c
> index b6764677..0cd3174f 100644
> --- a/s390x/spec_ex.c
> +++ b/s390x/spec_ex.c
> @@ -200,6 +200,30 @@ static int short_psw_bit_12_is_0(void)
>  	return 0;
>  }
>  
> +static int odd_ex_target(void)
> +{
> +	uint64_t target_addr_pre;
> +	int to = 0, from = 0x0dd;
> +
> +	asm volatile ( ".pushsection .rodata\n"
> +		"odd_ex_target_pre_insn:\n"
> +		"	.balign 2\n"
> +		"	. = . + 1\n"
> +		"	lr	%[to],%[from]\n"
> +		"	.popsection\n"
> +
> +		"	larl	%[target_addr_pre],odd_ex_target_pre_insn\n"
> +		"	ex	0,1(%[target_addr_pre])\n"
> +		: [target_addr_pre] "=&a" (target_addr_pre),
> +		  [to] "+d" (to)
> +		: [from] "d" (from)
> +	);
> +
> +	assert((target_addr_pre + 1) & 1);
> +	report(to != from, "did not perform ex with odd target");
> +	return 0;
> +}
> +
>  static int bad_alignment(void)
>  {
>  	uint32_t words[5] __attribute__((aligned(16)));
> @@ -241,6 +265,7 @@ static const struct spec_ex_trigger spec_ex_triggers[] = {
>  	{ "psw_bit_12_is_1", &psw_bit_12_is_1, false, &fixup_invalid_psw },
>  	{ "short_psw_bit_12_is_0", &short_psw_bit_12_is_0, false, &fixup_invalid_psw },
>  	{ "psw_odd_address", &psw_odd_address, false, &fixup_invalid_psw },
> +	{ "odd_ex_target", &odd_ex_target, true, NULL },
>  	{ "bad_alignment", &bad_alignment, true, NULL },
>  	{ "not_even", &not_even, true, NULL },
>  	{ NULL, NULL, false, NULL },


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

* Re: [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW
  2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW Nina Schoetterl-Glausch
@ 2023-02-17 11:05   ` Claudio Imbrenda
  2023-02-20 14:09     ` Nina Schoetterl-Glausch
  0 siblings, 1 reply; 6+ messages in thread
From: Claudio Imbrenda @ 2023-02-17 11:05 UTC (permalink / raw)
  To: Nina Schoetterl-Glausch
  Cc: Thomas Huth, Janosch Frank, David Hildenbrand, kvm, linux-s390

On Wed, 15 Feb 2023 18:18:51 +0100
Nina Schoetterl-Glausch <nsg@linux.ibm.com> wrote:

> Instructions on s390 must be halfword aligned.
> Introducing an odd instruction address into the PSW leads to a
> specification exception when attempting to execute the instruction at
> the odd address.
> Add a test for this.
> 
> Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> ---
>  s390x/spec_ex.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 69 insertions(+), 4 deletions(-)
> 
> diff --git a/s390x/spec_ex.c b/s390x/spec_ex.c
> index 42ecaed3..b6764677 100644
> --- a/s390x/spec_ex.c
> +++ b/s390x/spec_ex.c
> @@ -44,9 +44,10 @@ static void fixup_invalid_psw(struct stack_frame_int *stack)
>  /*
>   * Load possibly invalid psw, but setup fixup_psw before,
>   * so that fixup_invalid_psw() can bring us back onto the right track.
> + * The provided argument is loaded into register 1.
>   * Also acts as compiler barrier, -> none required in expect/check_invalid_psw
>   */
> -static void load_psw(struct psw psw)
> +static void load_psw_with_arg(struct psw psw, uint64_t arg)
>  {
>  	uint64_t scratch;
>  
> @@ -57,15 +58,22 @@ static void load_psw(struct psw psw)
>  	fixup_psw.mask = extract_psw_mask();
>  	asm volatile ( "larl	%[scratch],0f\n"
>  		"	stg	%[scratch],%[fixup_addr]\n"
> +		"	lgr	%%r1,%[arg]\n"
>  		"	lpswe	%[psw]\n"
>  		"0:	nop\n"
>  		: [scratch] "=&d" (scratch),
>  		  [fixup_addr] "=&T" (fixup_psw.addr)
> -		: [psw] "Q" (psw)
> -		: "cc", "memory"
> +		: [psw] "Q" (psw),
> +		  [arg] "d" (arg)
> +		: "cc", "memory", "%r1"
>  	);
>  }
>  
> +static void load_psw(struct psw psw)
> +{
> +	load_psw_with_arg(psw, 0);
> +}
> +
>  static void load_short_psw(struct short_psw psw)
>  {
>  	uint64_t scratch;
> @@ -88,12 +96,18 @@ static void expect_invalid_psw(struct psw psw)
>  	invalid_psw_expected = true;
>  }
>  
> +static void clear_invalid_psw(void)
> +{
> +	expected_psw = (struct psw){0};

as of today, you can use PSW(0, 0)  :)

> +	invalid_psw_expected = false;
> +}
> +
>  static int check_invalid_psw(void)
>  {
>  	/* Since the fixup sets this to false we check for false here. */
>  	if (!invalid_psw_expected) {
>  		if (expected_psw.mask == invalid_psw.mask &&
> -		    expected_psw.addr == invalid_psw.addr)
> +		    expected_psw.addr == invalid_psw.addr - lowcore.pgm_int_id)

can you explain this change?

>  			return 0;
>  		report_fail("Wrong invalid PSW");
>  	} else {
> @@ -115,6 +129,56 @@ static int psw_bit_12_is_1(void)
>  	return check_invalid_psw();
>  }
>  
> +static int psw_odd_address(void)
> +{
> +	struct psw odd = {

now you can use PSW_WITH_CUR_MASK(0) here

> +		.mask = extract_psw_mask(),
> +	};
> +	uint64_t regs[16];
> +	int r;
> +
> +	/*
> +	 * This asm is reentered at an odd address, which should cause a specification
> +	 * exception before the first unaligned instruction is executed.
> +	 * In this case, the interrupt handler fixes the address and the test succeeds.
> +	 * If, however, unaligned instructions *are* executed, they are jumped to
> +	 * from somewhere, with unknown registers, so save and restore those before.
> +	 */

I wonder if this could be simplified

> +	asm volatile ( "stmg	%%r0,%%r15,%[regs]\n"
> +		//can only offset by even number when using larl -> increment by one
> +		"	larl	%[r],0f\n"
> +		"	aghi	%[r],1\n"
> +		"	stg	%[r],%[addr]\n"

the above is ok (set up illegal PSW)

(maybe call expect_invalid_psw here, see comments below)

put the address of the exit label in a register

then do a lpswe here to jump to the invalid PSW

> +		"	xr	%[r],%[r]\n"
> +		"	brc	0xf,1f\n"

then do the above. that will only happen if the PSW was not loaded.

> +		"0:	. = . + 1\n"

if we are here, things went wrong.
write something in r, jump to the exit label (using the address in the
register that we saved earlier)

> +		"	lmg	%%r0,%%r15,0(%%r1)\n"
> +		//address of the instruction itself, should be odd, store for assert
> +		"	larl	%[r],0\n"
> +		"	stg	%[r],%[addr]\n"
> +		"	larl	%[r],0f\n"
> +		"	aghi	%[r],1\n"
> +		"	bcr	0xf,%[r]\n"
> +		"0:	. = . + 1\n"
> +		"1:\n"
> +	: [addr] "=T" (odd.addr),
> +	  [regs] "=Q" (regs),
> +	  [r] "=d" (r)
> +	: : "cc", "memory"
> +	);
> +

if we come out here and r is 0, then things went well, otherwise we
fail.

> +	if (!r) {
> +		expect_invalid_psw(odd);

that ^ should probably go before the asm (or _in_ the asm, maybe you
can call the C function from asm)

> +		load_psw_with_arg(odd, (uint64_t)&regs);

this would not be needed anymore ^


this way you don't need to save registers or do crazy things where you
jump back in the middle of the asm from C code. and then you don't even
need load_psw_with_arg


> +		return check_invalid_psw();
> +	} else {
> +		assert(odd.addr & 1);
> +		clear_invalid_psw();
> +		report_fail("executed unaligned instructions");
> +		return 1;
> +	}
> +}
> +
>  /* A short PSW needs to have bit 12 set to be valid. */
>  static int short_psw_bit_12_is_0(void)
>  {
> @@ -176,6 +240,7 @@ struct spec_ex_trigger {
>  static const struct spec_ex_trigger spec_ex_triggers[] = {
>  	{ "psw_bit_12_is_1", &psw_bit_12_is_1, false, &fixup_invalid_psw },
>  	{ "short_psw_bit_12_is_0", &short_psw_bit_12_is_0, false, &fixup_invalid_psw },
> +	{ "psw_odd_address", &psw_odd_address, false, &fixup_invalid_psw },
>  	{ "bad_alignment", &bad_alignment, true, NULL },
>  	{ "not_even", &not_even, true, NULL },
>  	{ NULL, NULL, false, NULL },


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

* Re: [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW
  2023-02-17 11:05   ` Claudio Imbrenda
@ 2023-02-20 14:09     ` Nina Schoetterl-Glausch
  0 siblings, 0 replies; 6+ messages in thread
From: Nina Schoetterl-Glausch @ 2023-02-20 14:09 UTC (permalink / raw)
  To: Claudio Imbrenda
  Cc: Thomas Huth, Janosch Frank, David Hildenbrand, kvm, linux-s390

On Fri, 2023-02-17 at 12:05 +0100, Claudio Imbrenda wrote:
> On Wed, 15 Feb 2023 18:18:51 +0100
> Nina Schoetterl-Glausch <nsg@linux.ibm.com> wrote:
> 
> > Instructions on s390 must be halfword aligned.
> > Introducing an odd instruction address into the PSW leads to a
> > specification exception when attempting to execute the instruction at
> > the odd address.
> > Add a test for this.
> > 
> > Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> > ---
> >  s390x/spec_ex.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++---
> >  1 file changed, 69 insertions(+), 4 deletions(-)
> > 
> > diff --git a/s390x/spec_ex.c b/s390x/spec_ex.c
> > index 42ecaed3..b6764677 100644
> > --- a/s390x/spec_ex.c
> > +++ b/s390x/spec_ex.c
> > @@ -44,9 +44,10 @@ static void fixup_invalid_psw(struct stack_frame_int *stack)
> >  /*
> >   * Load possibly invalid psw, but setup fixup_psw before,
> >   * so that fixup_invalid_psw() can bring us back onto the right track.
> > + * The provided argument is loaded into register 1.
> >   * Also acts as compiler barrier, -> none required in expect/check_invalid_psw
> >   */
> > -static void load_psw(struct psw psw)
> > +static void load_psw_with_arg(struct psw psw, uint64_t arg)
> >  {
> >  	uint64_t scratch;
> >  
> > @@ -57,15 +58,22 @@ static void load_psw(struct psw psw)
> >  	fixup_psw.mask = extract_psw_mask();
> >  	asm volatile ( "larl	%[scratch],0f\n"
> >  		"	stg	%[scratch],%[fixup_addr]\n"
> > +		"	lgr	%%r1,%[arg]\n"
> >  		"	lpswe	%[psw]\n"
> >  		"0:	nop\n"
> >  		: [scratch] "=&d" (scratch),
> >  		  [fixup_addr] "=&T" (fixup_psw.addr)
> > -		: [psw] "Q" (psw)
> > -		: "cc", "memory"
> > +		: [psw] "Q" (psw),
> > +		  [arg] "d" (arg)
> > +		: "cc", "memory", "%r1"
> >  	);
> >  }
> >  
> > +static void load_psw(struct psw psw)
> > +{
> > +	load_psw_with_arg(psw, 0);
> > +}
> > +
> >  static void load_short_psw(struct short_psw psw)
> >  {
> >  	uint64_t scratch;
> > @@ -88,12 +96,18 @@ static void expect_invalid_psw(struct psw psw)
> >  	invalid_psw_expected = true;
> >  }
> >  
> > +static void clear_invalid_psw(void)
> > +{
> > +	expected_psw = (struct psw){0};
> 
> as of today, you can use PSW(0, 0)  :)
> 
> > +	invalid_psw_expected = false;
> > +}
> > +
> >  static int check_invalid_psw(void)
> >  {
> >  	/* Since the fixup sets this to false we check for false here. */
> >  	if (!invalid_psw_expected) {
> >  		if (expected_psw.mask == invalid_psw.mask &&
> > -		    expected_psw.addr == invalid_psw.addr)
> > +		    expected_psw.addr == invalid_psw.addr - lowcore.pgm_int_id)
> 
> can you explain this change?

In the existing invalid PSW tests, the instruction length code is 0, so no
change there. In case of an odd address being introduced into the PSW, the
address is incremented by an unpredictable amount, the subtraction removes that.
> 
> >  			return 0;
> >  		report_fail("Wrong invalid PSW");
> >  	} else {
> > @@ -115,6 +129,56 @@ static int psw_bit_12_is_1(void)
> >  	return check_invalid_psw();
> >  }
> >  
> > +static int psw_odd_address(void)
> > +{
> > +	struct psw odd = {
> 
> now you can use PSW_WITH_CUR_MASK(0) here
> 
> > +		.mask = extract_psw_mask(),
> > +	};
> > +	uint64_t regs[16];
> > +	int r;
> > +
> > +	/*
> > +	 * This asm is reentered at an odd address, which should cause a specification
> > +	 * exception before the first unaligned instruction is executed.
> > +	 * In this case, the interrupt handler fixes the address and the test succeeds.
> > +	 * If, however, unaligned instructions *are* executed, they are jumped to
> > +	 * from somewhere, with unknown registers, so save and restore those before.
> > +	 */
> 
> I wonder if this could be simplified
> 
> > +	asm volatile ( "stmg	%%r0,%%r15,%[regs]\n"
> > +		//can only offset by even number when using larl -> increment by one
> > +		"	larl	%[r],0f\n"
> > +		"	aghi	%[r],1\n"
> > +		"	stg	%[r],%[addr]\n"
> 
> the above is ok (set up illegal PSW)
> 
> (maybe call expect_invalid_psw here, see comments below)
> 
> put the address of the exit label in a register
> 
> then do a lpswe here to jump to the invalid PSW
> 
> > +		"	xr	%[r],%[r]\n"
> > +		"	brc	0xf,1f\n"
> 
> then do the above. that will only happen if the PSW was not loaded.
> 
> > +		"0:	. = . + 1\n"
> 
> if we are here, things went wrong.
> write something in r, jump to the exit label (using the address in the
> register that we saved earlier)
> 
> > +		"	lmg	%%r0,%%r15,0(%%r1)\n"
> > +		//address of the instruction itself, should be odd, store for assert
> > +		"	larl	%[r],0\n"
> > +		"	stg	%[r],%[addr]\n"
> > +		"	larl	%[r],0f\n"
> > +		"	aghi	%[r],1\n"
> > +		"	bcr	0xf,%[r]\n"
> > +		"0:	. = . + 1\n"
> > +		"1:\n"
> > +	: [addr] "=T" (odd.addr),
> > +	  [regs] "=Q" (regs),
> > +	  [r] "=d" (r)
> > +	: : "cc", "memory"
> > +	);
> > +
> 
> if we come out here and r is 0, then things went well, otherwise we
> fail.
> 
> > +	if (!r) {
> > +		expect_invalid_psw(odd);
> 
> that ^ should probably go before the asm (or _in_ the asm, maybe you
> can call the C function from asm)
> 
> > +		load_psw_with_arg(odd, (uint64_t)&regs);
> 
> this would not be needed anymore ^
> 
> 
> this way you don't need to save registers or do crazy things where you
> jump back in the middle of the asm from C code. and then you don't even
> need load_psw_with_arg
> 
I'll see what I can do.
> 
> > +		return check_invalid_psw();
> > +	} else {
> > +		assert(odd.addr & 1);
> > +		clear_invalid_psw();
> > +		report_fail("executed unaligned instructions");
> > +		return 1;
> > +	}
> > +}
> > +
> >  /* A short PSW needs to have bit 12 set to be valid. */
> >  static int short_psw_bit_12_is_0(void)
> >  {
> > @@ -176,6 +240,7 @@ struct spec_ex_trigger {
> >  static const struct spec_ex_trigger spec_ex_triggers[] = {
> >  	{ "psw_bit_12_is_1", &psw_bit_12_is_1, false, &fixup_invalid_psw },
> >  	{ "short_psw_bit_12_is_0", &short_psw_bit_12_is_0, false, &fixup_invalid_psw },
> > +	{ "psw_odd_address", &psw_odd_address, false, &fixup_invalid_psw },
> >  	{ "bad_alignment", &bad_alignment, true, NULL },
> >  	{ "not_even", &not_even, true, NULL },
> >  	{ NULL, NULL, false, NULL },
> 


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

end of thread, other threads:[~2023-02-20 14:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-15 17:18 [kvm-unit-tests PATCH v1 0/2] s390x: Add misaligned instruction tests Nina Schoetterl-Glausch
2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 1/2] s390x/spec_ex: Add test introducing odd address into PSW Nina Schoetterl-Glausch
2023-02-17 11:05   ` Claudio Imbrenda
2023-02-20 14:09     ` Nina Schoetterl-Glausch
2023-02-15 17:18 ` [kvm-unit-tests PATCH v1 2/2] s390x/spec_ex: Add test of EXECUTE with odd target address Nina Schoetterl-Glausch
2023-02-17 10:01   ` Claudio Imbrenda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).