diff mbox series

[kvm-unit-tests,v2,2/3] s390x: skrf: Add exception new skey test and add test to unittests.cfg

Message ID 20200727095415.494318-3-frankja@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series PV tests part 1 | expand

Commit Message

Janosch Frank July 27, 2020, 9:54 a.m. UTC
When an exception new psw with a storage key in its mask is loaded
from lowcore, a specification exception is raised. This differs from
the behavior when trying to execute skey related instructions, which
will result in special operation exceptions.

Also let's add the test unittests.cfg so it is run more often.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
---
 s390x/skrf.c        | 80 +++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg |  4 +++
 2 files changed, 84 insertions(+)

Comments

Thomas Huth July 27, 2020, 12:20 p.m. UTC | #1
On 27/07/2020 11.54, Janosch Frank wrote:
> When an exception new psw with a storage key in its mask is loaded
> from lowcore, a specification exception is raised. This differs from
> the behavior when trying to execute skey related instructions, which
> will result in special operation exceptions.
> 
> Also let's add the test unittests.cfg so it is run more often.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> ---
>  s390x/skrf.c        | 80 +++++++++++++++++++++++++++++++++++++++++++++
>  s390x/unittests.cfg |  4 +++
>  2 files changed, 84 insertions(+)
> 
> diff --git a/s390x/skrf.c b/s390x/skrf.c
> index 9cae589..fe78711 100644
> --- a/s390x/skrf.c
> +++ b/s390x/skrf.c
> @@ -11,12 +11,16 @@
>   */
>  #include <libcflat.h>
>  #include <asm/asm-offsets.h>
> +#include <asm-generic/barrier.h>
>  #include <asm/interrupt.h>
>  #include <asm/page.h>
>  #include <asm/facility.h>
>  #include <asm/mem.h>
> +#include <asm/sigp.h>
> +#include <smp.h>
>  
>  static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
> +static int testflag = 0;
>  
>  static void test_facilities(void)
>  {
> @@ -106,6 +110,81 @@ static void test_tprot(void)
>  	report_prefix_pop();
>  }
>  
> +static void wait_for_flag(void)
> +{
> +	while (!testflag)
> +		mb();
> +}
> +
> +static void set_flag(int val)
> +{
> +	mb();
> +	testflag = val;
> +	mb();
> +}
> +
> +static void ecall_cleanup(void)
> +{
> +	struct lowcore *lc = (void *)0x0;
> +
> +	lc->ext_new_psw.mask = 0x0000000180000000UL;
> +	lc->sw_int_crs[0] = 0x0000000000040000;
> +
> +	/*
> +	 * PGM old contains the ext new PSW, we need to clean it up,
> +	 * so we don't get a special operation exception on the lpswe
> +	 * of pgm old.
> +	 */
> +	lc->pgm_old_psw.mask = 0x0000000180000000UL;
> +	lc->pgm_old_psw.addr = (unsigned long)wait_for_flag;

I don't quite understand why you are using wait_for_flag here? Won't
that function return immediately due to the set_flag(1) below? And if it
returns, where does the cpu continue to exec code in that case? Wouldn't
it be better to leave the .addr unchanged, so that the CPU returns to
the endless loop in smp_cpu_setup_state ?

 Thomas


> +	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
> +	set_flag(1);
> +}
> +
> +/* Set a key into the external new psw mask and open external call masks */
> +static void ecall_setup(void)
> +{
> +	struct lowcore *lc = (void *)0x0;
> +	uint64_t mask;
> +
> +	register_pgm_int_func(ecall_cleanup);
> +	expect_pgm_int();
> +	/* Put a skey into the ext new psw */
> +	lc->ext_new_psw.mask = 0x00F0000180000000UL;
> +	/* Open up ext masks */
> +	ctl_set_bit(0, 13);
> +	mask = extract_psw_mask();
> +	mask |= PSW_MASK_EXT;
> +	load_psw_mask(mask);
> +	/* Tell cpu 0 that we're ready */
> +	set_flag(1);
> +}
> +
> +static void test_exception_ext_new(void)
> +{
> +	struct psw psw = {
> +		.mask = extract_psw_mask(),
> +		.addr = (unsigned long)ecall_setup
> +	};
> +
> +	report_prefix_push("exception external new");
> +	if (smp_query_num_cpus() < 2) {
> +		report_skip("Need second cpu for exception external new test.");
> +		report_prefix_pop();
> +		return;
> +	}
> +
> +	smp_cpu_setup(1, psw);
> +	wait_for_flag();
> +	set_flag(0);
> +
> +	sigp(1, SIGP_EXTERNAL_CALL, 0, NULL);
> +	wait_for_flag();
> +	smp_cpu_stop(1);
> +	report_prefix_pop();
> +}
> +
>  int main(void)
>  {
>  	report_prefix_push("skrf");
> @@ -121,6 +200,7 @@ int main(void)
>  	test_mvcos();
>  	test_spka();
>  	test_tprot();
> +	test_exception_ext_new();
>  
>  done:
>  	report_prefix_pop();
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index 0f156af..b35269b 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -88,3 +88,7 @@ extra_params = -m 3G
>  [css]
>  file = css.elf
>  extra_params = -device virtio-net-ccw
> +
> +[skrf]
> +file = skrf.elf
> +smp = 2
>
Janosch Frank July 27, 2020, 12:38 p.m. UTC | #2
On 7/27/20 2:20 PM, Thomas Huth wrote:
> On 27/07/2020 11.54, Janosch Frank wrote:
>> When an exception new psw with a storage key in its mask is loaded
>> from lowcore, a specification exception is raised. This differs from
>> the behavior when trying to execute skey related instructions, which
>> will result in special operation exceptions.
>>
>> Also let's add the test unittests.cfg so it is run more often.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
>> ---
>>  s390x/skrf.c        | 80 +++++++++++++++++++++++++++++++++++++++++++++
>>  s390x/unittests.cfg |  4 +++
>>  2 files changed, 84 insertions(+)
>>
>> diff --git a/s390x/skrf.c b/s390x/skrf.c
>> index 9cae589..fe78711 100644
>> --- a/s390x/skrf.c
>> +++ b/s390x/skrf.c
>> @@ -11,12 +11,16 @@
>>   */
>>  #include <libcflat.h>
>>  #include <asm/asm-offsets.h>
>> +#include <asm-generic/barrier.h>
>>  #include <asm/interrupt.h>
>>  #include <asm/page.h>
>>  #include <asm/facility.h>
>>  #include <asm/mem.h>
>> +#include <asm/sigp.h>
>> +#include <smp.h>
>>  
>>  static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
>> +static int testflag = 0;
>>  
>>  static void test_facilities(void)
>>  {
>> @@ -106,6 +110,81 @@ static void test_tprot(void)
>>  	report_prefix_pop();
>>  }
>>  
>> +static void wait_for_flag(void)
>> +{
>> +	while (!testflag)
>> +		mb();
>> +}
>> +
>> +static void set_flag(int val)
>> +{
>> +	mb();
>> +	testflag = val;
>> +	mb();
>> +}
>> +
>> +static void ecall_cleanup(void)
>> +{
>> +	struct lowcore *lc = (void *)0x0;
>> +
>> +	lc->ext_new_psw.mask = 0x0000000180000000UL;
>> +	lc->sw_int_crs[0] = 0x0000000000040000;
>> +
>> +	/*
>> +	 * PGM old contains the ext new PSW, we need to clean it up,
>> +	 * so we don't get a special operation exception on the lpswe
>> +	 * of pgm old.
>> +	 */
>> +	lc->pgm_old_psw.mask = 0x0000000180000000UL;
>> +	lc->pgm_old_psw.addr = (unsigned long)wait_for_flag;
> 
> I don't quite understand why you are using wait_for_flag here? Won't
> that function return immediately due to the set_flag(1) below? And if it
> returns, where does the cpu continue to exec code in that case? Wouldn't
> it be better to leave the .addr unchanged, so that the CPU returns to
> the endless loop in smp_cpu_setup_state ?

That's a valid point, will change

> 
>  Thomas
> 
> 
>> +	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
>> +	set_flag(1);
>> +}
>> +
>> +/* Set a key into the external new psw mask and open external call masks */
>> +static void ecall_setup(void)
>> +{
>> +	struct lowcore *lc = (void *)0x0;
>> +	uint64_t mask;
>> +
>> +	register_pgm_int_func(ecall_cleanup);
>> +	expect_pgm_int();
>> +	/* Put a skey into the ext new psw */
>> +	lc->ext_new_psw.mask = 0x00F0000180000000UL;
>> +	/* Open up ext masks */
>> +	ctl_set_bit(0, 13);
>> +	mask = extract_psw_mask();
>> +	mask |= PSW_MASK_EXT;
>> +	load_psw_mask(mask);
>> +	/* Tell cpu 0 that we're ready */
>> +	set_flag(1);
>> +}
>> +
>> +static void test_exception_ext_new(void)
>> +{
>> +	struct psw psw = {
>> +		.mask = extract_psw_mask(),
>> +		.addr = (unsigned long)ecall_setup
>> +	};
>> +
>> +	report_prefix_push("exception external new");
>> +	if (smp_query_num_cpus() < 2) {
>> +		report_skip("Need second cpu for exception external new test.");
>> +		report_prefix_pop();
>> +		return;
>> +	}
>> +
>> +	smp_cpu_setup(1, psw);
>> +	wait_for_flag();
>> +	set_flag(0);
>> +
>> +	sigp(1, SIGP_EXTERNAL_CALL, 0, NULL);
>> +	wait_for_flag();
>> +	smp_cpu_stop(1);
>> +	report_prefix_pop();
>> +}
>> +
>>  int main(void)
>>  {
>>  	report_prefix_push("skrf");
>> @@ -121,6 +200,7 @@ int main(void)
>>  	test_mvcos();
>>  	test_spka();
>>  	test_tprot();
>> +	test_exception_ext_new();
>>  
>>  done:
>>  	report_prefix_pop();
>> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
>> index 0f156af..b35269b 100644
>> --- a/s390x/unittests.cfg
>> +++ b/s390x/unittests.cfg
>> @@ -88,3 +88,7 @@ extra_params = -m 3G
>>  [css]
>>  file = css.elf
>>  extra_params = -device virtio-net-ccw
>> +
>> +[skrf]
>> +file = skrf.elf
>> +smp = 2
>>
>
Cornelia Huck July 30, 2020, 11:03 a.m. UTC | #3
On Mon, 27 Jul 2020 05:54:14 -0400
Janosch Frank <frankja@linux.ibm.com> wrote:

> When an exception new psw with a storage key in its mask is loaded
> from lowcore, a specification exception is raised. This differs from
> the behavior when trying to execute skey related instructions, which
> will result in special operation exceptions.
> 
> Also let's add the test unittests.cfg so it is run more often.

when you respin: s/add the test/add the test to/

> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
> ---
>  s390x/skrf.c        | 80 +++++++++++++++++++++++++++++++++++++++++++++
>  s390x/unittests.cfg |  4 +++
>  2 files changed, 84 insertions(+)
diff mbox series

Patch

diff --git a/s390x/skrf.c b/s390x/skrf.c
index 9cae589..fe78711 100644
--- a/s390x/skrf.c
+++ b/s390x/skrf.c
@@ -11,12 +11,16 @@ 
  */
 #include <libcflat.h>
 #include <asm/asm-offsets.h>
+#include <asm-generic/barrier.h>
 #include <asm/interrupt.h>
 #include <asm/page.h>
 #include <asm/facility.h>
 #include <asm/mem.h>
+#include <asm/sigp.h>
+#include <smp.h>
 
 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
+static int testflag = 0;
 
 static void test_facilities(void)
 {
@@ -106,6 +110,81 @@  static void test_tprot(void)
 	report_prefix_pop();
 }
 
+static void wait_for_flag(void)
+{
+	while (!testflag)
+		mb();
+}
+
+static void set_flag(int val)
+{
+	mb();
+	testflag = val;
+	mb();
+}
+
+static void ecall_cleanup(void)
+{
+	struct lowcore *lc = (void *)0x0;
+
+	lc->ext_new_psw.mask = 0x0000000180000000UL;
+	lc->sw_int_crs[0] = 0x0000000000040000;
+
+	/*
+	 * PGM old contains the ext new PSW, we need to clean it up,
+	 * so we don't get a special operation exception on the lpswe
+	 * of pgm old.
+	 */
+	lc->pgm_old_psw.mask = 0x0000000180000000UL;
+	lc->pgm_old_psw.addr = (unsigned long)wait_for_flag;
+
+	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+	set_flag(1);
+}
+
+/* Set a key into the external new psw mask and open external call masks */
+static void ecall_setup(void)
+{
+	struct lowcore *lc = (void *)0x0;
+	uint64_t mask;
+
+	register_pgm_int_func(ecall_cleanup);
+	expect_pgm_int();
+	/* Put a skey into the ext new psw */
+	lc->ext_new_psw.mask = 0x00F0000180000000UL;
+	/* Open up ext masks */
+	ctl_set_bit(0, 13);
+	mask = extract_psw_mask();
+	mask |= PSW_MASK_EXT;
+	load_psw_mask(mask);
+	/* Tell cpu 0 that we're ready */
+	set_flag(1);
+}
+
+static void test_exception_ext_new(void)
+{
+	struct psw psw = {
+		.mask = extract_psw_mask(),
+		.addr = (unsigned long)ecall_setup
+	};
+
+	report_prefix_push("exception external new");
+	if (smp_query_num_cpus() < 2) {
+		report_skip("Need second cpu for exception external new test.");
+		report_prefix_pop();
+		return;
+	}
+
+	smp_cpu_setup(1, psw);
+	wait_for_flag();
+	set_flag(0);
+
+	sigp(1, SIGP_EXTERNAL_CALL, 0, NULL);
+	wait_for_flag();
+	smp_cpu_stop(1);
+	report_prefix_pop();
+}
+
 int main(void)
 {
 	report_prefix_push("skrf");
@@ -121,6 +200,7 @@  int main(void)
 	test_mvcos();
 	test_spka();
 	test_tprot();
+	test_exception_ext_new();
 
 done:
 	report_prefix_pop();
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 0f156af..b35269b 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -88,3 +88,7 @@  extra_params = -m 3G
 [css]
 file = css.elf
 extra_params = -device virtio-net-ccw
+
+[skrf]
+file = skrf.elf
+smp = 2