Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.9-rc8 369 lines 8.5 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Ultravisor Interfaces 4 * 5 * Copyright IBM Corp. 2019 6 * 7 * Author(s): 8 * Vasily Gorbik <gor@linux.ibm.com> 9 * Janosch Frank <frankja@linux.ibm.com> 10 */ 11#ifndef _ASM_S390_UV_H 12#define _ASM_S390_UV_H 13 14#include <linux/types.h> 15#include <linux/errno.h> 16#include <linux/bug.h> 17#include <linux/sched.h> 18#include <asm/page.h> 19#include <asm/gmap.h> 20 21#define UVC_RC_EXECUTED 0x0001 22#define UVC_RC_INV_CMD 0x0002 23#define UVC_RC_INV_STATE 0x0003 24#define UVC_RC_INV_LEN 0x0005 25#define UVC_RC_NO_RESUME 0x0007 26#define UVC_RC_NEED_DESTROY 0x8000 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_SET_SEC_CONF_PARAMS 0x0300 37#define UVC_CMD_UNPACK_IMG 0x0301 38#define UVC_CMD_VERIFY_IMG 0x0302 39#define UVC_CMD_CPU_RESET 0x0310 40#define UVC_CMD_CPU_RESET_INITIAL 0x0311 41#define UVC_CMD_PREPARE_RESET 0x0320 42#define UVC_CMD_CPU_RESET_CLEAR 0x0321 43#define UVC_CMD_CPU_SET_STATE 0x0330 44#define UVC_CMD_SET_UNSHARE_ALL 0x0340 45#define UVC_CMD_PIN_PAGE_SHARED 0x0341 46#define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 47#define UVC_CMD_SET_SHARED_ACCESS 0x1000 48#define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 49 50/* Bits in installed uv calls */ 51enum uv_cmds_inst { 52 BIT_UVC_CMD_QUI = 0, 53 BIT_UVC_CMD_INIT_UV = 1, 54 BIT_UVC_CMD_CREATE_SEC_CONF = 2, 55 BIT_UVC_CMD_DESTROY_SEC_CONF = 3, 56 BIT_UVC_CMD_CREATE_SEC_CPU = 4, 57 BIT_UVC_CMD_DESTROY_SEC_CPU = 5, 58 BIT_UVC_CMD_CONV_TO_SEC_STOR = 6, 59 BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7, 60 BIT_UVC_CMD_SET_SHARED_ACCESS = 8, 61 BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9, 62 BIT_UVC_CMD_SET_SEC_PARMS = 11, 63 BIT_UVC_CMD_UNPACK_IMG = 13, 64 BIT_UVC_CMD_VERIFY_IMG = 14, 65 BIT_UVC_CMD_CPU_RESET = 15, 66 BIT_UVC_CMD_CPU_RESET_INITIAL = 16, 67 BIT_UVC_CMD_CPU_SET_STATE = 17, 68 BIT_UVC_CMD_PREPARE_RESET = 18, 69 BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19, 70 BIT_UVC_CMD_UNSHARE_ALL = 20, 71 BIT_UVC_CMD_PIN_PAGE_SHARED = 21, 72 BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, 73}; 74 75struct uv_cb_header { 76 u16 len; 77 u16 cmd; /* Command Code */ 78 u16 rc; /* Response Code */ 79 u16 rrc; /* Return Reason Code */ 80} __packed __aligned(8); 81 82/* Query Ultravisor Information */ 83struct uv_cb_qui { 84 struct uv_cb_header header; 85 u64 reserved08; 86 u64 inst_calls_list[4]; 87 u64 reserved30[2]; 88 u64 uv_base_stor_len; 89 u64 reserved48; 90 u64 conf_base_phys_stor_len; 91 u64 conf_base_virt_stor_len; 92 u64 conf_virt_var_stor_len; 93 u64 cpu_stor_len; 94 u32 reserved70[3]; 95 u32 max_num_sec_conf; 96 u64 max_guest_stor_addr; 97 u8 reserved88[158 - 136]; 98 u16 max_guest_cpus; 99 u8 reserveda0[200 - 160]; 100} __packed __aligned(8); 101 102/* Initialize Ultravisor */ 103struct uv_cb_init { 104 struct uv_cb_header header; 105 u64 reserved08[2]; 106 u64 stor_origin; 107 u64 stor_len; 108 u64 reserved28[4]; 109} __packed __aligned(8); 110 111/* Create Guest Configuration */ 112struct 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_virt_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 reserved58[5]; 124} __packed __aligned(8); 125 126/* Create Secure CPU */ 127struct uv_cb_csc { 128 struct uv_cb_header header; 129 u64 reserved08[2]; 130 u64 cpu_handle; 131 u64 guest_handle; 132 u64 stor_origin; 133 u8 reserved30[6]; 134 u16 num; 135 u64 state_origin; 136 u64 reserved40[4]; 137} __packed __aligned(8); 138 139/* Convert to Secure */ 140struct uv_cb_cts { 141 struct uv_cb_header header; 142 u64 reserved08[2]; 143 u64 guest_handle; 144 u64 gaddr; 145} __packed __aligned(8); 146 147/* Convert from Secure / Pin Page Shared */ 148struct uv_cb_cfs { 149 struct uv_cb_header header; 150 u64 reserved08[2]; 151 u64 paddr; 152} __packed __aligned(8); 153 154/* Set Secure Config Parameter */ 155struct uv_cb_ssc { 156 struct uv_cb_header header; 157 u64 reserved08[2]; 158 u64 guest_handle; 159 u64 sec_header_origin; 160 u32 sec_header_len; 161 u32 reserved2c; 162 u64 reserved30[4]; 163} __packed __aligned(8); 164 165/* Unpack */ 166struct uv_cb_unp { 167 struct uv_cb_header header; 168 u64 reserved08[2]; 169 u64 guest_handle; 170 u64 gaddr; 171 u64 tweak[2]; 172 u64 reserved38[3]; 173} __packed __aligned(8); 174 175#define PV_CPU_STATE_OPR 1 176#define PV_CPU_STATE_STP 2 177#define PV_CPU_STATE_CHKSTP 3 178#define PV_CPU_STATE_OPR_LOAD 5 179 180struct uv_cb_cpu_set_state { 181 struct uv_cb_header header; 182 u64 reserved08[2]; 183 u64 cpu_handle; 184 u8 reserved20[7]; 185 u8 state; 186 u64 reserved28[5]; 187}; 188 189/* 190 * A common UV call struct for calls that take no payload 191 * Examples: 192 * Destroy cpu/config 193 * Verify 194 */ 195struct uv_cb_nodata { 196 struct uv_cb_header header; 197 u64 reserved08[2]; 198 u64 handle; 199 u64 reserved20[4]; 200} __packed __aligned(8); 201 202/* Set Shared Access */ 203struct uv_cb_share { 204 struct uv_cb_header header; 205 u64 reserved08[3]; 206 u64 paddr; 207 u64 reserved28; 208} __packed __aligned(8); 209 210static inline int __uv_call(unsigned long r1, unsigned long r2) 211{ 212 int cc; 213 214 asm volatile( 215 " .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n" 216 " ipm %[cc]\n" 217 " srl %[cc],28\n" 218 : [cc] "=d" (cc) 219 : [r1] "a" (r1), [r2] "a" (r2) 220 : "memory", "cc"); 221 return cc; 222} 223 224static inline int uv_call(unsigned long r1, unsigned long r2) 225{ 226 int cc; 227 228 do { 229 cc = __uv_call(r1, r2); 230 } while (cc > 1); 231 return cc; 232} 233 234/* Low level uv_call that avoids stalls for long running busy conditions */ 235static inline int uv_call_sched(unsigned long r1, unsigned long r2) 236{ 237 int cc; 238 239 do { 240 cc = __uv_call(r1, r2); 241 cond_resched(); 242 } while (cc > 1); 243 return cc; 244} 245 246/* 247 * special variant of uv_call that only transports the cpu or guest 248 * handle and the command, like destroy or verify. 249 */ 250static inline int uv_cmd_nodata(u64 handle, u16 cmd, u16 *rc, u16 *rrc) 251{ 252 struct uv_cb_nodata uvcb = { 253 .header.cmd = cmd, 254 .header.len = sizeof(uvcb), 255 .handle = handle, 256 }; 257 int cc; 258 259 WARN(!handle, "No handle provided to Ultravisor call cmd %x\n", cmd); 260 cc = uv_call_sched(0, (u64)&uvcb); 261 *rc = uvcb.header.rc; 262 *rrc = uvcb.header.rrc; 263 return cc ? -EINVAL : 0; 264} 265 266struct uv_info { 267 unsigned long inst_calls_list[4]; 268 unsigned long uv_base_stor_len; 269 unsigned long guest_base_stor_len; 270 unsigned long guest_virt_base_stor_len; 271 unsigned long guest_virt_var_stor_len; 272 unsigned long guest_cpu_stor_len; 273 unsigned long max_sec_stor_addr; 274 unsigned int max_num_sec_conf; 275 unsigned short max_guest_cpus; 276}; 277 278extern struct uv_info uv_info; 279 280#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 281extern int prot_virt_guest; 282 283static inline int is_prot_virt_guest(void) 284{ 285 return prot_virt_guest; 286} 287 288static inline int share(unsigned long addr, u16 cmd) 289{ 290 struct uv_cb_share uvcb = { 291 .header.cmd = cmd, 292 .header.len = sizeof(uvcb), 293 .paddr = addr 294 }; 295 296 if (!is_prot_virt_guest()) 297 return -EOPNOTSUPP; 298 /* 299 * Sharing is page wise, if we encounter addresses that are 300 * not page aligned, we assume something went wrong. If 301 * malloced structs are passed to this function, we could leak 302 * data to the hypervisor. 303 */ 304 BUG_ON(addr & ~PAGE_MASK); 305 306 if (!uv_call(0, (u64)&uvcb)) 307 return 0; 308 return -EINVAL; 309} 310 311/* 312 * Guest 2 request to the Ultravisor to make a page shared with the 313 * hypervisor for IO. 314 * 315 * @addr: Real or absolute address of the page to be shared 316 */ 317static inline int uv_set_shared(unsigned long addr) 318{ 319 return share(addr, UVC_CMD_SET_SHARED_ACCESS); 320} 321 322/* 323 * Guest 2 request to the Ultravisor to make a page unshared. 324 * 325 * @addr: Real or absolute address of the page to be unshared 326 */ 327static inline int uv_remove_shared(unsigned long addr) 328{ 329 return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); 330} 331 332#else 333#define is_prot_virt_guest() 0 334static inline int uv_set_shared(unsigned long addr) { return 0; } 335static inline int uv_remove_shared(unsigned long addr) { return 0; } 336#endif 337 338#if IS_ENABLED(CONFIG_KVM) 339extern int prot_virt_host; 340 341static inline int is_prot_virt_host(void) 342{ 343 return prot_virt_host; 344} 345 346int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb); 347int uv_convert_from_secure(unsigned long paddr); 348int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr); 349 350void setup_uv(void); 351void adjust_to_uv_max(unsigned long *vmax); 352#else 353#define is_prot_virt_host() 0 354static inline void setup_uv(void) {} 355static inline void adjust_to_uv_max(unsigned long *vmax) {} 356 357static inline int uv_convert_from_secure(unsigned long paddr) 358{ 359 return 0; 360} 361#endif 362 363#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM) 364void uv_query_info(void); 365#else 366static inline void uv_query_info(void) {} 367#endif 368 369#endif /* _ASM_S390_UV_H */