Re: [kvm-unit-tests PATCH v2 8/8] s390x: Add simple guarded storage tests

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

 



On 20.03.2018 12:19, Janosch Frank wrote:
> Guarded storage was introduced with IBM z14. Loads with the special
> instruction LOAD GUARDED are suspect to access controls if they fall
> into a guarded area. A handler is called if such an access is
> detected. The test checks for exceptions if the instructions are
> executed without cr2 enablement and tests handler execution on load
> guarded.
> 
> The initial test case is once again from Martin Schwidefsky with minor
> adaptions by me for kvm-unit-tests.
> 
> Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx>
> ---
>  s390x/Makefile      |   1 +
>  s390x/gs.c          | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  s390x/unittests.cfg |   3 +
>  3 files changed, 174 insertions(+)
>  create mode 100644 s390x/gs.c
> 
> diff --git a/s390x/Makefile b/s390x/Makefile
> index 47013d1..b44efb5 100644
> --- a/s390x/Makefile
> +++ b/s390x/Makefile
> @@ -8,6 +8,7 @@ tests += $(TEST_DIR)/diag10.elf
>  tests += $(TEST_DIR)/pfmf.elf
>  tests += $(TEST_DIR)/cmm.elf
>  tests += $(TEST_DIR)/vector.elf
> +tests += $(TEST_DIR)/gs.elf
>  
>  all: directories test_cases
>  
> diff --git a/s390x/gs.c b/s390x/gs.c
> new file mode 100644
> index 0000000..ea66697
> --- /dev/null
> +++ b/s390x/gs.c
> @@ -0,0 +1,170 @@
> +/*
> + * Tests guarded storage support.
> + *
> + * Copyright 2018 IBM Corp.
> + *
> + * Authors:
> + *    Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
> + *    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.
> + */
> +#include <libcflat.h>
> +#include <asm/page.h>
> +#include <asm/facility.h>
> +#include <asm/interrupt.h>
> +#include <asm-generic/barrier.h>
> +
> +struct gs_cb {
> +	uint64_t reserved;
> +	uint64_t gsd;
> +	uint64_t gssm;
> +	uint64_t gs_epl_a;
> +};
> +
> +struct gs_epl {
> +	uint8_t pad1;
> +	union {
> +		uint8_t gs_eam;
> +		struct {
> +			uint8_t		: 6;
> +			uint8_t e	: 1;
> +			uint8_t b	: 1;
> +		};
> +	};
> +	union {
> +		uint8_t gs_eci;
> +		struct {
> +			uint8_t tx	: 1;
> +			uint8_t cx	: 1;
> +			uint8_t		: 5;
> +			uint8_t in	: 1;
> +		};
> +	};
> +	union {
> +		uint8_t gs_eai;
> +		struct {
> +			uint8_t		: 1;
> +			uint8_t t	: 1;
> +			uint8_t as	: 2;
> +			uint8_t ar	: 4;
> +		};
> +	};
> +	uint32_t pad2;
> +	uint64_t gs_eha;
> +	uint64_t gs_eia;
> +	uint64_t gs_eoa;
> +	uint64_t gs_eir;
> +	uint64_t gs_era;
> +};
> +
> +static volatile int guarded = 0;
> +static struct gs_cb gs_cb;
> +static struct gs_epl gs_epl;
> +static unsigned long gs_area = 0x2000000;
> +
> +static inline void load_gs_cb(struct gs_cb *gs_cb)
> +{
> +	asm volatile(".insn rxy,0xe3000000004d,0,%0" : : "Q" (*gs_cb));
> +}
> +
> +static inline void store_gs_cb(struct gs_cb *gs_cb)
> +{
> +	asm volatile(".insn rxy,0xe30000000049,0,%0" : : "Q" (*gs_cb));
> +}
> +
> +static inline unsigned long load_guarded(unsigned long *p)
> +{
> +	unsigned long v;
> +
> +	asm(".insn rxy,0xe3000000004c, %0,%1"
> +	    : "=d" (v)
> +	    : "m" (*p)
> +	    : "r14", "memory");
> +	return v;
> +}
> +
> +/* guarded-storage event handler and finally it calls gs_handler */
> +extern void gs_handler_asm(void);
> +	asm(".globl gs_handler_asm\n"
> +	    "gs_handler_asm:\n"
> +	    "	    lgr	    %r14,%r15\n" 		/* Save current stack address in r14 */
> +	    "	    aghi    %r15,-320\n" 		/* Allocate stack frame */
> +	    "	    stmg    %r0,%r14,192(%r15)\n" 	/* Store regs to save area */

Not sure, but I think r0 to r13 would be enough here? Since r14 is
overwritten with the value from GSERA below?

> +	    "	    stg	    %r14,312(%r15)\n"
> +	    "	    la	    %r2,160(%r15)\n" 		/* Store gscb address in this_cb */
> +	    "	    .insn   rxy,0xe30000000049,0,160(%r15)\n" /* stgsc */
> +	    "	    lg	    %r14,24(%r2)\n" 		/* Get GSEPLA from GSCB*/
> +	    "	    lg	    %r14,40(%r14)\n" 		/* Get GSERA from GSEPL*/
> +	    "	    stg	    %r14,304(%r15)\n" 		/* Store GSEPL in r14 of reg save area */

s/GSEPL/GSERA/ in above comment?

> +	    "	    brasl   %r14,gs_handler\n" 		/* Jump to gs_handler */
> +	    "	    lmg	    %r0,%r15,192(%r15)\n" 	/* Restore regs */
> +	    "	    aghi    %r14, 6\n" 			/* Add lgg instr len to GSERA */
> +	    "	    br	    %r14\n" 			/* Jump to next instruction after lgg */
> +	    "	    .size gs_handler_asm,.-gs_handler_asm\n");
> +
> +void gs_handler(struct gs_cb *this_cb)
> +{
> +	guarded = 1;
> +	struct gs_epl *gs_epl = (struct gs_epl *) this_cb->gs_epl_a;
> +	printf("gs_handler called for %016lx at %016lx\n",
> +	       gs_epl->gs_eir, gs_epl->gs_eia);
> +}
> +
> +/* Test if load guarded gets intercepted. */
> +static void test_load(void)
> +{
> +	unsigned long v;
> +
> +	guarded = 0;
> +	v = load_guarded(&gs_area);
> +	report("load guarded %ld", guarded, v);
> +	guarded = 0;
> +}
> +
> +/* Test gs instructions without enablement resulting in an exception */
> +static void test_special(void)
> +{
> +	expect_pgm_int();
> +	load_gs_cb(&gs_cb);
> +	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
> +	expect_pgm_int();
> +	store_gs_cb(&gs_cb);
> +	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
> +}
> +
> +static void init(void)
> +{
> +	/* Enable control bit for gs */
> +	ctl_set_bit(2, 4);
> +
> +	/* Setup gs registers to guard the gs_area */
> +	gs_cb.gsd = gs_area | 25;
> +
> +	/* Check all 512kb slots for events */
> +	gs_cb.gssm = 0xFFFFFFFFFFFFFFFF;

It's rather just cosmetical here, but please add a "ULL" suffix to the
value.

> +	gs_cb.gs_epl_a =  (unsigned long) &gs_epl;
> +
> +	/* Register handler */
> +	gs_epl.gs_eha = (unsigned long) gs_handler_asm;
> +	load_gs_cb(&gs_cb);
> +}
> +
> +int main(void)
> +{
> +	bool has_gs = test_facility(133);
> +
> +	report_prefix_push("gs");
> +	report_xfail("Guarded storage available", !has_gs, has_gs);
> +	if (!has_gs)
> +		goto done;
> +
> +	test_special();
> +	init();
> +	test_load();
> +
> +done:
> +	report_prefix_pop();
> +	return report_summary();
> +}

Apart from the nits, this looks good to me. When you fixed the nits:

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