mbox series

[kvm-unit-tests,v2,0/5] s390x: STFLE nested interpretation

Message ID 20240105225419.2841310-1-nsg@linux.ibm.com (mailing list archive)
Headers show
Series s390x: STFLE nested interpretation | expand

Message

Nina Schoetterl-Glausch Jan. 5, 2024, 10:54 p.m. UTC
v1 -> v2 (range-diff below):
 * implement SHA-256 based PRNG
 * pick up R-b (thanks Claudio)
 * change snippet exit API and implementation (thanks Claudio)
 * add stfle-sie to unittests.cfg

Add a test case that tests the interpretation of STFLE performed by a
nested guest using a snippet.
Also add some functionality to lib/, namely:
* pseudo random number generation (arch independent)
* exit (optionally with return code) from snippet (s390x)

Nina Schoetterl-Glausch (5):
  lib: Add pseudo random functions
  s390x: lib: Remove double include
  s390x: Add library functions for exiting from snippet
  s390x: Use library functions for snippet exit
  s390x: Add test for STFLE interpretive execution (format-0)

 Makefile                                |   1 +
 s390x/Makefile                          |   3 +
 lib/s390x/asm/arch_def.h                |  13 ++
 lib/s390x/asm/facility.h                |  10 +-
 lib/rand.h                              |  21 +++
 lib/s390x/sie.h                         |   1 +
 lib/s390x/snippet-guest.h               |  26 ++++
 lib/s390x/{snippet.h => snippet-host.h} |  10 +-
 lib/rand.c                              | 177 ++++++++++++++++++++++++
 lib/s390x/sie.c                         |  32 ++++-
 lib/s390x/snippet-host.c                |  42 ++++++
 lib/s390x/uv.c                          |   2 +-
 s390x/mvpg-sie.c                        |   2 +-
 s390x/pv-diags.c                        |   2 +-
 s390x/pv-icptcode.c                     |   2 +-
 s390x/pv-ipl.c                          |   2 +-
 s390x/sie-dat.c                         |  13 +-
 s390x/snippets/c/sie-dat.c              |  19 +--
 s390x/snippets/c/stfle.c                |  26 ++++
 s390x/spec_ex-sie.c                     |   2 +-
 s390x/stfle-sie.c                       | 134 ++++++++++++++++++
 s390x/uv-host.c                         |   2 +-
 s390x/unittests.cfg                     |   3 +
 23 files changed, 506 insertions(+), 39 deletions(-)
 create mode 100644 lib/rand.h
 create mode 100644 lib/s390x/snippet-guest.h
 rename lib/s390x/{snippet.h => snippet-host.h} (92%)
 create mode 100644 lib/rand.c
 create mode 100644 lib/s390x/snippet-host.c
 create mode 100644 s390x/snippets/c/stfle.c
 create mode 100644 s390x/stfle-sie.c

Range-diff against v1:
1:  40d815f3 < -:  -------- lib: Add pseudo random functions
-:  -------- > 1:  6c869961 lib: Add pseudo random functions
2:  f5284941 ! 2:  77319d3e s390x: lib: Remove double include
    @@ Commit message
     
         libcflat.h was included twice.
     
    +    Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
         Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
     
      ## lib/s390x/sie.c ##
3:  303cf927 ! 3:  e2c2cad8 s390x: Add library functions for exiting from snippet
    @@ Commit message
         Add this functionality, also add helper functions for the host to check
         for an exit and get or check the value.
         Use diag 0x44 and 0x9c for this.
    -    Add a guest specific snippet header file and rename the host's.
    +    Add a guest specific snippet header file and rename snippet.h to reflect
    +    that it is host specific.
     
         Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
     
    @@ lib/s390x/snippet-host.h: static inline void snippet_setup_guest(struct vm *vm,
      	}
      }
      
    -+bool snippet_check_force_exit(struct vm *vm);
    -+bool snippet_get_force_exit_value(struct vm *vm, uint64_t *value);
    ++bool snippet_is_force_exit(struct vm *vm);
    ++bool snippet_is_force_exit_value(struct vm *vm);
    ++uint64_t snippet_get_force_exit_value(struct vm *vm);
     +void snippet_check_force_exit_value(struct vm *vm, uint64_t exit_exp);
      #endif
     
    @@ lib/s390x/sie.c: void sie_check_validity(struct vm *vm, uint16_t vir_exp)
      
     +bool sie_is_diag_icpt(struct vm *vm, unsigned int diag)
     +{
    -+	uint32_t ipb = vm->sblk->ipb;
    ++	union {
    ++		struct {
    ++			uint64_t     : 16;
    ++			uint64_t ipa : 16;
    ++			uint64_t ipb : 32;
    ++		};
    ++		struct {
    ++			uint64_t          : 16;
    ++			uint64_t opcode   :  8;
    ++			uint64_t r_1      :  4;
    ++			uint64_t r_2      :  4;
    ++			uint64_t r_base   :  4;
    ++			uint64_t displace : 12;
    ++			uint64_t zero     : 16;
    ++		};
    ++	} instr = { .ipa = vm->sblk->ipa, .ipb = vm->sblk->ipb };
     +	uint64_t code;
    -+	uint16_t displace;
    -+	uint8_t base;
    -+	bool ret = true;
     +
    -+	ret = ret && vm->sblk->icptcode == ICPT_INST;
    -+	ret = ret && (vm->sblk->ipa & 0xff00) == 0x8300;
    -+	switch (diag) {
    -+	case 0x44:
    -+	case 0x9c:
    -+		ret = ret && !(ipb & 0xffff);
    -+		ipb >>= 16;
    -+		displace = ipb & 0xfff;
    -+		ipb >>= 12;
    -+		base = ipb & 0xf;
    -+		code = base ? vm->save_area.guest.grs[base] + displace : displace;
    -+		code &= 0xffff;
    -+		ret = ret && (code == diag);
    -+		break;
    -+	default:
    -+		abort(); /* not implemented */
    -+	}
    -+	return ret;
    ++	assert(diag == 0x44 || diag == 0x9c);
    ++
    ++	if (vm->sblk->icptcode != ICPT_INST)
    ++		return false;
    ++	if (instr.opcode != 0x83 || instr.zero)
    ++		return false;
    ++	code = instr.r_base ? vm->save_area.guest.grs[instr.r_base] : 0;
    ++	code = (code + instr.displace) & 0xffff;
    ++	return code == diag;
     +}
     +
      void sie_handle_validity(struct vm *vm)
    @@ lib/s390x/snippet-host.c (new)
     +#include <snippet-host.h>
     +#include <sie.h>
     +
    -+bool snippet_check_force_exit(struct vm *vm)
    ++bool snippet_is_force_exit(struct vm *vm)
     +{
    -+	bool r;
    ++	return sie_is_diag_icpt(vm, 0x44);
    ++}
     +
    -+	r = sie_is_diag_icpt(vm, 0x44);
    -+	report(r, "guest forced exit");
    -+	return r;
    ++bool snippet_is_force_exit_value(struct vm *vm)
    ++{
    ++	return sie_is_diag_icpt(vm, 0x9c);
     +}
     +
    -+bool snippet_get_force_exit_value(struct vm *vm, uint64_t *value)
    ++uint64_t snippet_get_force_exit_value(struct vm *vm)
     +{
     +	struct kvm_s390_sie_block *sblk = vm->sblk;
     +
    -+	if (sie_is_diag_icpt(vm, 0x9c)) {
    -+		*value = vm->save_area.guest.grs[(sblk->ipa & 0xf0) >> 4];
    -+		report_pass("guest forced exit with value: 0x%lx", *value);
    -+		return true;
    -+	}
    -+	report_fail("guest forced exit with value");
    -+	return false;
    ++	assert(snippet_is_force_exit_value(vm));
    ++
    ++	return vm->save_area.guest.grs[(sblk->ipa & 0xf0) >> 4];
     +}
     +
     +void snippet_check_force_exit_value(struct vm *vm, uint64_t value_exp)
     +{
     +	uint64_t value;
     +
    -+	if (snippet_get_force_exit_value(vm, &value))
    -+		report(value == value_exp, "guest exit value matches 0x%lx", value_exp);
    ++	if (snippet_is_force_exit_value(vm)) {
    ++		value = snippet_get_force_exit_value(vm);
    ++		report(value == value_exp, "guest forced exit with value (0x%lx == 0x%lx)",
    ++		       value, value_exp);
    ++	} else {
    ++		report_fail("guest forced exit with value");
    ++	}
     +}
     
      ## lib/s390x/uv.c ##
4:  efe8449a ! 4:  67fbf0bb s390x: Use library functions for snippet exit
    @@ s390x/sie-dat.c: static void test_sie_dat(void)
     -
     -	r1 = (vm.sblk->ipa & 0xf0) >> 4;
     -	test_page_gpa = vm.save_area.guest.grs[r1];
    -+	assert(snippet_get_force_exit_value(&vm, &test_page_gpa));
    ++	assert(snippet_is_force_exit_value(&vm));
    ++	test_page_gpa = snippet_get_force_exit_value(&vm);
      	test_page_hpa = virt_to_pte_phys(guest_root, (void*)test_page_gpa);
      	test_page_hva = __va(test_page_hpa);
      	report_info("test buffer gpa=0x%lx hva=%p", test_page_gpa, test_page_hva);
    @@ s390x/sie-dat.c: static void test_sie_dat(void)
      	sie(&vm);
     -	assert(vm.sblk->icptcode == ICPT_INST &&
     -	       vm.sblk->ipa == 0x8300 && vm.sblk->ipb == 0x440000);
    -+	assert(snippet_check_force_exit(&vm));
    ++	assert(snippet_is_force_exit(&vm));
      
      	contents_match = true;
      	for (unsigned int i = 0; i < GUEST_TEST_PAGE_COUNT; i++) {
5:  f0eaac68 ! 5:  157079f2 s390x: Add test for STFLE interpretive execution (format-0)
    @@ s390x/stfle-sie.c (new)
     +#include <snippet-host.h>
     +#include <alloc_page.h>
     +#include <sclp.h>
    ++#include <rand.h>
     +
     +static struct vm vm;
     +static uint64_t (*fac)[PAGE_SIZE / sizeof(uint64_t)];
    -+static rand_state rand_s;
    ++static prng_state prng_s;
     +
     +static void setup_guest(void)
     +{
    @@ s390x/stfle-sie.c (new)
     +	uint64_t guest_stfle_addr;
     +
     +	sie(&vm);
    -+	assert(snippet_get_force_exit_value(&vm, &guest_stfle_addr));
    ++	assert(snippet_is_force_exit_value(&vm));
    ++	guest_stfle_addr = snippet_get_force_exit_value(&vm);
     +	res.mem = &vm.guest_mem[guest_stfle_addr];
     +	memcpy(&res.reg, res.mem, sizeof(res.reg));
     +	res.len = (res.reg & 0xff) + 1;
    @@ s390x/stfle-sie.c (new)
     +
     +	report_prefix_push("format-0");
     +	for (int j = 0; j < stfle_size(); j++)
    -+		WRITE_ONCE((*fac)[j], rand64(&rand_s));
    ++		WRITE_ONCE((*fac)[j], prng64(&prng_s));
     +	vm.sblk->fac = (uint32_t)(uint64_t)fac;
     +	res = run_guest();
     +	report(res.len == stfle_size(), "stfle len correct");
    @@ s390x/stfle-sie.c (new)
     +		goto out;
     +	}
     +
    -+	report_info("pseudo rand seed: 0x%lx", args.seed);
    -+	rand_s = RAND_STATE_INIT(args.seed);
    ++	report_info("PRNG seed: 0x%lx", args.seed);
    ++	prng_s = prng_init(args.seed);
     +	setup_guest();
     +	if (test_facility(7))
     +		test_stfle_format_0();
     +out:
     +	return report_summary();
     +}
    +
    + ## s390x/unittests.cfg ##
    +@@ s390x/unittests.cfg: extra_params = """-cpu max,ctop=on -smp cpus=1,drawers=2,books=2,sockets=2,cores
    + 
    + [sie-dat]
    + file = sie-dat.elf
    ++
    ++[stfle-sie]
    ++file = stfle-sie.elf

base-commit: 3c1736b1344b9831f17fbd64f95ea89c279564c6