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