1 /* 2 * s390x Ultravisor related definitions 3 * 4 * Copyright (c) 2020 IBM Corp 5 * 6 * Authors: 7 * Janosch Frank <frankja@linux.ibm.com> 8 * 9 * This code is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License version 2. 11 */ 12 #ifndef _ASMS390X_UV_H_ 13 #define _ASMS390X_UV_H_ 14 15 #define UVC_RC_EXECUTED 0x0001 16 #define UVC_RC_INV_CMD 0x0002 17 #define UVC_RC_INV_STATE 0x0003 18 #define UVC_RC_INV_LEN 0x0005 19 #define UVC_RC_NO_RESUME 0x0007 20 #define UVC_RC_INV_GHANDLE 0x0020 21 #define UVC_RC_INV_CHANDLE 0x0021 22 23 #define UVC_CMD_QUI 0x0001 24 #define UVC_CMD_INIT_UV 0x000f 25 #define UVC_CMD_CREATE_SEC_CONF 0x0100 26 #define UVC_CMD_DESTROY_SEC_CONF 0x0101 27 #define UVC_CMD_CREATE_SEC_CPU 0x0120 28 #define UVC_CMD_DESTROY_SEC_CPU 0x0121 29 #define UVC_CMD_CONV_TO_SEC_STOR 0x0200 30 #define UVC_CMD_CONV_FROM_SEC_STOR 0x0201 31 #define UVC_CMD_SET_SEC_CONF_PARAMS 0x0300 32 #define UVC_CMD_UNPACK_IMG 0x0301 33 #define UVC_CMD_VERIFY_IMG 0x0302 34 #define UVC_CMD_CPU_RESET 0x0310 35 #define UVC_CMD_CPU_RESET_INITIAL 0x0311 36 #define UVC_CMD_PERF_CONF_CLEAR_RESET 0x0320 37 #define UVC_CMD_CPU_RESET_CLEAR 0x0321 38 #define UVC_CMD_CPU_SET_STATE 0x0330 39 #define UVC_CMD_SET_UNSHARED_ALL 0x0340 40 #define UVC_CMD_PIN_PAGE_SHARED 0x0341 41 #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 42 #define UVC_CMD_SET_SHARED_ACCESS 0x1000 43 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 44 45 /* Bits in installed uv calls */ 46 enum uv_cmds_inst { 47 BIT_UVC_CMD_QUI = 0, 48 BIT_UVC_CMD_INIT_UV = 1, 49 BIT_UVC_CMD_CREATE_SEC_CONF = 2, 50 BIT_UVC_CMD_DESTROY_SEC_CONF = 3, 51 BIT_UVC_CMD_CREATE_SEC_CPU = 4, 52 BIT_UVC_CMD_DESTROY_SEC_CPU = 5, 53 BIT_UVC_CMD_CONV_TO_SEC_STOR = 6, 54 BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7, 55 BIT_UVC_CMD_SET_SHARED_ACCESS = 8, 56 BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9, 57 BIT_UVC_CMD_SET_SEC_PARMS = 11, 58 BIT_UVC_CMD_UNPACK_IMG = 13, 59 BIT_UVC_CMD_VERIFY_IMG = 14, 60 BIT_UVC_CMD_CPU_RESET = 15, 61 BIT_UVC_CMD_CPU_RESET_INITIAL = 16, 62 BIT_UVC_CMD_CPU_SET_STATE = 17, 63 BIT_UVC_CMD_PREPARE_CLEAR_RESET = 18, 64 BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19, 65 BIT_UVC_CMD_UNSHARE_ALL = 20, 66 BIT_UVC_CMD_PIN_PAGE_SHARED = 21, 67 BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, 68 }; 69 70 struct uv_cb_header { 71 u16 len; 72 u16 cmd; /* Command Code */ 73 u16 rc; /* Response Code */ 74 u16 rrc; /* Return Reason Code */ 75 } __attribute__((packed)) __attribute__((aligned(8))); 76 77 struct uv_cb_init { 78 struct uv_cb_header header; 79 u64 reserved08[2]; 80 u64 stor_origin; 81 u64 stor_len; 82 u64 reserved28[4]; 83 84 } __attribute__((packed)) __attribute__((aligned(8))); 85 86 struct uv_cb_qui { 87 struct uv_cb_header header; /* 0x0000 */ 88 u64 reserved08; /* 0x0008 */ 89 u64 inst_calls_list[4]; /* 0x0010 */ 90 u64 reserved30[2]; /* 0x0030 */ 91 u64 uv_base_stor_len; /* 0x0040 */ 92 u64 reserved48; /* 0x0048 */ 93 u64 conf_base_phys_stor_len; /* 0x0050 */ 94 u64 conf_base_virt_stor_len; /* 0x0058 */ 95 u64 conf_virt_var_stor_len; /* 0x0060 */ 96 u64 cpu_stor_len; /* 0x0068 */ 97 u32 reserved70[3]; /* 0x0070 */ 98 u32 max_num_sec_conf; /* 0x007c */ 99 u64 max_guest_stor_addr; /* 0x0080 */ 100 u8 reserved88[158 - 136]; /* 0x0088 */ 101 uint16_t max_guest_cpus; /* 0x009e */ 102 u64 uv_feature_indications; /* 0x00a0 */ 103 u8 reserveda8[200 - 168]; /* 0x00a8 */ 104 } __attribute__((packed)) __attribute__((aligned(8))); 105 106 struct uv_cb_cgc { 107 struct uv_cb_header header; 108 u64 reserved08[2]; 109 u64 guest_handle; 110 u64 conf_base_stor_origin; 111 u64 conf_var_stor_origin; 112 u64 reserved30; 113 u64 guest_stor_origin; 114 u64 guest_stor_len; 115 u64 guest_sca; 116 u64 guest_asce; 117 u64 reserved60[5]; 118 } __attribute__((packed)) __attribute__((aligned(8))); 119 120 struct uv_cb_csc { 121 struct uv_cb_header header; 122 u64 reserved08[2]; 123 u64 cpu_handle; 124 u64 guest_handle; 125 u64 stor_origin; 126 u8 reserved30[6]; 127 u16 num; 128 u64 state_origin; 129 u64 reserved[4]; 130 } __attribute__((packed)) __attribute__((aligned(8))); 131 132 struct uv_cb_unp { 133 struct uv_cb_header header; 134 u64 reserved08[2]; 135 u64 guest_handle; 136 u64 gaddr; 137 u64 tweak[2]; 138 u64 reserved38[3]; 139 } __attribute__((packed)) __attribute__((aligned(8))); 140 141 /* 142 * A common UV call struct for the following calls: 143 * Destroy cpu/config 144 * Verify 145 */ 146 struct uv_cb_nodata { 147 struct uv_cb_header header; 148 u64 reserved08[2]; 149 u64 handle; 150 u64 reserved20[4]; 151 } __attribute__((packed)) __attribute__((aligned(8))); 152 153 struct uv_cb_share { 154 struct uv_cb_header header; 155 u64 reserved08[3]; 156 u64 paddr; 157 u64 reserved28; 158 } __attribute__((packed)) __attribute__((aligned(8))); 159 160 /* Convert to Secure */ 161 struct uv_cb_cts { 162 struct uv_cb_header header; 163 u64 reserved08[2]; 164 u64 guest_handle; 165 u64 gaddr; 166 } __attribute__((packed)) __attribute__((aligned(8))); 167 168 /* Convert from Secure / Pin Page Shared */ 169 struct uv_cb_cfs { 170 struct uv_cb_header header; 171 u64 reserved08[2]; 172 u64 paddr; 173 } __attribute__((packed)) __attribute__((aligned(8))); 174 175 /* Set Secure Config Parameter */ 176 struct uv_cb_ssc { 177 struct uv_cb_header header; 178 u64 reserved08[2]; 179 u64 guest_handle; 180 u64 sec_header_origin; 181 u32 sec_header_len; 182 u32 reserved2c; 183 u64 reserved30[4]; 184 } __attribute__((packed)) __attribute__((aligned(8))); 185 186 static inline int uv_call_once(unsigned long r1, unsigned long r2) 187 { 188 int cc; 189 190 asm volatile( 191 "0: .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n" 192 " ipm %[cc]\n" 193 " srl %[cc],28\n" 194 : [cc] "=d" (cc) 195 : [r1] "a" (r1), [r2] "a" (r2) 196 : "memory", "cc"); 197 return cc; 198 } 199 200 static inline int uv_call(unsigned long r1, unsigned long r2) 201 { 202 int cc; 203 204 /* 205 * CC 2 and 3 tell us to re-execute because the instruction 206 * hasn't yet finished. 207 */ 208 do { 209 cc = uv_call_once(r1, r2); 210 } while (cc > 1); 211 212 return cc; 213 } 214 215 static inline int share(unsigned long addr, u16 cmd) 216 { 217 struct uv_cb_share uvcb = { 218 .header.cmd = cmd, 219 .header.len = sizeof(uvcb), 220 .paddr = addr 221 }; 222 int cc; 223 224 cc = uv_call(0, (u64)&uvcb); 225 if (!cc && uvcb.header.rc == UVC_RC_EXECUTED) 226 return 0; 227 228 report_info("uv_call: cmd %04x cc %d response code: %04x", cc, cmd, 229 uvcb.header.rc); 230 return -1; 231 } 232 233 /* 234 * Guest 2 request to the Ultravisor to make a page shared with the 235 * hypervisor for IO. 236 * 237 * @addr: Real or absolute address of the page to be shared 238 */ 239 static inline int uv_set_shared(unsigned long addr) 240 { 241 return share(addr, UVC_CMD_SET_SHARED_ACCESS); 242 } 243 244 /* 245 * Guest 2 request to the Ultravisor to make a page unshared. 246 * 247 * @addr: Real or absolute address of the page to be unshared 248 */ 249 static inline int uv_remove_shared(unsigned long addr) 250 { 251 return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); 252 } 253 254 struct uv_cb_cpu_set_state { 255 struct uv_cb_header header; 256 u64 reserved08[2]; 257 u64 cpu_handle; 258 u8 reserved20[7]; 259 u8 state; 260 u64 reserved28[5]; 261 }; 262 263 #define PV_CPU_STATE_OPR 1 264 #define PV_CPU_STATE_STP 2 265 #define PV_CPU_STATE_CHKSTP 3 266 #define PV_CPU_STATE_OPR_LOAD 5 267 268 #endif 269