1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Tests SIE diagnose intercepts. 4 * Mainly used as a template for SIE tests. 5 * 6 * Copyright 2021 IBM Corp. 7 * 8 * Authors: 9 * Janosch Frank <frankja@linux.ibm.com> 10 */ 11 #include <libcflat.h> 12 #include <asm/asm-offsets.h> 13 #include <asm/arch_def.h> 14 #include <asm/interrupt.h> 15 #include <asm/page.h> 16 #include <alloc_page.h> 17 #include <vmalloc.h> 18 #include <asm/facility.h> 19 #include <mmu.h> 20 #include <sclp.h> 21 #include <sie.h> 22 23 static u8 *guest; 24 static u8 *guest_instr; 25 static struct vm vm; 26 27 static void test_diag(u32 instr) 28 { 29 vm.sblk->gpsw.addr = PAGE_SIZE * 2; 30 vm.sblk->gpsw.mask = PSW_MASK_64; 31 32 memset(guest_instr, 0, PAGE_SIZE); 33 memcpy(guest_instr, &instr, 4); 34 sie(&vm); 35 report(vm.sblk->icptcode == ICPT_INST && 36 vm.sblk->ipa == instr >> 16 && vm.sblk->ipb == instr << 16, 37 "Intercept data"); 38 } 39 40 static struct { 41 const char *name; 42 u32 instr; 43 } tests[] = { 44 { "10", 0x83020010 }, 45 { "44", 0x83020044 }, 46 { "9c", 0x8302009c }, 47 { NULL, 0 } 48 }; 49 50 static void test_diags(void) 51 { 52 int i; 53 54 for (i = 0; tests[i].name; i++) { 55 report_prefix_push(tests[i].name); 56 test_diag(tests[i].instr); 57 report_prefix_pop(); 58 } 59 } 60 61 static void test_epoch_ext(void) 62 { 63 u32 instr[] = { 64 0xb2780000, /* STCKE 0 */ 65 0x83000044 /* DIAG 0x44 to intercept */ 66 }; 67 68 if (!test_facility(139)) { 69 report_skip("epdx: Multiple Epoch Facility is not available"); 70 return; 71 } 72 73 guest[0] = 0x00; 74 memcpy(guest_instr, instr, sizeof(instr)); 75 76 vm.sblk->gpsw.addr = PAGE_SIZE * 2; 77 vm.sblk->gpsw.mask = PSW_MASK_64; 78 79 vm.sblk->ecd |= ECD_MEF; 80 vm.sblk->epdx = 0x47; /* Setting the epoch extension here ... */ 81 82 sie(&vm); 83 84 /* ... should result in the same epoch extension here: */ 85 report(guest[0] == 0x47, "epdx: different epoch is visible in the guest"); 86 } 87 88 static void setup_guest(void) 89 { 90 setup_vm(); 91 92 /* Allocate 1MB as guest memory */ 93 guest = alloc_pages(8); 94 /* The first two pages are the lowcore */ 95 guest_instr = guest + PAGE_SIZE * 2; 96 97 sie_guest_create(&vm, (uint64_t)guest, HPAGE_SIZE); 98 } 99 100 int main(void) 101 { 102 report_prefix_push("sie"); 103 if (!sclp_facilities.has_sief2) { 104 report_skip("SIEF2 facility unavailable"); 105 goto done; 106 } 107 108 setup_guest(); 109 test_diags(); 110 test_epoch_ext(); 111 sie_guest_destroy(&vm); 112 113 done: 114 report_prefix_pop(); 115 return report_summary(); 116 } 117