149934b5aSJanis Schoetterl-Glausch // SPDX-License-Identifier: GPL-2.0-only 249934b5aSJanis Schoetterl-Glausch /* 349934b5aSJanis Schoetterl-Glausch * Copyright IBM Corp. 2021 449934b5aSJanis Schoetterl-Glausch * 549934b5aSJanis Schoetterl-Glausch * Specification exception interception test. 649934b5aSJanis Schoetterl-Glausch * Checks that specification exception interceptions occur as expected when 749934b5aSJanis Schoetterl-Glausch * specification exception interpretation is off/on. 849934b5aSJanis Schoetterl-Glausch */ 949934b5aSJanis Schoetterl-Glausch #include <libcflat.h> 10d05bf604SJanis Schoetterl-Glausch #include <stdlib.h> 1149934b5aSJanis Schoetterl-Glausch #include <sclp.h> 1249934b5aSJanis Schoetterl-Glausch #include <asm/page.h> 1349934b5aSJanis Schoetterl-Glausch #include <asm/arch_def.h> 1449934b5aSJanis Schoetterl-Glausch #include <alloc_page.h> 1549934b5aSJanis Schoetterl-Glausch #include <sie.h> 1649934b5aSJanis Schoetterl-Glausch #include <snippet.h> 17d05bf604SJanis Schoetterl-Glausch #include <hardware.h> 1849934b5aSJanis Schoetterl-Glausch 1949934b5aSJanis Schoetterl-Glausch static struct vm vm; 20d05bf604SJanis Schoetterl-Glausch static bool strict; 2149934b5aSJanis Schoetterl-Glausch 2249934b5aSJanis Schoetterl-Glausch static void setup_guest(void) 2349934b5aSJanis Schoetterl-Glausch { 24*be76de4dSNico Boehr extern const char SNIPPET_NAME_START(c, spec_ex)[]; 25*be76de4dSNico Boehr extern const char SNIPPET_NAME_END(c, spec_ex)[]; 2649934b5aSJanis Schoetterl-Glausch 2749934b5aSJanis Schoetterl-Glausch setup_vm(); 28*be76de4dSNico Boehr 29*be76de4dSNico Boehr snippet_setup_guest(&vm, false); 30*be76de4dSNico Boehr snippet_init(&vm, SNIPPET_NAME_START(c, spec_ex), 31*be76de4dSNico Boehr SNIPPET_LEN(c, spec_ex), SNIPPET_UNPACK_OFF); 3249934b5aSJanis Schoetterl-Glausch } 3349934b5aSJanis Schoetterl-Glausch 3449934b5aSJanis Schoetterl-Glausch static void reset_guest(void) 3549934b5aSJanis Schoetterl-Glausch { 3649934b5aSJanis Schoetterl-Glausch vm.sblk->gpsw = snippet_psw; 3749934b5aSJanis Schoetterl-Glausch vm.sblk->icptcode = 0; 3849934b5aSJanis Schoetterl-Glausch } 3949934b5aSJanis Schoetterl-Glausch 4049934b5aSJanis Schoetterl-Glausch static void test_spec_ex_sie(void) 4149934b5aSJanis Schoetterl-Glausch { 42d05bf604SJanis Schoetterl-Glausch const char *msg; 43d05bf604SJanis Schoetterl-Glausch 4449934b5aSJanis Schoetterl-Glausch setup_guest(); 4549934b5aSJanis Schoetterl-Glausch 4649934b5aSJanis Schoetterl-Glausch report_prefix_push("SIE spec ex interpretation"); 4749934b5aSJanis Schoetterl-Glausch report_prefix_push("off"); 4849934b5aSJanis Schoetterl-Glausch reset_guest(); 4949934b5aSJanis Schoetterl-Glausch sie(&vm); 5049934b5aSJanis Schoetterl-Glausch /* interpretation off -> initial exception must cause interception */ 5149934b5aSJanis Schoetterl-Glausch report(vm.sblk->icptcode == ICPT_PROGI 5249934b5aSJanis Schoetterl-Glausch && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION 5349934b5aSJanis Schoetterl-Glausch && vm.sblk->gpsw.addr != 0xdeadbeee, 5449934b5aSJanis Schoetterl-Glausch "Received specification exception intercept for initial exception"); 5549934b5aSJanis Schoetterl-Glausch report_prefix_pop(); 5649934b5aSJanis Schoetterl-Glausch 5749934b5aSJanis Schoetterl-Glausch report_prefix_push("on"); 5849934b5aSJanis Schoetterl-Glausch vm.sblk->ecb |= ECB_SPECI; 5949934b5aSJanis Schoetterl-Glausch reset_guest(); 6049934b5aSJanis Schoetterl-Glausch sie(&vm); 6149934b5aSJanis Schoetterl-Glausch /* interpretation on -> configuration dependent if initial exception causes 6249934b5aSJanis Schoetterl-Glausch * interception, but invalid new program PSW must 6349934b5aSJanis Schoetterl-Glausch */ 6449934b5aSJanis Schoetterl-Glausch report(vm.sblk->icptcode == ICPT_PROGI 6549934b5aSJanis Schoetterl-Glausch && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION, 6649934b5aSJanis Schoetterl-Glausch "Received specification exception intercept"); 67d05bf604SJanis Schoetterl-Glausch msg = "Interpreted initial exception, intercepted invalid program new PSW exception"; 68d05bf604SJanis Schoetterl-Glausch if (strict) 69d05bf604SJanis Schoetterl-Glausch report(vm.sblk->gpsw.addr == 0xdeadbeee, "%s", msg); 70d05bf604SJanis Schoetterl-Glausch else if (vm.sblk->gpsw.addr == 0xdeadbeee) 71d05bf604SJanis Schoetterl-Glausch report_info("%s", msg); 7249934b5aSJanis Schoetterl-Glausch else 7349934b5aSJanis Schoetterl-Glausch report_info("Did not interpret initial exception"); 7449934b5aSJanis Schoetterl-Glausch report_prefix_pop(); 7549934b5aSJanis Schoetterl-Glausch report_prefix_pop(); 7649934b5aSJanis Schoetterl-Glausch } 7749934b5aSJanis Schoetterl-Glausch 78d05bf604SJanis Schoetterl-Glausch static bool parse_strict(int argc, char **argv) 79d05bf604SJanis Schoetterl-Glausch { 80d05bf604SJanis Schoetterl-Glausch uint16_t machine_id; 81d05bf604SJanis Schoetterl-Glausch char *list; 82d05bf604SJanis Schoetterl-Glausch bool ret; 83d05bf604SJanis Schoetterl-Glausch 84d05bf604SJanis Schoetterl-Glausch if (argc < 1) 85d05bf604SJanis Schoetterl-Glausch return false; 86d05bf604SJanis Schoetterl-Glausch if (strcmp("--strict", argv[0])) 87d05bf604SJanis Schoetterl-Glausch return false; 88d05bf604SJanis Schoetterl-Glausch 89d05bf604SJanis Schoetterl-Glausch machine_id = get_machine_id(); 90d05bf604SJanis Schoetterl-Glausch if (argc < 2) { 91d05bf604SJanis Schoetterl-Glausch printf("No argument to --strict, ignoring\n"); 92d05bf604SJanis Schoetterl-Glausch return false; 93d05bf604SJanis Schoetterl-Glausch } 94d05bf604SJanis Schoetterl-Glausch list = argv[1]; 95d05bf604SJanis Schoetterl-Glausch if (list[0] == '!') { 96d05bf604SJanis Schoetterl-Glausch ret = true; 97d05bf604SJanis Schoetterl-Glausch list++; 98d05bf604SJanis Schoetterl-Glausch } else { 99d05bf604SJanis Schoetterl-Glausch ret = false; 100d05bf604SJanis Schoetterl-Glausch } 101d05bf604SJanis Schoetterl-Glausch while (true) { 102d05bf604SJanis Schoetterl-Glausch long input = 0; 103d05bf604SJanis Schoetterl-Glausch 104d05bf604SJanis Schoetterl-Glausch if (strlen(list) == 0) 105d05bf604SJanis Schoetterl-Glausch return ret; 106d05bf604SJanis Schoetterl-Glausch input = strtol(list, &list, 16); 107d05bf604SJanis Schoetterl-Glausch if (*list == ',') 108d05bf604SJanis Schoetterl-Glausch list++; 109d05bf604SJanis Schoetterl-Glausch else if (*list != '\0') 110d05bf604SJanis Schoetterl-Glausch break; 111d05bf604SJanis Schoetterl-Glausch if (input == machine_id) 112d05bf604SJanis Schoetterl-Glausch return !ret; 113d05bf604SJanis Schoetterl-Glausch } 114d05bf604SJanis Schoetterl-Glausch printf("Invalid --strict argument \"%s\", ignoring\n", list); 115d05bf604SJanis Schoetterl-Glausch return ret; 116d05bf604SJanis Schoetterl-Glausch } 117d05bf604SJanis Schoetterl-Glausch 11849934b5aSJanis Schoetterl-Glausch int main(int argc, char **argv) 11949934b5aSJanis Schoetterl-Glausch { 120d05bf604SJanis Schoetterl-Glausch strict = parse_strict(argc - 1, argv + 1); 12149934b5aSJanis Schoetterl-Glausch if (!sclp_facilities.has_sief2) { 12249934b5aSJanis Schoetterl-Glausch report_skip("SIEF2 facility unavailable"); 12349934b5aSJanis Schoetterl-Glausch goto out; 12449934b5aSJanis Schoetterl-Glausch } 12549934b5aSJanis Schoetterl-Glausch 12649934b5aSJanis Schoetterl-Glausch test_spec_ex_sie(); 12749934b5aSJanis Schoetterl-Glausch out: 12849934b5aSJanis Schoetterl-Glausch return report_summary(); 12949934b5aSJanis Schoetterl-Glausch } 130