1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright IBM Corp. 2023 4 * 5 * SIE with STLFE interpretive execution facilities test. 6 */ 7 #include <libcflat.h> 8 #include <stdlib.h> 9 #include <asm/facility.h> 10 #include <asm/time.h> 11 #include <snippet.h> 12 #include <snippet-exit.h> 13 #include <alloc_page.h> 14 #include <sclp.h> 15 #include <rand.h> 16 17 static struct vm vm; 18 static uint64_t (*fac)[PAGE_SIZE / sizeof(uint64_t)]; 19 static prng_state prng_s; 20 21 static void setup_guest(void) 22 { 23 extern const char SNIPPET_NAME_START(c, stfle)[]; 24 extern const char SNIPPET_NAME_END(c, stfle)[]; 25 26 setup_vm(); 27 fac = alloc_pages_flags(0, AREA_DMA31); 28 29 snippet_setup_guest(&vm, false); 30 snippet_init(&vm, SNIPPET_NAME_START(c, stfle), 31 SNIPPET_LEN(c, stfle), SNIPPET_UNPACK_OFF); 32 } 33 34 struct guest_stfle_res { 35 uint16_t len; 36 unsigned char *mem; 37 }; 38 39 static struct guest_stfle_res run_guest(void) 40 { 41 struct guest_stfle_res res; 42 uint64_t guest_stfle_addr; 43 uint64_t reg; 44 45 sie(&vm); 46 assert(snippet_is_force_exit_value(&vm)); 47 guest_stfle_addr = snippet_get_force_exit_value(&vm); 48 res.mem = &vm.guest_mem[guest_stfle_addr]; 49 memcpy(®, res.mem, sizeof(reg)); 50 res.len = (reg & 0xff) + 1; 51 res.mem += sizeof(reg); 52 return res; 53 } 54 55 static void test_stfle_format_0(void) 56 { 57 struct guest_stfle_res res; 58 59 report_prefix_push("format-0"); 60 for (int j = 0; j < stfle_size(); j++) 61 WRITE_ONCE((*fac)[j], prng64(&prng_s)); 62 vm.sblk->fac = (uint32_t)(uint64_t)fac; 63 res = run_guest(); 64 report(res.len == stfle_size(), "stfle len correct"); 65 report(!memcmp(*fac, res.mem, res.len * sizeof(uint64_t)), 66 "Guest facility list as specified"); 67 report_prefix_pop(); 68 } 69 70 struct args { 71 uint64_t seed; 72 }; 73 74 static bool parse_uint64_t(const char *arg, uint64_t *out) 75 { 76 char *end; 77 uint64_t num; 78 79 if (arg[0] == '\0') 80 return false; 81 num = strtoul(arg, &end, 0); 82 if (end[0] != '\0') 83 return false; 84 *out = num; 85 return true; 86 } 87 88 static struct args parse_args(int argc, char **argv) 89 { 90 struct args args; 91 const char *flag; 92 unsigned int i; 93 uint64_t arg; 94 bool has_arg; 95 96 stck(&args.seed); 97 98 for (i = 1; i < argc; i++) { 99 if (i + 1 < argc) 100 has_arg = parse_uint64_t(argv[i + 1], &arg); 101 else 102 has_arg = false; 103 104 flag = "--seed"; 105 if (!strcmp(flag, argv[i])) { 106 if (!has_arg) 107 report_abort("%s needs an uint64_t parameter", flag); 108 args.seed = arg; 109 ++i; 110 continue; 111 } 112 report_abort("Unsupported parameter '%s'", 113 argv[i]); 114 } 115 116 return args; 117 } 118 119 int main(int argc, char **argv) 120 { 121 struct args args = parse_args(argc, argv); 122 bool run_format_0 = test_facility(7); 123 124 if (!sclp_facilities.has_sief2) { 125 report_skip("SIEF2 facility unavailable"); 126 goto out; 127 } 128 if (!run_format_0) 129 report_skip("STFLE facility not available"); 130 131 report_info("PRNG seed: 0x%lx", args.seed); 132 prng_s = prng_init(args.seed); 133 setup_guest(); 134 if (run_format_0) 135 test_stfle_format_0(); 136 out: 137 return report_summary(); 138 } 139