12ea7afb6SJanosch Frank /* 22ea7afb6SJanosch Frank * s390x Ultravisor related definitions 32ea7afb6SJanosch Frank * 42ea7afb6SJanosch Frank * Copyright (c) 2020 IBM Corp 52ea7afb6SJanosch Frank * 62ea7afb6SJanosch Frank * Authors: 72ea7afb6SJanosch Frank * Janosch Frank <frankja@linux.ibm.com> 82ea7afb6SJanosch Frank * 92ea7afb6SJanosch Frank * This code is free software; you can redistribute it and/or modify it 102ea7afb6SJanosch Frank * under the terms of the GNU General Public License version 2. 112ea7afb6SJanosch Frank */ 122ea7afb6SJanosch Frank #ifndef UV_H 132ea7afb6SJanosch Frank #define UV_H 142ea7afb6SJanosch Frank 152ea7afb6SJanosch Frank #define UVC_RC_EXECUTED 0x0001 162ea7afb6SJanosch Frank #define UVC_RC_INV_CMD 0x0002 172ea7afb6SJanosch Frank #define UVC_RC_INV_STATE 0x0003 182ea7afb6SJanosch Frank #define UVC_RC_INV_LEN 0x0005 192ea7afb6SJanosch Frank #define UVC_RC_NO_RESUME 0x0007 20*83d815a2SJanosch Frank #define UVC_RC_INV_GHANDLE 0x0020 21*83d815a2SJanosch Frank #define UVC_RC_INV_CHANDLE 0x0021 222ea7afb6SJanosch Frank 232ea7afb6SJanosch Frank #define UVC_CMD_QUI 0x0001 24*83d815a2SJanosch Frank #define UVC_CMD_INIT_UV 0x000f 25*83d815a2SJanosch Frank #define UVC_CMD_CREATE_SEC_CONF 0x0100 26*83d815a2SJanosch Frank #define UVC_CMD_DESTROY_SEC_CONF 0x0101 27*83d815a2SJanosch Frank #define UVC_CMD_CREATE_SEC_CPU 0x0120 28*83d815a2SJanosch Frank #define UVC_CMD_DESTROY_SEC_CPU 0x0121 29*83d815a2SJanosch Frank #define UVC_CMD_CONV_TO_SEC_STOR 0x0200 30*83d815a2SJanosch Frank #define UVC_CMD_CONV_FROM_SEC_STOR 0x0201 31*83d815a2SJanosch Frank #define UVC_CMD_SET_SEC_CONF_PARAMS 0x0300 32*83d815a2SJanosch Frank #define UVC_CMD_UNPACK_IMG 0x0301 33*83d815a2SJanosch Frank #define UVC_CMD_VERIFY_IMG 0x0302 34*83d815a2SJanosch Frank #define UVC_CMD_CPU_RESET 0x0310 35*83d815a2SJanosch Frank #define UVC_CMD_CPU_RESET_INITIAL 0x0311 36*83d815a2SJanosch Frank #define UVC_CMD_PERF_CONF_CLEAR_RESET 0x0320 37*83d815a2SJanosch Frank #define UVC_CMD_CPU_RESET_CLEAR 0x0321 38*83d815a2SJanosch Frank #define UVC_CMD_CPU_SET_STATE 0x0330 39*83d815a2SJanosch Frank #define UVC_CMD_SET_UNSHARED_ALL 0x0340 40*83d815a2SJanosch Frank #define UVC_CMD_PIN_PAGE_SHARED 0x0341 41*83d815a2SJanosch Frank #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 422ea7afb6SJanosch Frank #define UVC_CMD_SET_SHARED_ACCESS 0x1000 432ea7afb6SJanosch Frank #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 442ea7afb6SJanosch Frank 452ea7afb6SJanosch Frank /* Bits in installed uv calls */ 462ea7afb6SJanosch Frank enum uv_cmds_inst { 472ea7afb6SJanosch Frank BIT_UVC_CMD_QUI = 0, 48*83d815a2SJanosch Frank BIT_UVC_CMD_INIT_UV = 1, 49*83d815a2SJanosch Frank BIT_UVC_CMD_CREATE_SEC_CONF = 2, 50*83d815a2SJanosch Frank BIT_UVC_CMD_DESTROY_SEC_CONF = 3, 51*83d815a2SJanosch Frank BIT_UVC_CMD_CREATE_SEC_CPU = 4, 52*83d815a2SJanosch Frank BIT_UVC_CMD_DESTROY_SEC_CPU = 5, 53*83d815a2SJanosch Frank BIT_UVC_CMD_CONV_TO_SEC_STOR = 6, 54*83d815a2SJanosch Frank BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7, 552ea7afb6SJanosch Frank BIT_UVC_CMD_SET_SHARED_ACCESS = 8, 562ea7afb6SJanosch Frank BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9, 57*83d815a2SJanosch Frank BIT_UVC_CMD_SET_SEC_PARMS = 11, 58*83d815a2SJanosch Frank BIT_UVC_CMD_UNPACK_IMG = 13, 59*83d815a2SJanosch Frank BIT_UVC_CMD_VERIFY_IMG = 14, 60*83d815a2SJanosch Frank BIT_UVC_CMD_CPU_RESET = 15, 61*83d815a2SJanosch Frank BIT_UVC_CMD_CPU_RESET_INITIAL = 16, 62*83d815a2SJanosch Frank BIT_UVC_CMD_CPU_SET_STATE = 17, 63*83d815a2SJanosch Frank BIT_UVC_CMD_PREPARE_CLEAR_RESET = 18, 64*83d815a2SJanosch Frank BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19, 65*83d815a2SJanosch Frank BIT_UVC_CMD_UNSHARE_ALL = 20, 66*83d815a2SJanosch Frank BIT_UVC_CMD_PIN_PAGE_SHARED = 21, 67*83d815a2SJanosch Frank BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, 682ea7afb6SJanosch Frank }; 692ea7afb6SJanosch Frank 702ea7afb6SJanosch Frank struct uv_cb_header { 712ea7afb6SJanosch Frank u16 len; 722ea7afb6SJanosch Frank u16 cmd; /* Command Code */ 732ea7afb6SJanosch Frank u16 rc; /* Response Code */ 742ea7afb6SJanosch Frank u16 rrc; /* Return Reason Code */ 752ea7afb6SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 762ea7afb6SJanosch Frank 77*83d815a2SJanosch Frank struct uv_cb_init { 78*83d815a2SJanosch Frank struct uv_cb_header header; 79*83d815a2SJanosch Frank u64 reserved08[2]; 80*83d815a2SJanosch Frank u64 stor_origin; 81*83d815a2SJanosch Frank u64 stor_len; 82*83d815a2SJanosch Frank u64 reserved28[4]; 83*83d815a2SJanosch Frank 84*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 85*83d815a2SJanosch Frank 862ea7afb6SJanosch Frank struct uv_cb_qui { 872ea7afb6SJanosch Frank struct uv_cb_header header; 882ea7afb6SJanosch Frank u64 reserved08; 892ea7afb6SJanosch Frank u64 inst_calls_list[4]; 90*83d815a2SJanosch Frank u64 reserved30[2]; 91*83d815a2SJanosch Frank u64 uv_base_stor_len; 92*83d815a2SJanosch Frank u64 reserved48; 93*83d815a2SJanosch Frank u64 conf_base_phys_stor_len; 94*83d815a2SJanosch Frank u64 conf_base_virt_stor_len; 95*83d815a2SJanosch Frank u64 conf_virt_var_stor_len; 96*83d815a2SJanosch Frank u64 cpu_stor_len; 97*83d815a2SJanosch Frank u32 reserved70[3]; 98*83d815a2SJanosch Frank u32 max_num_sec_conf; 99*83d815a2SJanosch Frank u64 max_guest_stor_addr; 100*83d815a2SJanosch Frank u8 reserved88[158 - 136]; 101*83d815a2SJanosch Frank u16 max_guest_cpus; 102*83d815a2SJanosch Frank u8 reserveda0[200 - 160]; 103*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 104*83d815a2SJanosch Frank 105*83d815a2SJanosch Frank struct uv_cb_cgc { 106*83d815a2SJanosch Frank struct uv_cb_header header; 107*83d815a2SJanosch Frank u64 reserved08[2]; 108*83d815a2SJanosch Frank u64 guest_handle; 109*83d815a2SJanosch Frank u64 conf_base_stor_origin; 110*83d815a2SJanosch Frank u64 conf_var_stor_origin; 111*83d815a2SJanosch Frank u64 reserved30; 112*83d815a2SJanosch Frank u64 guest_stor_origin; 113*83d815a2SJanosch Frank u64 guest_stor_len; 114*83d815a2SJanosch Frank u64 guest_sca; 115*83d815a2SJanosch Frank u64 guest_asce; 116*83d815a2SJanosch Frank u64 reserved60[5]; 117*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 118*83d815a2SJanosch Frank 119*83d815a2SJanosch Frank struct uv_cb_csc { 120*83d815a2SJanosch Frank struct uv_cb_header header; 121*83d815a2SJanosch Frank u64 reserved08[2]; 122*83d815a2SJanosch Frank u64 cpu_handle; 123*83d815a2SJanosch Frank u64 guest_handle; 124*83d815a2SJanosch Frank u64 stor_origin; 125*83d815a2SJanosch Frank u8 reserved30[6]; 126*83d815a2SJanosch Frank u16 num; 127*83d815a2SJanosch Frank u64 state_origin; 128*83d815a2SJanosch Frank u64 reserved[4]; 129*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 130*83d815a2SJanosch Frank 131*83d815a2SJanosch Frank struct uv_cb_unp { 132*83d815a2SJanosch Frank struct uv_cb_header header; 133*83d815a2SJanosch Frank u64 reserved08[2]; 134*83d815a2SJanosch Frank u64 guest_handle; 135*83d815a2SJanosch Frank u64 gaddr; 136*83d815a2SJanosch Frank u64 tweak[2]; 137*83d815a2SJanosch Frank u64 reserved38[3]; 138*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 139*83d815a2SJanosch Frank 140*83d815a2SJanosch Frank /* 141*83d815a2SJanosch Frank * A common UV call struct for the following calls: 142*83d815a2SJanosch Frank * Destroy cpu/config 143*83d815a2SJanosch Frank * Verify 144*83d815a2SJanosch Frank */ 145*83d815a2SJanosch Frank struct uv_cb_nodata { 146*83d815a2SJanosch Frank struct uv_cb_header header; 147*83d815a2SJanosch Frank u64 reserved08[2]; 148*83d815a2SJanosch Frank u64 handle; 149*83d815a2SJanosch Frank u64 reserved20[4]; 1502ea7afb6SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 1512ea7afb6SJanosch Frank 1522ea7afb6SJanosch Frank struct uv_cb_share { 1532ea7afb6SJanosch Frank struct uv_cb_header header; 1542ea7afb6SJanosch Frank u64 reserved08[3]; 1552ea7afb6SJanosch Frank u64 paddr; 1562ea7afb6SJanosch Frank u64 reserved28; 1572ea7afb6SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 1582ea7afb6SJanosch Frank 159*83d815a2SJanosch Frank /* Convert to Secure */ 160*83d815a2SJanosch Frank struct uv_cb_cts { 161*83d815a2SJanosch Frank struct uv_cb_header header; 162*83d815a2SJanosch Frank u64 reserved08[2]; 163*83d815a2SJanosch Frank u64 guest_handle; 164*83d815a2SJanosch Frank u64 gaddr; 165*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 166*83d815a2SJanosch Frank 167*83d815a2SJanosch Frank /* Convert from Secure / Pin Page Shared */ 168*83d815a2SJanosch Frank struct uv_cb_cfs { 169*83d815a2SJanosch Frank struct uv_cb_header header; 170*83d815a2SJanosch Frank u64 reserved08[2]; 171*83d815a2SJanosch Frank u64 paddr; 172*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 173*83d815a2SJanosch Frank 174*83d815a2SJanosch Frank /* Set Secure Config Parameter */ 175*83d815a2SJanosch Frank struct uv_cb_ssc { 176*83d815a2SJanosch Frank struct uv_cb_header header; 177*83d815a2SJanosch Frank u64 reserved08[2]; 178*83d815a2SJanosch Frank u64 guest_handle; 179*83d815a2SJanosch Frank u64 sec_header_origin; 180*83d815a2SJanosch Frank u32 sec_header_len; 181*83d815a2SJanosch Frank u32 reserved2c; 182*83d815a2SJanosch Frank u64 reserved30[4]; 183*83d815a2SJanosch Frank } __attribute__((packed)) __attribute__((aligned(8))); 184*83d815a2SJanosch Frank 18588fb0e5dSJanosch Frank static inline int uv_call_once(unsigned long r1, unsigned long r2) 1862ea7afb6SJanosch Frank { 1872ea7afb6SJanosch Frank int cc; 1882ea7afb6SJanosch Frank 1892ea7afb6SJanosch Frank asm volatile( 1902ea7afb6SJanosch Frank "0: .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n" 1912ea7afb6SJanosch Frank " ipm %[cc]\n" 1922ea7afb6SJanosch Frank " srl %[cc],28\n" 1932ea7afb6SJanosch Frank : [cc] "=d" (cc) 1942ea7afb6SJanosch Frank : [r1] "a" (r1), [r2] "a" (r2) 1952ea7afb6SJanosch Frank : "memory", "cc"); 1962ea7afb6SJanosch Frank return cc; 1972ea7afb6SJanosch Frank } 1982ea7afb6SJanosch Frank 19988fb0e5dSJanosch Frank static inline int uv_call(unsigned long r1, unsigned long r2) 20088fb0e5dSJanosch Frank { 20188fb0e5dSJanosch Frank int cc; 20288fb0e5dSJanosch Frank 20388fb0e5dSJanosch Frank /* 20488fb0e5dSJanosch Frank * CC 2 and 3 tell us to re-execute because the instruction 20588fb0e5dSJanosch Frank * hasn't yet finished. 20688fb0e5dSJanosch Frank */ 20788fb0e5dSJanosch Frank do { 20888fb0e5dSJanosch Frank cc = uv_call_once(r1, r2); 20988fb0e5dSJanosch Frank } while (cc > 1); 21088fb0e5dSJanosch Frank 21188fb0e5dSJanosch Frank return cc; 21288fb0e5dSJanosch Frank } 21388fb0e5dSJanosch Frank 214027c8015SPierre Morel static inline int share(unsigned long addr, u16 cmd) 215027c8015SPierre Morel { 216027c8015SPierre Morel struct uv_cb_share uvcb = { 217027c8015SPierre Morel .header.cmd = cmd, 218027c8015SPierre Morel .header.len = sizeof(uvcb), 219027c8015SPierre Morel .paddr = addr 220027c8015SPierre Morel }; 221027c8015SPierre Morel int cc; 222027c8015SPierre Morel 223027c8015SPierre Morel cc = uv_call(0, (u64)&uvcb); 224027c8015SPierre Morel if (!cc && uvcb.header.rc == UVC_RC_EXECUTED) 225027c8015SPierre Morel return 0; 226027c8015SPierre Morel 227027c8015SPierre Morel report_info("uv_call: cmd %04x cc %d response code: %04x", cc, cmd, 228027c8015SPierre Morel uvcb.header.rc); 229027c8015SPierre Morel return -1; 230027c8015SPierre Morel } 231027c8015SPierre Morel 232027c8015SPierre Morel /* 233027c8015SPierre Morel * Guest 2 request to the Ultravisor to make a page shared with the 234027c8015SPierre Morel * hypervisor for IO. 235027c8015SPierre Morel * 236027c8015SPierre Morel * @addr: Real or absolute address of the page to be shared 237027c8015SPierre Morel */ 238027c8015SPierre Morel static inline int uv_set_shared(unsigned long addr) 239027c8015SPierre Morel { 240027c8015SPierre Morel return share(addr, UVC_CMD_SET_SHARED_ACCESS); 241027c8015SPierre Morel } 242027c8015SPierre Morel 243027c8015SPierre Morel /* 244027c8015SPierre Morel * Guest 2 request to the Ultravisor to make a page unshared. 245027c8015SPierre Morel * 246027c8015SPierre Morel * @addr: Real or absolute address of the page to be unshared 247027c8015SPierre Morel */ 248027c8015SPierre Morel static inline int uv_remove_shared(unsigned long addr) 249027c8015SPierre Morel { 250027c8015SPierre Morel return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); 251027c8015SPierre Morel } 252027c8015SPierre Morel 253*83d815a2SJanosch Frank struct uv_cb_cpu_set_state { 254*83d815a2SJanosch Frank struct uv_cb_header header; 255*83d815a2SJanosch Frank u64 reserved08[2]; 256*83d815a2SJanosch Frank u64 cpu_handle; 257*83d815a2SJanosch Frank u8 reserved20[7]; 258*83d815a2SJanosch Frank u8 state; 259*83d815a2SJanosch Frank u64 reserved28[5]; 260*83d815a2SJanosch Frank }; 261*83d815a2SJanosch Frank 262*83d815a2SJanosch Frank #define PV_CPU_STATE_OPR 1 263*83d815a2SJanosch Frank #define PV_CPU_STATE_STP 2 264*83d815a2SJanosch Frank #define PV_CPU_STATE_CHKSTP 3 265*83d815a2SJanosch Frank #define PV_CPU_STATE_OPR_LOAD 5 266*83d815a2SJanosch Frank 2672ea7afb6SJanosch Frank #endif 268