diff mbox

[kvm-unit-tests,3/8] s390x: Add storage keys tests

Message ID 1520942503-6163-4-git-send-email-frankja@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Janosch Frank March 13, 2018, 12:01 p.m. UTC
Storage keys are not used by Linux anymore, so let's show them some
love and test if the basics still work.

Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
---
 lib/s390x/asm/mem.h | 61 ++++++++++++++++++++++++++++++++++
 s390x/Makefile      |  1 +
 s390x/skey.c        | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 s390x/unittests.cfg |  3 ++
 4 files changed, 159 insertions(+)
 create mode 100644 lib/s390x/asm/mem.h
 create mode 100644 s390x/skey.c

Comments

Thomas Huth March 13, 2018, 6:32 p.m. UTC | #1
On 13.03.2018 13:01, Janosch Frank wrote:
> Storage keys are not used by Linux anymore, so let's show them some
> love and test if the basics still work.
> 
> Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
> ---
>  lib/s390x/asm/mem.h | 61 ++++++++++++++++++++++++++++++++++
>  s390x/Makefile      |  1 +
>  s390x/skey.c        | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  s390x/unittests.cfg |  3 ++
>  4 files changed, 159 insertions(+)
>  create mode 100644 lib/s390x/asm/mem.h
>  create mode 100644 s390x/skey.c
> 
> diff --git a/lib/s390x/asm/mem.h b/lib/s390x/asm/mem.h
> new file mode 100644
> index 0000000..28772b0
> --- /dev/null
> +++ b/lib/s390x/asm/mem.h
> @@ -0,0 +1,61 @@
> +/*
> + * Physical memory management related functions and definitions.
> + *
> + * Copyright IBM Corp. 2017

2018 ?

> + * Author(s): Janosch Frank <frankja@de.ibm.com>
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Library General Public License version 2.
> + */
> +#ifndef _ASM_S390_MEM_H
> +#define _ASM_S390_MEM_H
> +
> +union skey {
> +	struct {
> +		uint8_t acc : 4;
> +		uint8_t fp : 1;
> +		uint8_t rf : 1;
> +		uint8_t ch : 1;
> +		uint8_t pad : 1;
> +	} str;
> +	uint8_t val;
> +};
> +
> +static inline void set_storage_key(unsigned long addr,
> +				   unsigned char skey,
> +				   int nq)

I did not spot any occurance of set_storage_key(..., true) in this
patch, so do you really need this parameter?

> +{
> +	if (nq && test_facility(14))

I think you could simply drop the test_facility check here since the bit
is ignored accoring to the PoP if the facility is not installed.

> +		asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0"
> +			     : : "d" (skey), "a" (addr));
> +	else
> +		asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
> +}
> +
> +static inline unsigned long set_storage_key_mb(unsigned long addr,
> +					       unsigned char skey)
> +{
> +	if (!test_facility(8))
> +		return 0;

You check that already in test_set_mb() ... so I'd either remove this
if-statement or turn it into a assert(test_facility(8)).

> +	/* As we only have one cpu and no concurrent skey changes,
> +	 * we're able to use the non-quescing option (if available) to
> +	 * speed things up a little.
> +	 */
> +	if (test_facility(14))

Again, no need to explicitly check for that facility here - the bit is
ignored if the facility is not available.

> +		asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
> +			     : [addr] "+a" (addr) : [skey] "d" (skey));
> +	else
> +		asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],1,0"
> +			     : [addr] "+a" (addr) : [skey] "d" (skey));
> +	return addr;
> +}
> +
> +static inline unsigned char get_storage_key(unsigned long addr)
> +{
> +	unsigned char skey;
> +
> +	asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr));
> +	return skey;
> +}
> +#endif

The other parts of the patch look fine to me.

 Thomas
Janosch Frank March 14, 2018, 1:34 p.m. UTC | #2
On 13.03.2018 19:32, Thomas Huth wrote:
> On 13.03.2018 13:01, Janosch Frank wrote:
>> Storage keys are not used by Linux anymore, so let's show them some
>> love and test if the basics still work.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
>> ---
>>  lib/s390x/asm/mem.h | 61 ++++++++++++++++++++++++++++++++++
>>  s390x/Makefile      |  1 +
>>  s390x/skey.c        | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  s390x/unittests.cfg |  3 ++
>>  4 files changed, 159 insertions(+)
>>  create mode 100644 lib/s390x/asm/mem.h
>>  create mode 100644 s390x/skey.c
>>
>> diff --git a/lib/s390x/asm/mem.h b/lib/s390x/asm/mem.h
>> new file mode 100644
>> index 0000000..28772b0
>> --- /dev/null
>> +++ b/lib/s390x/asm/mem.h
>> @@ -0,0 +1,61 @@
>> +/*
>> + * Physical memory management related functions and definitions.
>> + *
>> + * Copyright IBM Corp. 2017
> 
> 2018 ?

Sure

> 
>> + * Author(s): Janosch Frank <frankja@de.ibm.com>
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU Library General Public License version 2.
>> + */
>> +#ifndef _ASM_S390_MEM_H
>> +#define _ASM_S390_MEM_H
>> +
>> +union skey {
>> +	struct {
>> +		uint8_t acc : 4;
>> +		uint8_t fp : 1;
>> +		uint8_t rf : 1;
>> +		uint8_t ch : 1;
>> +		uint8_t pad : 1;
>> +	} str;
>> +	uint8_t val;
>> +};
>> +
>> +static inline void set_storage_key(unsigned long addr,
>> +				   unsigned char skey,
>> +				   int nq)
> 
> I did not spot any occurance of set_storage_key(..., true) in this
> patch, so do you really need this parameter?

No, I just added nq setting because I was at it, if you want I can
remove it.

> 
>> +{
>> +	if (nq && test_facility(14))
> 
> I think you could simply drop the test_facility check here since the bit
> is ignored accoring to the PoP if the facility is not installed.
> 
>> +		asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0"
>> +			     : : "d" (skey), "a" (addr));
>> +	else
>> +		asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
>> +}
>> +
>> +static inline unsigned long set_storage_key_mb(unsigned long addr,
>> +					       unsigned char skey)
>> +{
>> +	if (!test_facility(8))
>> +		return 0;
> 
> You check that already in test_set_mb() ... so I'd either remove this
> if-statement or turn it into a assert(test_facility(8)).

Assert it is.

> 
>> +	/* As we only have one cpu and no concurrent skey changes,
>> +	 * we're able to use the non-quescing option (if available) to
>> +	 * speed things up a little.
>> +	 */
>> +	if (test_facility(14))
> 
> Again, no need to explicitly check for that facility here - the bit is
> ignored if the facility is not available.

Did not know that.

> 
>> +		asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
>> +			     : [addr] "+a" (addr) : [skey] "d" (skey));
>> +	else
>> +		asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],1,0"
>> +			     : [addr] "+a" (addr) : [skey] "d" (skey));
>> +	return addr;
>> +}
>> +
>> +static inline unsigned char get_storage_key(unsigned long addr)
>> +{
>> +	unsigned char skey;
>> +
>> +	asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr));
>> +	return skey;
>> +}
>> +#endif
> 
> The other parts of the patch look fine to me.
> 
>  Thomas
>
diff mbox

Patch

diff --git a/lib/s390x/asm/mem.h b/lib/s390x/asm/mem.h
new file mode 100644
index 0000000..28772b0
--- /dev/null
+++ b/lib/s390x/asm/mem.h
@@ -0,0 +1,61 @@ 
+/*
+ * Physical memory management related functions and definitions.
+ *
+ * Copyright IBM Corp. 2017
+ * Author(s): Janosch Frank <frankja@de.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2.
+ */
+#ifndef _ASM_S390_MEM_H
+#define _ASM_S390_MEM_H
+
+union skey {
+	struct {
+		uint8_t acc : 4;
+		uint8_t fp : 1;
+		uint8_t rf : 1;
+		uint8_t ch : 1;
+		uint8_t pad : 1;
+	} str;
+	uint8_t val;
+};
+
+static inline void set_storage_key(unsigned long addr,
+				   unsigned char skey,
+				   int nq)
+{
+	if (nq && test_facility(14))
+		asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0"
+			     : : "d" (skey), "a" (addr));
+	else
+		asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
+}
+
+static inline unsigned long set_storage_key_mb(unsigned long addr,
+					       unsigned char skey)
+{
+	if (!test_facility(8))
+		return 0;
+
+	/* As we only have one cpu and no concurrent skey changes,
+	 * we're able to use the non-quescing option (if available) to
+	 * speed things up a little.
+	 */
+	if (test_facility(14))
+		asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
+			     : [addr] "+a" (addr) : [skey] "d" (skey));
+	else
+		asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],1,0"
+			     : [addr] "+a" (addr) : [skey] "d" (skey));
+	return addr;
+}
+
+static inline unsigned char get_storage_key(unsigned long addr)
+{
+	unsigned char skey;
+
+	asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr));
+	return skey;
+}
+#endif
diff --git a/s390x/Makefile b/s390x/Makefile
index e062727..b73031d 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -3,6 +3,7 @@  tests += $(TEST_DIR)/intercept.elf
 tests += $(TEST_DIR)/emulator.elf
 tests += $(TEST_DIR)/sieve.elf
 tests += $(TEST_DIR)/sthyi.elf
+tests += $(TEST_DIR)/skey.elf
 
 all: directories test_cases
 
diff --git a/s390x/skey.c b/s390x/skey.c
new file mode 100644
index 0000000..e33e0e3
--- /dev/null
+++ b/s390x/skey.c
@@ -0,0 +1,94 @@ 
+/*
+ * Storage key tests
+ *
+ * Copyright (c) 2017 IBM Corp
+ *
+ * Authors:
+ *  Janosch Frank <frankja@linux.vnet.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2.
+ */
+#include <libcflat.h>
+#include <asm/asm-offsets.h>
+#include <asm/interrupt.h>
+#include <asm/page.h>
+#include <asm/facility.h>
+#include <asm/mem.h>
+
+
+static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
+const unsigned long page0 = (unsigned long)pagebuf;
+const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE);
+
+static void test_set_mb(void)
+{
+	union skey skey, ret1, ret2;
+	unsigned long addr = 0x10000 - 2 * PAGE_SIZE;
+	unsigned long end = 0x10000;
+
+	/* Multi block support came with EDAT 1 */
+	if (!test_facility(8))
+		return;
+
+	skey.val = 0x30;
+	while (addr < end)
+		addr = set_storage_key_mb(addr, skey.val);
+
+	ret1.val = get_storage_key(end - PAGE_SIZE);
+	ret2.val = get_storage_key(end - PAGE_SIZE * 2);
+	report("multi block", ret1.val == ret2.val && ret1.val == skey.val);
+}
+
+static void test_chg(void)
+{
+	union skey skey1, skey2;
+
+	skey1.val = 0x30;
+	set_storage_key(page0, skey1.val, 0);
+	skey1.val = get_storage_key(page0);
+	pagebuf[0] = 3;
+	skey2.val = get_storage_key(page0);
+	report("chg bit test", !skey1.str.ch && skey2.str.ch);
+}
+
+static void test_set(void)
+{
+	union skey skey, ret;
+
+	skey.val = 0x30;
+	ret.val = get_storage_key(page0);
+	set_storage_key(page0, skey.val, 0);
+	ret.val = get_storage_key(page0);
+	report("set key test", skey.val == ret.val);
+}
+
+static void test_priv(void)
+{
+	union skey skey;
+
+	memset(pagebuf, 0, PAGE_SIZE * 2);
+	expect_pgm_int();
+	enter_pstate();
+	set_storage_key(page0, 0x30, 0);
+	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
+
+	skey.val = get_storage_key(page0);
+	report("skey did not change on exception", skey.str.acc != 3);
+
+	expect_pgm_int();
+	enter_pstate();
+	get_storage_key(page0);
+	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
+}
+
+int main(void)
+{
+	report_prefix_push("skey");
+	test_priv();
+	test_set();
+	test_set_mb();
+	test_chg();
+	report_prefix_pop();
+	return report_summary();
+}
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 506891a..8321e9b 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -38,3 +38,6 @@  timeout = 600
 [sthyi]
 file = sthyi.elf
 accel = kvm
+
+[skey]
+file = skey.elf