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