diff mbox series

[kvm-unit-tests] s390x: Add diag308 subcode 0 testing

Message ID 20190822111100.4444-1-frankja@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series [kvm-unit-tests] s390x: Add diag308 subcode 0 testing | expand

Commit Message

Janosch Frank Aug. 22, 2019, 11:11 a.m. UTC
By adding a load reset routine to cstart.S we can also test the clear
reset done by subcode 0, as we now can restore our registers again.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
I managed to extract this from another bigger test, so let's add it to the bunch.
I'd be very happy about assembly review :-)
---
 s390x/cstart64.S | 27 +++++++++++++++++++++++++++
 s390x/diag308.c  | 31 ++++++++++---------------------
 2 files changed, 37 insertions(+), 21 deletions(-)

Comments

David Hildenbrand Aug. 23, 2019, 11 a.m. UTC | #1
On 22.08.19 13:11, Janosch Frank wrote:
> By adding a load reset routine to cstart.S we can also test the clear
> reset done by subcode 0, as we now can restore our registers again.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
> I managed to extract this from another bigger test, so let's add it to the bunch.
> I'd be very happy about assembly review :-)
> ---
>  s390x/cstart64.S | 27 +++++++++++++++++++++++++++
>  s390x/diag308.c  | 31 ++++++++++---------------------
>  2 files changed, 37 insertions(+), 21 deletions(-)
> 
> diff --git a/s390x/cstart64.S b/s390x/cstart64.S
> index dedfe80..47045e1 100644
> --- a/s390x/cstart64.S
> +++ b/s390x/cstart64.S
> @@ -145,6 +145,33 @@ memsetxc:
>  	.endm
>  
>  .section .text
> +/*
> + * load_reset calling convention:
> + * %r2 subcode (0 or 1)
> + */
> +.globl load_reset
> +load_reset:
> +	SAVE_REGS
> +	/* Save the first PSW word to the IPL PSW */
> +	epsw	%r0, %r1
> +	st	%r0, 0
> +	/* Store the address and the bit for 31 bit addressing */
> +	larl    %r0, 0f
> +	oilh    %r0, 0x8000
> +	st      %r0, 0x4
> +	/* Do the reset */
> +	diag    %r0,%r2,0x308
> +	/* Failure path */
> +	xgr	%r2, %r2
> +	br	%r14
> +	/* Success path */
> +	/* We lost cr0 due to the reset */
> +0:	larl	%r1, initial_cr0
> +	lctlg	%c0, %c0, 0(%r1)
> +	RESTORE_REGS
> +	lhi	%r2, 1
> +	br	%r14
> +
>  pgm_int:
>  	SAVE_REGS
>  	brasl	%r14, handle_pgm_int
> diff --git a/s390x/diag308.c b/s390x/diag308.c
> index f085b1a..baf9fd3 100644
> --- a/s390x/diag308.c
> +++ b/s390x/diag308.c
> @@ -21,32 +21,20 @@ static void test_priv(void)
>  	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
>  }
>  
> +
>  /*
> - * Check that diag308 with subcode 1 loads the PSW at address 0, i.e.
> + * Check that diag308 with subcode 0 and 1 loads the PSW at address 0, i.e.
>   * that we can put a pointer into address 4 which then gets executed.
>   */
> +extern int load_reset(u64);
> +static void test_subcode0(void)
> +{
> +	report("load modified clear done", load_reset(0));
> +}
> +
>  static void test_subcode1(void)
>  {
> -	uint64_t saved_psw = *(uint64_t *)0;
> -	long subcode = 1;
> -	long ret, tmp;
> -
> -	asm volatile (
> -		"	epsw	%0,%1\n"
> -		"	st	%0,0\n"
> -		"	larl	%0,0f\n"
> -		"	oilh	%0,0x8000\n"
> -		"	st	%0,4\n"
> -		"	diag	0,%2,0x308\n"
> -		"	lghi	%0,0\n"
> -		"	j	1f\n"
> -		"0:	lghi	%0,1\n"
> -		"1:"
> -		: "=&d"(ret), "=&d"(tmp) : "d"(subcode) : "memory");
> -
> -	*(uint64_t *)0 = saved_psw;
> -
> -	report("load normal reset done", ret == 1);
> +	report("load normal reset done", load_reset(1));
>  }
>  
>  /* Expect a specification exception when using an uneven register */
> @@ -107,6 +95,7 @@ static struct {
>  	void (*func)(void);
>  } tests[] = {
>  	{ "privileged", test_priv },
> +	{ "subcode 0", test_subcode0 },
>  	{ "subcode 1", test_subcode1 },
>  	{ "subcode 5", test_subcode5 },
>  	{ "subcode 6", test_subcode6 },
> 

So, in general I am wondering if we should restore the original IPL_PSW
after we used it - is there any chance we might require the old value
again (I guess we're fine with cpu resets)?
Janosch Frank Aug. 23, 2019, 11:33 a.m. UTC | #2
On 8/23/19 1:00 PM, David Hildenbrand wrote:
> On 22.08.19 13:11, Janosch Frank wrote:
>> By adding a load reset routine to cstart.S we can also test the clear
>> reset done by subcode 0, as we now can restore our registers again.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> ---
>> I managed to extract this from another bigger test, so let's add it to the bunch.
>> I'd be very happy about assembly review :-)
>> ---
>>  s390x/cstart64.S | 27 +++++++++++++++++++++++++++
>>  s390x/diag308.c  | 31 ++++++++++---------------------
>>  2 files changed, 37 insertions(+), 21 deletions(-)
>>
>> diff --git a/s390x/cstart64.S b/s390x/cstart64.S
>> index dedfe80..47045e1 100644
>> --- a/s390x/cstart64.S
>> +++ b/s390x/cstart64.S
>> @@ -145,6 +145,33 @@ memsetxc:
>>  	.endm
>>  
>>  .section .text
>> +/*
>> + * load_reset calling convention:
>> + * %r2 subcode (0 or 1)
>> + */
>> +.globl load_reset
>> +load_reset:
>> +	SAVE_REGS
>> +	/* Save the first PSW word to the IPL PSW */
>> +	epsw	%r0, %r1
>> +	st	%r0, 0
>> +	/* Store the address and the bit for 31 bit addressing */
>> +	larl    %r0, 0f
>> +	oilh    %r0, 0x8000
>> +	st      %r0, 0x4
>> +	/* Do the reset */
>> +	diag    %r0,%r2,0x308
>> +	/* Failure path */
>> +	xgr	%r2, %r2
>> +	br	%r14
>> +	/* Success path */
>> +	/* We lost cr0 due to the reset */
>> +0:	larl	%r1, initial_cr0
>> +	lctlg	%c0, %c0, 0(%r1)
>> +	RESTORE_REGS
>> +	lhi	%r2, 1
>> +	br	%r14
>> +
>>  pgm_int:
>>  	SAVE_REGS
>>  	brasl	%r14, handle_pgm_int
>> diff --git a/s390x/diag308.c b/s390x/diag308.c
>> index f085b1a..baf9fd3 100644
>> --- a/s390x/diag308.c
>> +++ b/s390x/diag308.c
>> @@ -21,32 +21,20 @@ static void test_priv(void)
>>  	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
>>  }
>>  
>> +
>>  /*
>> - * Check that diag308 with subcode 1 loads the PSW at address 0, i.e.
>> + * Check that diag308 with subcode 0 and 1 loads the PSW at address 0, i.e.
>>   * that we can put a pointer into address 4 which then gets executed.
>>   */
>> +extern int load_reset(u64);
>> +static void test_subcode0(void)
>> +{
>> +	report("load modified clear done", load_reset(0));
>> +}
>> +
>>  static void test_subcode1(void)
>>  {
>> -	uint64_t saved_psw = *(uint64_t *)0;
>> -	long subcode = 1;
>> -	long ret, tmp;
>> -
>> -	asm volatile (
>> -		"	epsw	%0,%1\n"
>> -		"	st	%0,0\n"
>> -		"	larl	%0,0f\n"
>> -		"	oilh	%0,0x8000\n"
>> -		"	st	%0,4\n"
>> -		"	diag	0,%2,0x308\n"
>> -		"	lghi	%0,0\n"
>> -		"	j	1f\n"
>> -		"0:	lghi	%0,1\n"
>> -		"1:"
>> -		: "=&d"(ret), "=&d"(tmp) : "d"(subcode) : "memory");
>> -
>> -	*(uint64_t *)0 = saved_psw;
>> -
>> -	report("load normal reset done", ret == 1);
>> +	report("load normal reset done", load_reset(1));
>>  }
>>  
>>  /* Expect a specification exception when using an uneven register */
>> @@ -107,6 +95,7 @@ static struct {
>>  	void (*func)(void);
>>  } tests[] = {
>>  	{ "privileged", test_priv },
>> +	{ "subcode 0", test_subcode0 },
>>  	{ "subcode 1", test_subcode1 },
>>  	{ "subcode 5", test_subcode5 },
>>  	{ "subcode 6", test_subcode6 },
>>
> 
> So, in general I am wondering if we should restore the original IPL_PSW
> after we used it - is there any chance we might require the old value
> again (I guess we're fine with cpu resets)?

I currently don't see a need, but we could cache it in the restart old
psw address. Or we just store back the two word constant.
David Hildenbrand Aug. 23, 2019, 11:36 a.m. UTC | #3
On 23.08.19 13:33, Janosch Frank wrote:
> On 8/23/19 1:00 PM, David Hildenbrand wrote:
>> On 22.08.19 13:11, Janosch Frank wrote:
>>> By adding a load reset routine to cstart.S we can also test the clear
>>> reset done by subcode 0, as we now can restore our registers again.
>>>
>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>>> ---
>>> I managed to extract this from another bigger test, so let's add it to the bunch.
>>> I'd be very happy about assembly review :-)
>>> ---
>>>  s390x/cstart64.S | 27 +++++++++++++++++++++++++++
>>>  s390x/diag308.c  | 31 ++++++++++---------------------
>>>  2 files changed, 37 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/s390x/cstart64.S b/s390x/cstart64.S
>>> index dedfe80..47045e1 100644
>>> --- a/s390x/cstart64.S
>>> +++ b/s390x/cstart64.S
>>> @@ -145,6 +145,33 @@ memsetxc:
>>>  	.endm
>>>  
>>>  .section .text
>>> +/*
>>> + * load_reset calling convention:
>>> + * %r2 subcode (0 or 1)
>>> + */
>>> +.globl load_reset
>>> +load_reset:
>>> +	SAVE_REGS
>>> +	/* Save the first PSW word to the IPL PSW */
>>> +	epsw	%r0, %r1
>>> +	st	%r0, 0
>>> +	/* Store the address and the bit for 31 bit addressing */
>>> +	larl    %r0, 0f
>>> +	oilh    %r0, 0x8000
>>> +	st      %r0, 0x4
>>> +	/* Do the reset */
>>> +	diag    %r0,%r2,0x308
>>> +	/* Failure path */
>>> +	xgr	%r2, %r2
>>> +	br	%r14
>>> +	/* Success path */
>>> +	/* We lost cr0 due to the reset */
>>> +0:	larl	%r1, initial_cr0
>>> +	lctlg	%c0, %c0, 0(%r1)
>>> +	RESTORE_REGS
>>> +	lhi	%r2, 1
>>> +	br	%r14
>>> +
>>>  pgm_int:
>>>  	SAVE_REGS
>>>  	brasl	%r14, handle_pgm_int
>>> diff --git a/s390x/diag308.c b/s390x/diag308.c
>>> index f085b1a..baf9fd3 100644
>>> --- a/s390x/diag308.c
>>> +++ b/s390x/diag308.c
>>> @@ -21,32 +21,20 @@ static void test_priv(void)
>>>  	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
>>>  }
>>>  
>>> +
>>>  /*
>>> - * Check that diag308 with subcode 1 loads the PSW at address 0, i.e.
>>> + * Check that diag308 with subcode 0 and 1 loads the PSW at address 0, i.e.
>>>   * that we can put a pointer into address 4 which then gets executed.
>>>   */
>>> +extern int load_reset(u64);
>>> +static void test_subcode0(void)
>>> +{
>>> +	report("load modified clear done", load_reset(0));
>>> +}
>>> +
>>>  static void test_subcode1(void)
>>>  {
>>> -	uint64_t saved_psw = *(uint64_t *)0;
>>> -	long subcode = 1;
>>> -	long ret, tmp;
>>> -
>>> -	asm volatile (
>>> -		"	epsw	%0,%1\n"
>>> -		"	st	%0,0\n"
>>> -		"	larl	%0,0f\n"
>>> -		"	oilh	%0,0x8000\n"
>>> -		"	st	%0,4\n"
>>> -		"	diag	0,%2,0x308\n"
>>> -		"	lghi	%0,0\n"
>>> -		"	j	1f\n"
>>> -		"0:	lghi	%0,1\n"
>>> -		"1:"
>>> -		: "=&d"(ret), "=&d"(tmp) : "d"(subcode) : "memory");
>>> -
>>> -	*(uint64_t *)0 = saved_psw;
>>> -
>>> -	report("load normal reset done", ret == 1);
>>> +	report("load normal reset done", load_reset(1));
>>>  }
>>>  
>>>  /* Expect a specification exception when using an uneven register */
>>> @@ -107,6 +95,7 @@ static struct {
>>>  	void (*func)(void);
>>>  } tests[] = {
>>>  	{ "privileged", test_priv },
>>> +	{ "subcode 0", test_subcode0 },
>>>  	{ "subcode 1", test_subcode1 },
>>>  	{ "subcode 5", test_subcode5 },
>>>  	{ "subcode 6", test_subcode6 },
>>>
>>
>> So, in general I am wondering if we should restore the original IPL_PSW
>> after we used it - is there any chance we might require the old value
>> again (I guess we're fine with cpu resets)?
> 
> I currently don't see a need, but we could cache it in the restart old
> psw address. Or we just store back the two word constant.
> 

If there's no need right no, I guess we can skip that. Was just wondering.
Thomas Huth Aug. 23, 2019, 2:12 p.m. UTC | #4
On 8/22/19 1:11 PM, Janosch Frank wrote:
> By adding a load reset routine to cstart.S we can also test the clear
> reset done by subcode 0, as we now can restore our registers again.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
> I managed to extract this from another bigger test, so let's add it to the bunch.
> I'd be very happy about assembly review :-)

FWIW, the assembly code looks fine to me.

> ---
>  s390x/cstart64.S | 27 +++++++++++++++++++++++++++
>  s390x/diag308.c  | 31 ++++++++++---------------------
>  2 files changed, 37 insertions(+), 21 deletions(-)
> 
> diff --git a/s390x/cstart64.S b/s390x/cstart64.S
> index dedfe80..47045e1 100644
> --- a/s390x/cstart64.S
> +++ b/s390x/cstart64.S
> @@ -145,6 +145,33 @@ memsetxc:
>  	.endm
>  
>  .section .text
> +/*
> + * load_reset calling convention:
> + * %r2 subcode (0 or 1)
> + */
> +.globl load_reset
> +load_reset:

Maybe rather name the function diag308_load_reset so that it is clear
that it belongs to the diag308 test?
Or are you going to re-use this function in other tests later?

Anyway,
Reviewed-by: Thomas Huth <thuth@redhat.com>
Janosch Frank Aug. 23, 2019, 2:41 p.m. UTC | #5
On 8/23/19 4:12 PM, Thomas Huth wrote:
> On 8/22/19 1:11 PM, Janosch Frank wrote:
>> By adding a load reset routine to cstart.S we can also test the clear
>> reset done by subcode 0, as we now can restore our registers again.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> ---
>> I managed to extract this from another bigger test, so let's add it to the bunch.
>> I'd be very happy about assembly review :-)
> 
> FWIW, the assembly code looks fine to me.
> 
>> ---
>>  s390x/cstart64.S | 27 +++++++++++++++++++++++++++
>>  s390x/diag308.c  | 31 ++++++++++---------------------
>>  2 files changed, 37 insertions(+), 21 deletions(-)
>>
>> diff --git a/s390x/cstart64.S b/s390x/cstart64.S
>> index dedfe80..47045e1 100644
>> --- a/s390x/cstart64.S
>> +++ b/s390x/cstart64.S
>> @@ -145,6 +145,33 @@ memsetxc:
>>  	.endm
>>  
>>  .section .text
>> +/*
>> + * load_reset calling convention:
>> + * %r2 subcode (0 or 1)
>> + */
>> +.globl load_reset
>> +load_reset:
> 
> Maybe rather name the function diag308_load_reset so that it is clear
> that it belongs to the diag308 test?

Sure

> Or are you going to re-use this function in other tests later?

I currently have no such plans
But I'm thinking about a way to check the CPU registers in combination
with smp. So it might be extended.

> 
> Anyway,
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> 

Thanks!
diff mbox series

Patch

diff --git a/s390x/cstart64.S b/s390x/cstart64.S
index dedfe80..47045e1 100644
--- a/s390x/cstart64.S
+++ b/s390x/cstart64.S
@@ -145,6 +145,33 @@  memsetxc:
 	.endm
 
 .section .text
+/*
+ * load_reset calling convention:
+ * %r2 subcode (0 or 1)
+ */
+.globl load_reset
+load_reset:
+	SAVE_REGS
+	/* Save the first PSW word to the IPL PSW */
+	epsw	%r0, %r1
+	st	%r0, 0
+	/* Store the address and the bit for 31 bit addressing */
+	larl    %r0, 0f
+	oilh    %r0, 0x8000
+	st      %r0, 0x4
+	/* Do the reset */
+	diag    %r0,%r2,0x308
+	/* Failure path */
+	xgr	%r2, %r2
+	br	%r14
+	/* Success path */
+	/* We lost cr0 due to the reset */
+0:	larl	%r1, initial_cr0
+	lctlg	%c0, %c0, 0(%r1)
+	RESTORE_REGS
+	lhi	%r2, 1
+	br	%r14
+
 pgm_int:
 	SAVE_REGS
 	brasl	%r14, handle_pgm_int
diff --git a/s390x/diag308.c b/s390x/diag308.c
index f085b1a..baf9fd3 100644
--- a/s390x/diag308.c
+++ b/s390x/diag308.c
@@ -21,32 +21,20 @@  static void test_priv(void)
 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
 }
 
+
 /*
- * Check that diag308 with subcode 1 loads the PSW at address 0, i.e.
+ * Check that diag308 with subcode 0 and 1 loads the PSW at address 0, i.e.
  * that we can put a pointer into address 4 which then gets executed.
  */
+extern int load_reset(u64);
+static void test_subcode0(void)
+{
+	report("load modified clear done", load_reset(0));
+}
+
 static void test_subcode1(void)
 {
-	uint64_t saved_psw = *(uint64_t *)0;
-	long subcode = 1;
-	long ret, tmp;
-
-	asm volatile (
-		"	epsw	%0,%1\n"
-		"	st	%0,0\n"
-		"	larl	%0,0f\n"
-		"	oilh	%0,0x8000\n"
-		"	st	%0,4\n"
-		"	diag	0,%2,0x308\n"
-		"	lghi	%0,0\n"
-		"	j	1f\n"
-		"0:	lghi	%0,1\n"
-		"1:"
-		: "=&d"(ret), "=&d"(tmp) : "d"(subcode) : "memory");
-
-	*(uint64_t *)0 = saved_psw;
-
-	report("load normal reset done", ret == 1);
+	report("load normal reset done", load_reset(1));
 }
 
 /* Expect a specification exception when using an uneven register */
@@ -107,6 +95,7 @@  static struct {
 	void (*func)(void);
 } tests[] = {
 	{ "privileged", test_priv },
+	{ "subcode 0", test_subcode0 },
 	{ "subcode 1", test_subcode1 },
 	{ "subcode 5", test_subcode5 },
 	{ "subcode 6", test_subcode6 },