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@xxxxxxxxxxxxx> Signed-off-by: Nina Schoetterl-Glausch <nsg@xxxxxxxxxxxxx> ## 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@xxxxxxxxxxxxx> @@ 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 -- 2.43.0