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