1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Guest Ultravisor Call tests 4 * 5 * Copyright (c) 2020 IBM Corp 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.ibm.com> 9 */ 10 11 #include <libcflat.h> 12 #include <alloc_page.h> 13 #include <asm/page.h> 14 #include <asm/asm-offsets.h> 15 #include <asm/interrupt.h> 16 #include <asm/facility.h> 17 #include <asm/uv.h> 18 19 static unsigned long page; 20 21 static void test_priv(void) 22 { 23 struct uv_cb_header uvcb = {}; 24 25 report_prefix_push("privileged"); 26 27 report_prefix_push("query"); 28 uvcb.cmd = UVC_CMD_QUI; 29 uvcb.len = sizeof(struct uv_cb_qui); 30 expect_pgm_int(); 31 enter_pstate(); 32 uv_call_once(0, (u64)&uvcb); 33 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 34 report_prefix_pop(); 35 36 report_prefix_push("share"); 37 uvcb.cmd = UVC_CMD_SET_SHARED_ACCESS; 38 uvcb.len = sizeof(struct uv_cb_share); 39 expect_pgm_int(); 40 enter_pstate(); 41 uv_call_once(0, (u64)&uvcb); 42 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 43 report_prefix_pop(); 44 45 report_prefix_push("unshare"); 46 uvcb.cmd = UVC_CMD_REMOVE_SHARED_ACCESS; 47 uvcb.len = sizeof(struct uv_cb_share); 48 expect_pgm_int(); 49 enter_pstate(); 50 uv_call_once(0, (u64)&uvcb); 51 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 52 report_prefix_pop(); 53 54 report_prefix_pop(); 55 } 56 57 static void test_query(void) 58 { 59 struct uv_cb_qui uvcb = { 60 .header.cmd = UVC_CMD_QUI, 61 .header.len = sizeof(uvcb) - 8, 62 }; 63 int cc; 64 65 report_prefix_push("query"); 66 cc = uv_call(0, (u64)&uvcb); 67 report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length"); 68 69 uvcb.header.len = sizeof(uvcb); 70 cc = uv_call(0, (u64)&uvcb); 71 report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "successful query"); 72 73 /* 74 * These bits have been introduced with the very first 75 * Ultravisor version and are expected to always be available 76 * because they are basic building blocks. 77 */ 78 report(test_bit_inv(BIT_UVC_CMD_QUI, &uvcb.inst_calls_list[0]), 79 "query indicated"); 80 report(test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, &uvcb.inst_calls_list[0]), 81 "share indicated"); 82 report(test_bit_inv(BIT_UVC_CMD_REMOVE_SHARED_ACCESS, &uvcb.inst_calls_list[0]), 83 "unshare indicated"); 84 report_prefix_pop(); 85 } 86 87 static void test_sharing(void) 88 { 89 struct uv_cb_share uvcb = { 90 .header.cmd = UVC_CMD_SET_SHARED_ACCESS, 91 .header.len = sizeof(uvcb) - 8, 92 .paddr = page, 93 }; 94 int cc; 95 96 report_prefix_push("share"); 97 cc = uv_call(0, (u64)&uvcb); 98 report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length"); 99 uvcb.header.len = sizeof(uvcb); 100 cc = uv_call(0, (u64)&uvcb); 101 report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "share"); 102 report_prefix_pop(); 103 104 report_prefix_push("unshare"); 105 uvcb.header.cmd = UVC_CMD_REMOVE_SHARED_ACCESS; 106 uvcb.header.len -= 8; 107 cc = uv_call(0, (u64)&uvcb); 108 report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length"); 109 uvcb.header.len = sizeof(uvcb); 110 cc = uv_call(0, (u64)&uvcb); 111 report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "unshare"); 112 report_prefix_pop(); 113 114 report_prefix_pop(); 115 } 116 117 static void test_invalid(void) 118 { 119 struct uv_cb_header uvcb = { 120 .len = 16, 121 .cmd = 0x4242, 122 }; 123 int cc; 124 125 cc = uv_call(0, (u64)&uvcb); 126 report(cc == 1 && uvcb.rc == UVC_RC_INV_CMD, "invalid command"); 127 } 128 129 int main(void) 130 { 131 bool has_uvc = test_facility(158); 132 133 report_prefix_push("uvc"); 134 if (!has_uvc) { 135 report_skip("Ultravisor call facility is not available"); 136 goto done; 137 } 138 139 page = (unsigned long)alloc_page(); 140 test_priv(); 141 test_invalid(); 142 test_query(); 143 test_sharing(); 144 free_page((void *)page); 145 done: 146 report_prefix_pop(); 147 return report_summary(); 148 } 149