1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright IBM Corp. 2021 4 * 5 * Specification exception interception test. 6 * Checks that specification exception interceptions occur as expected when 7 * specification exception interpretation is off/on. 8 */ 9 #include <libcflat.h> 10 #include <stdlib.h> 11 #include <sclp.h> 12 #include <asm/page.h> 13 #include <asm/arch_def.h> 14 #include <alloc_page.h> 15 #include <sie.h> 16 #include <snippet.h> 17 #include <hardware.h> 18 19 static struct vm vm; 20 static bool strict; 21 22 static void setup_guest(void) 23 { 24 extern const char SNIPPET_NAME_START(c, spec_ex)[]; 25 extern const char SNIPPET_NAME_END(c, spec_ex)[]; 26 27 setup_vm(); 28 29 snippet_setup_guest(&vm, false); 30 snippet_init(&vm, SNIPPET_NAME_START(c, spec_ex), 31 SNIPPET_LEN(c, spec_ex), SNIPPET_UNPACK_OFF); 32 } 33 34 static void reset_guest(void) 35 { 36 vm.sblk->gpsw = snippet_psw; 37 vm.sblk->icptcode = 0; 38 } 39 40 static void test_spec_ex_sie(void) 41 { 42 const char *msg; 43 44 setup_guest(); 45 46 report_prefix_push("SIE spec ex interpretation"); 47 report_prefix_push("off"); 48 reset_guest(); 49 sie(&vm); 50 /* interpretation off -> initial exception must cause interception */ 51 report(vm.sblk->icptcode == ICPT_PROGI 52 && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION 53 && vm.sblk->gpsw.addr != 0xdeadbeee, 54 "Received specification exception intercept for initial exception"); 55 report_prefix_pop(); 56 57 report_prefix_push("on"); 58 vm.sblk->ecb |= ECB_SPECI; 59 reset_guest(); 60 sie(&vm); 61 /* interpretation on -> configuration dependent if initial exception causes 62 * interception, but invalid new program PSW must 63 */ 64 report(vm.sblk->icptcode == ICPT_PROGI 65 && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION, 66 "Received specification exception intercept"); 67 msg = "Interpreted initial exception, intercepted invalid program new PSW exception"; 68 if (strict) 69 report(vm.sblk->gpsw.addr == 0xdeadbeee, "%s", msg); 70 else if (vm.sblk->gpsw.addr == 0xdeadbeee) 71 report_info("%s", msg); 72 else 73 report_info("Did not interpret initial exception"); 74 report_prefix_pop(); 75 report_prefix_pop(); 76 } 77 78 static bool parse_strict(int argc, char **argv) 79 { 80 uint16_t machine_id; 81 char *list; 82 bool ret; 83 84 if (argc < 1) 85 return false; 86 if (strcmp("--strict", argv[0])) 87 return false; 88 89 machine_id = get_machine_id(); 90 if (argc < 2) { 91 printf("No argument to --strict, ignoring\n"); 92 return false; 93 } 94 list = argv[1]; 95 if (list[0] == '!') { 96 ret = true; 97 list++; 98 } else { 99 ret = false; 100 } 101 while (true) { 102 long input = 0; 103 104 if (strlen(list) == 0) 105 return ret; 106 input = strtol(list, &list, 16); 107 if (*list == ',') 108 list++; 109 else if (*list != '\0') 110 break; 111 if (input == machine_id) 112 return !ret; 113 } 114 printf("Invalid --strict argument \"%s\", ignoring\n", list); 115 return ret; 116 } 117 118 int main(int argc, char **argv) 119 { 120 strict = parse_strict(argc - 1, argv + 1); 121 if (!sclp_facilities.has_sief2) { 122 report_skip("SIEF2 facility unavailable"); 123 goto out; 124 } 125 126 test_spec_ex_sie(); 127 out: 128 return report_summary(); 129 } 130