Re: [kvm-unit-tests PATCH v2 3/8] s390x: Add storage keys tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 20.03.2018 12:19, 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@xxxxxxxxxxxxxxxxxx>
> ---
>  lib/s390x/asm/mem.h | 52 +++++++++++++++++++++++++++++
>  s390x/Makefile      |  1 +
>  s390x/skey.c        | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  s390x/unittests.cfg |  3 ++
>  4 files changed, 150 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..909e6d4
> --- /dev/null
> +++ b/lib/s390x/asm/mem.h
> @@ -0,0 +1,52 @@
> +/*
> + * Physical memory management related functions and definitions.
> + *
> + * Copyright IBM Corp. 2018
> + * Author(s): Janosch Frank <frankja@xxxxxxxxxx>
> + *
> + * 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)
> +		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)
> +{
> +	assert(test_facility(8));
> +
> +	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..e4c2a43
> --- /dev/null
> +++ b/s390x/skey.c
> @@ -0,0 +1,94 @@
> +/*
> + * Storage key tests
> + *
> + * Copyright (c) 2018 IBM Corp
> + *
> + * Authors:
> + *  Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx>
> + *
> + * 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
> 

Reviewed-by: Thomas Huth <thuth@xxxxxxxxxx>



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux