1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * PV virtualization interception tests for diagnose instructions. 4 * 5 * Copyright (c) 2021 IBM Corp 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.ibm.com> 9 */ 10 #include <libcflat.h> 11 #include <snippet.h> 12 #include <sie.h> 13 #include <sclp.h> 14 #include <asm/facility.h> 15 16 static struct vm vm; 17 18 static void test_diag_500(void) 19 { 20 extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_500)[]; 21 extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_500)[]; 22 extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_500)[]; 23 extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_500)[]; 24 int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_500); 25 int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_500); 26 27 report_prefix_push("diag 0x500"); 28 29 snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_500), 30 SNIPPET_HDR_START(asm, snippet_pv_diag_500), 31 size_gbin, size_hdr, SNIPPET_UNPACK_OFF); 32 33 sie(&vm); 34 report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 && 35 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x500, 36 "intercept values"); 37 report(vm.save_area.guest.grs[1] == 1 && 38 vm.save_area.guest.grs[2] == 2 && 39 vm.save_area.guest.grs[3] == 3 && 40 vm.save_area.guest.grs[4] == 4, 41 "register values"); 42 /* 43 * Check if we can inject a PGM operand which we are always 44 * allowed to do after a diag500 exit. 45 */ 46 vm.sblk->iictl = IICTL_CODE_OPERAND; 47 sie(&vm); 48 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 49 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c 50 && vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND, 51 "operand exception"); 52 53 /* 54 * Check if we can inject a PGM specification which we are always 55 * allowed to do after a diag500 exit. 56 */ 57 sie(&vm); 58 vm.sblk->iictl = IICTL_CODE_SPECIFICATION; 59 /* Inject PGM, next exit should be 9c */ 60 sie(&vm); 61 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 62 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c 63 && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION, 64 "specification exception"); 65 66 /* No need for cleanup, just tear down the VM */ 67 uv_destroy_guest(&vm); 68 69 report_prefix_pop(); 70 } 71 72 73 static void test_diag_288(void) 74 { 75 extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_288)[]; 76 extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_288)[]; 77 extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_288)[]; 78 extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_288)[]; 79 int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_288); 80 int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_288); 81 82 report_prefix_push("diag 0x288"); 83 84 snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_288), 85 SNIPPET_HDR_START(asm, snippet_pv_diag_288), 86 size_gbin, size_hdr, SNIPPET_UNPACK_OFF); 87 88 sie(&vm); 89 report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 && 90 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x288, 91 "intercept values"); 92 report(vm.save_area.guest.grs[0] == 1 && 93 vm.save_area.guest.grs[1] == 2 && 94 vm.save_area.guest.grs[2] == 3, 95 "register values"); 96 97 /* 98 * Check if we can inject a PGM spec which we are always 99 * allowed to do after a diag288 exit. 100 */ 101 vm.sblk->iictl = IICTL_CODE_SPECIFICATION; 102 sie(&vm); 103 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 104 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c 105 && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION, 106 "specification exception"); 107 108 /* No need for cleanup, just tear down the VM */ 109 uv_destroy_guest(&vm); 110 111 report_prefix_pop(); 112 } 113 114 static void test_diag_yield(void) 115 { 116 extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_yield)[]; 117 extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_yield)[]; 118 extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_yield)[]; 119 extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_yield)[]; 120 int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_yield); 121 int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_yield); 122 123 report_prefix_push("diag yield"); 124 125 snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_yield), 126 SNIPPET_HDR_START(asm, snippet_pv_diag_yield), 127 size_gbin, size_hdr, SNIPPET_UNPACK_OFF); 128 129 /* 0x44 */ 130 report_prefix_push("0x44"); 131 sie(&vm); 132 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 133 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x44, 134 "intercept values"); 135 report_prefix_pop(); 136 137 /* 0x9c */ 138 report_prefix_push("0x9c"); 139 sie(&vm); 140 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 141 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c, 142 "intercept values"); 143 report(vm.save_area.guest.grs[0] == 42, "r1 correct"); 144 report_prefix_pop(); 145 146 uv_destroy_guest(&vm); 147 report_prefix_pop(); 148 } 149 150 151 int main(void) 152 { 153 report_prefix_push("pv-diags"); 154 if (!test_facility(158)) { 155 report_skip("UV Call facility unavailable"); 156 goto done; 157 } 158 if (!sclp_facilities.has_sief2) { 159 report_skip("SIEF2 facility unavailable"); 160 goto done; 161 } 162 163 uv_setup_asces(); 164 snippet_setup_guest(&vm, true); 165 test_diag_yield(); 166 test_diag_288(); 167 test_diag_500(); 168 sie_guest_destroy(&vm); 169 170 done: 171 report_prefix_pop(); 172 return report_summary(); 173 } 174