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 /* Enables printing of command code and return codes for failed UVCs */ 16 #ifndef UVC_ERR_DEBUG 17 #define UVC_ERR_DEBUG 0 18 #endif 19 20 #define UVC_RC_EXECUTED 0x0001 21 #define UVC_RC_INV_CMD 0x0002 22 #define UVC_RC_INV_STATE 0x0003 23 #define UVC_RC_INV_LEN 0x0005 24 #define UVC_RC_NO_RESUME 0x0007 25 #define UVC_RC_INV_GHANDLE 0x0020 26 #define UVC_RC_INV_CHANDLE 0x0021 27 28 #define UVC_CMD_QUI 0x0001 29 #define UVC_CMD_INIT_UV 0x000f 30 #define UVC_CMD_CREATE_SEC_CONF 0x0100 31 #define UVC_CMD_DESTROY_SEC_CONF 0x0101 32 #define UVC_CMD_CREATE_SEC_CPU 0x0120 33 #define UVC_CMD_DESTROY_SEC_CPU 0x0121 34 #define UVC_CMD_CONV_TO_SEC_STOR 0x0200 35 #define UVC_CMD_CONV_FROM_SEC_STOR 0x0201 36 #define UVC_CMD_DESTR_SEC_STOR 0x0202 37 #define UVC_CMD_SET_SEC_CONF_PARAMS 0x0300 38 #define UVC_CMD_UNPACK_IMG 0x0301 39 #define UVC_CMD_VERIFY_IMG 0x0302 40 #define UVC_CMD_CPU_RESET 0x0310 41 #define UVC_CMD_CPU_RESET_INITIAL 0x0311 42 #define UVC_CMD_PREPARE_RESET 0x0320 43 #define UVC_CMD_CPU_RESET_CLEAR 0x0321 44 #define UVC_CMD_CPU_SET_STATE 0x0330 45 #define UVC_CMD_SET_UNSHARED_ALL 0x0340 46 #define UVC_CMD_PIN_PAGE_SHARED 0x0341 47 #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 48 #define UVC_CMD_SET_SHARED_ACCESS 0x1000 49 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 50 51 /* Bits in installed uv calls */ 52 enum uv_cmds_inst { 53 BIT_UVC_CMD_QUI = 0, 54 BIT_UVC_CMD_INIT_UV = 1, 55 BIT_UVC_CMD_CREATE_SEC_CONF = 2, 56 BIT_UVC_CMD_DESTROY_SEC_CONF = 3, 57 BIT_UVC_CMD_CREATE_SEC_CPU = 4, 58 BIT_UVC_CMD_DESTROY_SEC_CPU = 5, 59 BIT_UVC_CMD_CONV_TO_SEC_STOR = 6, 60 BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7, 61 BIT_UVC_CMD_SET_SHARED_ACCESS = 8, 62 BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9, 63 BIT_UVC_CMD_SET_SEC_PARMS = 11, 64 BIT_UVC_CMD_UNPACK_IMG = 13, 65 BIT_UVC_CMD_VERIFY_IMG = 14, 66 BIT_UVC_CMD_CPU_RESET = 15, 67 BIT_UVC_CMD_CPU_RESET_INITIAL = 16, 68 BIT_UVC_CMD_CPU_SET_STATE = 17, 69 BIT_UVC_CMD_PREPARE_RESET = 18, 70 BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19, 71 BIT_UVC_CMD_UNSHARE_ALL = 20, 72 BIT_UVC_CMD_PIN_PAGE_SHARED = 21, 73 BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, 74 }; 75 76 struct uv_cb_header { 77 u16 len; 78 u16 cmd; /* Command Code */ 79 u16 rc; /* Response Code */ 80 u16 rrc; /* Return Reason Code */ 81 } __attribute__((packed)) __attribute__((aligned(8))); 82 83 struct uv_cb_init { 84 struct uv_cb_header header; 85 u64 reserved08[2]; 86 u64 stor_origin; 87 u64 stor_len; 88 u64 reserved28[4]; 89 90 } __attribute__((packed)) __attribute__((aligned(8))); 91 92 struct uv_cb_qui { 93 struct uv_cb_header header; /* 0x0000 */ 94 u64 reserved08; /* 0x0008 */ 95 u64 inst_calls_list[4]; /* 0x0010 */ 96 u64 reserved30[2]; /* 0x0030 */ 97 u64 uv_base_stor_len; /* 0x0040 */ 98 u64 reserved48; /* 0x0048 */ 99 u64 conf_base_phys_stor_len; /* 0x0050 */ 100 u64 conf_base_virt_stor_len; /* 0x0058 */ 101 u64 conf_virt_var_stor_len; /* 0x0060 */ 102 u64 cpu_stor_len; /* 0x0068 */ 103 u32 reserved70[3]; /* 0x0070 */ 104 u32 max_num_sec_conf; /* 0x007c */ 105 u64 max_guest_stor_addr; /* 0x0080 */ 106 u8 reserved88[158 - 136]; /* 0x0088 */ 107 uint16_t max_guest_cpus; /* 0x009e */ 108 u64 uv_feature_indications; /* 0x00a0 */ 109 u8 reserveda8[200 - 168]; /* 0x00a8 */ 110 } __attribute__((packed)) __attribute__((aligned(8))); 111 112 struct uv_cb_cgc { 113 struct uv_cb_header header; 114 u64 reserved08[2]; 115 u64 guest_handle; 116 u64 conf_base_stor_origin; 117 u64 conf_var_stor_origin; 118 u64 reserved30; 119 u64 guest_stor_origin; 120 u64 guest_stor_len; 121 u64 guest_sca; 122 u64 guest_asce; 123 u64 reserved60[5]; 124 } __attribute__((packed)) __attribute__((aligned(8))); 125 126 struct uv_cb_csc { 127 struct uv_cb_header header; 128 u64 reserved08[2]; 129 u64 cpu_handle; 130 u64 guest_handle; 131 u64 stor_origin; 132 u8 reserved30[6]; 133 u16 num; 134 u64 state_origin; 135 u64 reserved[4]; 136 } __attribute__((packed)) __attribute__((aligned(8))); 137 138 struct uv_cb_unp { 139 struct uv_cb_header header; 140 u64 reserved08[2]; 141 u64 guest_handle; 142 u64 gaddr; 143 u64 tweak[2]; 144 u64 reserved38[3]; 145 } __attribute__((packed)) __attribute__((aligned(8))); 146 147 /* 148 * A common UV call struct for the following calls: 149 * Destroy cpu/config 150 * Verify 151 */ 152 struct uv_cb_nodata { 153 struct uv_cb_header header; 154 u64 reserved08[2]; 155 u64 handle; 156 u64 reserved20[4]; 157 } __attribute__((packed)) __attribute__((aligned(8))); 158 159 struct uv_cb_share { 160 struct uv_cb_header header; 161 u64 reserved08[3]; 162 u64 paddr; 163 u64 reserved28; 164 } __attribute__((packed)) __attribute__((aligned(8))); 165 166 /* Convert to Secure */ 167 struct uv_cb_cts { 168 struct uv_cb_header header; 169 u64 reserved08[2]; 170 u64 guest_handle; 171 u64 gaddr; 172 } __attribute__((packed)) __attribute__((aligned(8))); 173 174 /* Convert from Secure / Pin Page Shared */ 175 struct uv_cb_cfs { 176 struct uv_cb_header header; 177 u64 reserved08[2]; 178 u64 paddr; 179 } __attribute__((packed)) __attribute__((aligned(8))); 180 181 /* Set Secure Config Parameter */ 182 struct uv_cb_ssc { 183 struct uv_cb_header header; 184 u64 reserved08[2]; 185 u64 guest_handle; 186 u64 sec_header_origin; 187 u32 sec_header_len; 188 u32 reserved2c; 189 u64 reserved30[4]; 190 } __attribute__((packed)) __attribute__((aligned(8))); 191 192 static inline int uv_call_once(unsigned long r1, unsigned long r2) 193 { 194 int cc; 195 196 asm volatile( 197 "0: .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n" 198 " ipm %[cc]\n" 199 " srl %[cc],28\n" 200 : [cc] "=d" (cc) 201 : [r1] "a" (r1), [r2] "a" (r2) 202 : "memory", "cc"); 203 204 if (UVC_ERR_DEBUG && cc == 1) 205 printf("UV call error: call %x rc %x rrc %x\n", 206 ((struct uv_cb_header *)r2)->cmd, 207 ((struct uv_cb_header *)r2)->rc, 208 ((struct uv_cb_header *)r2)->rrc); 209 210 return cc; 211 } 212 213 static inline int uv_call(unsigned long r1, unsigned long r2) 214 { 215 int cc; 216 217 /* 218 * CC 2 and 3 tell us to re-execute because the instruction 219 * hasn't yet finished. 220 */ 221 do { 222 cc = uv_call_once(r1, r2); 223 } while (cc > 1); 224 225 return cc; 226 } 227 228 static inline int share(unsigned long addr, u16 cmd) 229 { 230 struct uv_cb_share uvcb = { 231 .header.cmd = cmd, 232 .header.len = sizeof(uvcb), 233 .paddr = addr 234 }; 235 236 return uv_call(0, (u64)&uvcb); 237 } 238 239 /* 240 * Guest 2 request to the Ultravisor to make a page shared with the 241 * hypervisor for IO. 242 * 243 * @addr: Real or absolute address of the page to be shared 244 */ 245 static inline int uv_set_shared(unsigned long addr) 246 { 247 return share(addr, UVC_CMD_SET_SHARED_ACCESS); 248 } 249 250 /* 251 * Guest 2 request to the Ultravisor to make a page unshared. 252 * 253 * @addr: Real or absolute address of the page to be unshared 254 */ 255 static inline int uv_remove_shared(unsigned long addr) 256 { 257 return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); 258 } 259 260 static inline int uv_cmd_nodata(uint64_t handle, uint16_t cmd, uint16_t *rc, uint16_t *rrc) 261 { 262 struct uv_cb_nodata uvcb = { 263 .header.cmd = cmd, 264 .header.len = sizeof(uvcb), 265 .handle = handle, 266 }; 267 int cc; 268 269 assert(handle); 270 cc = uv_call(0, (uint64_t)&uvcb); 271 *rc = uvcb.header.rc; 272 *rrc = uvcb.header.rrc; 273 return cc; 274 } 275 276 static inline int uv_import(uint64_t handle, unsigned long gaddr) 277 { 278 struct uv_cb_cts uvcb = { 279 .header.cmd = UVC_CMD_CONV_TO_SEC_STOR, 280 .header.len = sizeof(uvcb), 281 .guest_handle = handle, 282 .gaddr = gaddr, 283 }; 284 285 return uv_call(0, (uint64_t)&uvcb); 286 } 287 288 static inline int uv_export(unsigned long paddr) 289 { 290 struct uv_cb_cfs uvcb = { 291 .header.cmd = UVC_CMD_CONV_FROM_SEC_STOR, 292 .header.len = sizeof(uvcb), 293 .paddr = paddr 294 }; 295 296 return uv_call(0, (u64)&uvcb); 297 } 298 299 /* 300 * Requests the Ultravisor to destroy a guest page and make it 301 * accessible to the host. The destroy clears the page instead of 302 * exporting. 303 * 304 * @paddr: Absolute host address of page to be destroyed 305 */ 306 static inline int uv_destroy_page(unsigned long paddr) 307 { 308 struct uv_cb_cfs uvcb = { 309 .header.cmd = UVC_CMD_DESTR_SEC_STOR, 310 .header.len = sizeof(uvcb), 311 .paddr = paddr 312 }; 313 314 return uv_call(0, (uint64_t)&uvcb); 315 } 316 317 struct uv_cb_cpu_set_state { 318 struct uv_cb_header header; 319 u64 reserved08[2]; 320 u64 cpu_handle; 321 u8 reserved20[7]; 322 u8 state; 323 u64 reserved28[5]; 324 }; 325 326 #define PV_CPU_STATE_OPR 1 327 #define PV_CPU_STATE_STP 2 328 #define PV_CPU_STATE_CHKSTP 3 329 #define PV_CPU_STATE_OPR_LOAD 5 330 331 static inline int uv_set_cpu_state(uint64_t handle, uint8_t state) 332 { 333 struct uv_cb_cpu_set_state uvcb = { 334 .header.cmd = UVC_CMD_CPU_SET_STATE, 335 .header.len = sizeof(uvcb), 336 .cpu_handle = handle, 337 .state = state, 338 }; 339 340 assert(handle); 341 return uv_call(0, (uint64_t)&uvcb); 342 } 343 344 static inline int uv_set_se_hdr(uint64_t handle, void *hdr, size_t len) 345 { 346 struct uv_cb_ssc uvcb = { 347 .header.cmd = UVC_CMD_SET_SEC_CONF_PARAMS, 348 .header.len = sizeof(uvcb), 349 .sec_header_origin = (uint64_t)hdr, 350 .sec_header_len = len, 351 .guest_handle = handle, 352 }; 353 354 assert(handle); 355 return uv_call(0, (uint64_t)&uvcb); 356 } 357 358 static inline int uv_unp_page(uint64_t handle, uint64_t gaddr, uint64_t tweak1, uint64_t tweak2) 359 { 360 struct uv_cb_unp uvcb = { 361 .header.cmd = UVC_CMD_UNPACK_IMG, 362 .header.len = sizeof(uvcb), 363 .guest_handle = handle, 364 .gaddr = gaddr, 365 .tweak[0] = tweak1, 366 .tweak[1] = tweak2, 367 }; 368 369 return uv_call(0, (uint64_t)&uvcb); 370 } 371 372 #endif 373