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 extern const char SNIPPET_NAME_START(c, spec_ex)[]; 21 extern const char SNIPPET_NAME_END(c, spec_ex)[]; 22 static bool strict; 23 24 static void setup_guest(void) 25 { 26 char *guest; 27 int binary_size = SNIPPET_LEN(c, spec_ex); 28 29 setup_vm(); 30 guest = alloc_pages(8); 31 memcpy(guest, SNIPPET_NAME_START(c, spec_ex), binary_size); 32 sie_guest_create(&vm, (uint64_t) guest, HPAGE_SIZE); 33 } 34 35 static void reset_guest(void) 36 { 37 vm.sblk->gpsw = snippet_psw; 38 vm.sblk->icptcode = 0; 39 } 40 41 static void test_spec_ex_sie(void) 42 { 43 const char *msg; 44 45 setup_guest(); 46 47 report_prefix_push("SIE spec ex interpretation"); 48 report_prefix_push("off"); 49 reset_guest(); 50 sie(&vm); 51 /* interpretation off -> initial exception must cause interception */ 52 report(vm.sblk->icptcode == ICPT_PROGI 53 && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION 54 && vm.sblk->gpsw.addr != 0xdeadbeee, 55 "Received specification exception intercept for initial exception"); 56 report_prefix_pop(); 57 58 report_prefix_push("on"); 59 vm.sblk->ecb |= ECB_SPECI; 60 reset_guest(); 61 sie(&vm); 62 /* interpretation on -> configuration dependent if initial exception causes 63 * interception, but invalid new program PSW must 64 */ 65 report(vm.sblk->icptcode == ICPT_PROGI 66 && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION, 67 "Received specification exception intercept"); 68 msg = "Interpreted initial exception, intercepted invalid program new PSW exception"; 69 if (strict) 70 report(vm.sblk->gpsw.addr == 0xdeadbeee, "%s", msg); 71 else if (vm.sblk->gpsw.addr == 0xdeadbeee) 72 report_info("%s", msg); 73 else 74 report_info("Did not interpret initial exception"); 75 report_prefix_pop(); 76 report_prefix_pop(); 77 } 78 79 static bool parse_strict(int argc, char **argv) 80 { 81 uint16_t machine_id; 82 char *list; 83 bool ret; 84 85 if (argc < 1) 86 return false; 87 if (strcmp("--strict", argv[0])) 88 return false; 89 90 machine_id = get_machine_id(); 91 if (argc < 2) { 92 printf("No argument to --strict, ignoring\n"); 93 return false; 94 } 95 list = argv[1]; 96 if (list[0] == '!') { 97 ret = true; 98 list++; 99 } else { 100 ret = false; 101 } 102 while (true) { 103 long input = 0; 104 105 if (strlen(list) == 0) 106 return ret; 107 input = strtol(list, &list, 16); 108 if (*list == ',') 109 list++; 110 else if (*list != '\0') 111 break; 112 if (input == machine_id) 113 return !ret; 114 } 115 printf("Invalid --strict argument \"%s\", ignoring\n", list); 116 return ret; 117 } 118 119 int main(int argc, char **argv) 120 { 121 strict = parse_strict(argc - 1, argv + 1); 122 if (!sclp_facilities.has_sief2) { 123 report_skip("SIEF2 facility unavailable"); 124 goto out; 125 } 126 127 test_spec_ex_sie(); 128 out: 129 return report_summary(); 130 } 131