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 <asm/page.h> 18 19 #define UVC_RC_EXECUTED 0x0001 20 #define UVC_RC_INV_CMD 0x0002 21 #define UVC_RC_INV_STATE 0x0003 22 #define UVC_RC_INV_LEN 0x0005 23 #define UVC_RC_NO_RESUME 0x0007 24 25 #define UVC_CMD_QUI 0x0001 26 #define UVC_CMD_SET_SHARED_ACCESS 0x1000 27 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 28 29 /* Bits in installed uv calls */ 30 enum uv_cmds_inst { 31 BIT_UVC_CMD_QUI = 0, 32 BIT_UVC_CMD_SET_SHARED_ACCESS = 8, 33 BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9, 34 }; 35 36 struct uv_cb_header { 37 u16 len; 38 u16 cmd; /* Command Code */ 39 u16 rc; /* Response Code */ 40 u16 rrc; /* Return Reason Code */ 41 } __packed __aligned(8); 42 43 struct uv_cb_qui { 44 struct uv_cb_header header; 45 u64 reserved08; 46 u64 inst_calls_list[4]; 47 u64 reserved30[15]; 48 } __packed __aligned(8); 49 50 struct uv_cb_share { 51 struct uv_cb_header header; 52 u64 reserved08[3]; 53 u64 paddr; 54 u64 reserved28; 55 } __packed __aligned(8); 56 57 static inline int uv_call(unsigned long r1, unsigned long r2) 58 { 59 int cc; 60 61 asm volatile( 62 "0: .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n" 63 " brc 3,0b\n" 64 " ipm %[cc]\n" 65 " srl %[cc],28\n" 66 : [cc] "=d" (cc) 67 : [r1] "a" (r1), [r2] "a" (r2) 68 : "memory", "cc"); 69 return cc; 70 } 71 72 #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 73 extern int prot_virt_guest; 74 75 static inline int is_prot_virt_guest(void) 76 { 77 return prot_virt_guest; 78 } 79 80 static inline int share(unsigned long addr, u16 cmd) 81 { 82 struct uv_cb_share uvcb = { 83 .header.cmd = cmd, 84 .header.len = sizeof(uvcb), 85 .paddr = addr 86 }; 87 88 if (!is_prot_virt_guest()) 89 return -ENOTSUPP; 90 /* 91 * Sharing is page wise, if we encounter addresses that are 92 * not page aligned, we assume something went wrong. If 93 * malloced structs are passed to this function, we could leak 94 * data to the hypervisor. 95 */ 96 BUG_ON(addr & ~PAGE_MASK); 97 98 if (!uv_call(0, (u64)&uvcb)) 99 return 0; 100 return -EINVAL; 101 } 102 103 /* 104 * Guest 2 request to the Ultravisor to make a page shared with the 105 * hypervisor for IO. 106 * 107 * @addr: Real or absolute address of the page to be shared 108 */ 109 static inline int uv_set_shared(unsigned long addr) 110 { 111 return share(addr, UVC_CMD_SET_SHARED_ACCESS); 112 } 113 114 /* 115 * Guest 2 request to the Ultravisor to make a page unshared. 116 * 117 * @addr: Real or absolute address of the page to be unshared 118 */ 119 static inline int uv_remove_shared(unsigned long addr) 120 { 121 return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); 122 } 123 124 void uv_query_info(void); 125 #else 126 #define is_prot_virt_guest() 0 127 static inline int uv_set_shared(unsigned long addr) { return 0; } 128 static inline int uv_remove_shared(unsigned long addr) { return 0; } 129 static inline void uv_query_info(void) {} 130 #endif 131 132 #endif /* _ASM_S390_UV_H */ 133