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-icpt.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(sie_is_diag_icpt(&vm, 0x500), "intercept values"); 36 report(vm.save_area.guest.grs[1] == 1 && 37 vm.save_area.guest.grs[2] == 2 && 38 vm.save_area.guest.grs[3] == 3 && 39 vm.save_area.guest.grs[4] == 4, 40 "register values"); 41 /* 42 * Check if we can inject a PGM operand which we are always 43 * allowed to do after a diag500 exit. 44 */ 45 vm.sblk->iictl = IICTL_CODE_OPERAND; 46 sie(&vm); 47 report(sie_is_diag_icpt(&vm, 0x9c) && 48 vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND, 49 "operand exception"); 50 51 /* 52 * Check if we can inject a PGM specification which we are always 53 * allowed to do after a diag500 exit. 54 */ 55 sie(&vm); 56 vm.sblk->iictl = IICTL_CODE_SPECIFICATION; 57 /* Inject PGM, next exit should be 9c */ 58 sie(&vm); 59 report(sie_is_diag_icpt(&vm, 0x9c) && 60 vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION, 61 "specification exception"); 62 63 /* No need for cleanup, just tear down the VM */ 64 uv_destroy_guest(&vm); 65 66 report_prefix_pop(); 67 } 68 69 70 static void test_diag_288(void) 71 { 72 extern const char SNIPPET_NAME_START(asm, pv_diag_288)[]; 73 extern const char SNIPPET_NAME_END(asm, pv_diag_288)[]; 74 extern const char SNIPPET_HDR_START(asm, pv_diag_288)[]; 75 extern const char SNIPPET_HDR_END(asm, pv_diag_288)[]; 76 int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_288); 77 int size_gbin = SNIPPET_LEN(asm, pv_diag_288); 78 79 report_prefix_push("diag 0x288"); 80 81 snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_288), 82 SNIPPET_HDR_START(asm, pv_diag_288), 83 size_gbin, size_hdr, SNIPPET_UNPACK_OFF); 84 85 sie(&vm); 86 report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 && 87 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x288, 88 "intercept values"); 89 report(vm.save_area.guest.grs[0] == 1 && 90 vm.save_area.guest.grs[1] == 2 && 91 vm.save_area.guest.grs[2] == 3, 92 "register values"); 93 94 /* 95 * Check if we can inject a PGM spec which we are always 96 * allowed to do after a diag288 exit. 97 */ 98 vm.sblk->iictl = IICTL_CODE_SPECIFICATION; 99 sie(&vm); 100 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 101 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c 102 && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION, 103 "specification exception"); 104 105 /* No need for cleanup, just tear down the VM */ 106 uv_destroy_guest(&vm); 107 108 report_prefix_pop(); 109 } 110 111 static void test_diag_yield(void) 112 { 113 extern const char SNIPPET_NAME_START(asm, pv_diag_yield)[]; 114 extern const char SNIPPET_NAME_END(asm, pv_diag_yield)[]; 115 extern const char SNIPPET_HDR_START(asm, pv_diag_yield)[]; 116 extern const char SNIPPET_HDR_END(asm, pv_diag_yield)[]; 117 int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_yield); 118 int size_gbin = SNIPPET_LEN(asm, pv_diag_yield); 119 120 report_prefix_push("diag yield"); 121 122 snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_yield), 123 SNIPPET_HDR_START(asm, pv_diag_yield), 124 size_gbin, size_hdr, SNIPPET_UNPACK_OFF); 125 126 /* 0x44 */ 127 report_prefix_push("0x44"); 128 sie(&vm); 129 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 130 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x44, 131 "intercept values"); 132 report_prefix_pop(); 133 134 /* 0x9c */ 135 report_prefix_push("0x9c"); 136 sie(&vm); 137 report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && 138 vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c, 139 "intercept values"); 140 report(vm.save_area.guest.grs[0] == 42, "r1 correct"); 141 report_prefix_pop(); 142 143 uv_destroy_guest(&vm); 144 report_prefix_pop(); 145 } 146 147 148 int main(void) 149 { 150 report_prefix_push("pv-diags"); 151 if (!uv_host_requirement_checks()) 152 goto done; 153 154 uv_setup_asces(); 155 snippet_setup_guest(&vm, true); 156 test_diag_yield(); 157 test_diag_288(); 158 test_diag_500(); 159 sie_guest_destroy(&vm); 160 161 done: 162 report_prefix_pop(); 163 return report_summary(); 164 } 165