ioasm.c (5171B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Channel subsystem I/O instructions. 4 */ 5 6#include <linux/export.h> 7 8#include <asm/asm-extable.h> 9#include <asm/chpid.h> 10#include <asm/schid.h> 11#include <asm/crw.h> 12 13#include "ioasm.h" 14#include "orb.h" 15#include "cio.h" 16#include "cio_inject.h" 17 18static inline int __stsch(struct subchannel_id schid, struct schib *addr) 19{ 20 unsigned long r1 = *(unsigned int *)&schid; 21 int ccode = -EIO; 22 23 asm volatile( 24 " lgr 1,%[r1]\n" 25 " stsch %[addr]\n" 26 "0: ipm %[cc]\n" 27 " srl %[cc],28\n" 28 "1:\n" 29 EX_TABLE(0b, 1b) 30 : [cc] "+&d" (ccode), [addr] "=Q" (*addr) 31 : [r1] "d" (r1) 32 : "cc", "1"); 33 return ccode; 34} 35 36int stsch(struct subchannel_id schid, struct schib *addr) 37{ 38 int ccode; 39 40 ccode = __stsch(schid, addr); 41 trace_s390_cio_stsch(schid, addr, ccode); 42 43 return ccode; 44} 45EXPORT_SYMBOL(stsch); 46 47static inline int __msch(struct subchannel_id schid, struct schib *addr) 48{ 49 unsigned long r1 = *(unsigned int *)&schid; 50 int ccode = -EIO; 51 52 asm volatile( 53 " lgr 1,%[r1]\n" 54 " msch %[addr]\n" 55 "0: ipm %[cc]\n" 56 " srl %[cc],28\n" 57 "1:\n" 58 EX_TABLE(0b, 1b) 59 : [cc] "+&d" (ccode) 60 : [r1] "d" (r1), [addr] "Q" (*addr) 61 : "cc", "1"); 62 return ccode; 63} 64 65int msch(struct subchannel_id schid, struct schib *addr) 66{ 67 int ccode; 68 69 ccode = __msch(schid, addr); 70 trace_s390_cio_msch(schid, addr, ccode); 71 72 return ccode; 73} 74 75static inline int __tsch(struct subchannel_id schid, struct irb *addr) 76{ 77 unsigned long r1 = *(unsigned int *)&schid; 78 int ccode; 79 80 asm volatile( 81 " lgr 1,%[r1]\n" 82 " tsch %[addr]\n" 83 " ipm %[cc]\n" 84 " srl %[cc],28" 85 : [cc] "=&d" (ccode), [addr] "=Q" (*addr) 86 : [r1] "d" (r1) 87 : "cc", "1"); 88 return ccode; 89} 90 91int tsch(struct subchannel_id schid, struct irb *addr) 92{ 93 int ccode; 94 95 ccode = __tsch(schid, addr); 96 trace_s390_cio_tsch(schid, addr, ccode); 97 98 return ccode; 99} 100 101static inline int __ssch(struct subchannel_id schid, union orb *addr) 102{ 103 unsigned long r1 = *(unsigned int *)&schid; 104 int ccode = -EIO; 105 106 asm volatile( 107 " lgr 1,%[r1]\n" 108 " ssch %[addr]\n" 109 "0: ipm %[cc]\n" 110 " srl %[cc],28\n" 111 "1:\n" 112 EX_TABLE(0b, 1b) 113 : [cc] "+&d" (ccode) 114 : [r1] "d" (r1), [addr] "Q" (*addr) 115 : "cc", "memory", "1"); 116 return ccode; 117} 118 119int ssch(struct subchannel_id schid, union orb *addr) 120{ 121 int ccode; 122 123 ccode = __ssch(schid, addr); 124 trace_s390_cio_ssch(schid, addr, ccode); 125 126 return ccode; 127} 128EXPORT_SYMBOL(ssch); 129 130static inline int __csch(struct subchannel_id schid) 131{ 132 unsigned long r1 = *(unsigned int *)&schid; 133 int ccode; 134 135 asm volatile( 136 " lgr 1,%[r1]\n" 137 " csch\n" 138 " ipm %[cc]\n" 139 " srl %[cc],28\n" 140 : [cc] "=&d" (ccode) 141 : [r1] "d" (r1) 142 : "cc", "1"); 143 return ccode; 144} 145 146int csch(struct subchannel_id schid) 147{ 148 int ccode; 149 150 ccode = __csch(schid); 151 trace_s390_cio_csch(schid, ccode); 152 153 return ccode; 154} 155EXPORT_SYMBOL(csch); 156 157int tpi(struct tpi_info *addr) 158{ 159 int ccode; 160 161 asm volatile( 162 " tpi %[addr]\n" 163 " ipm %[cc]\n" 164 " srl %[cc],28" 165 : [cc] "=&d" (ccode), [addr] "=Q" (*addr) 166 : 167 : "cc"); 168 trace_s390_cio_tpi(addr, ccode); 169 170 return ccode; 171} 172 173int chsc(void *chsc_area) 174{ 175 typedef struct { char _[4096]; } addr_type; 176 int cc = -EIO; 177 178 asm volatile( 179 " .insn rre,0xb25f0000,%[chsc_area],0\n" 180 "0: ipm %[cc]\n" 181 " srl %[cc],28\n" 182 "1:\n" 183 EX_TABLE(0b, 1b) 184 : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area) 185 : [chsc_area] "d" (chsc_area) 186 : "cc"); 187 trace_s390_cio_chsc(chsc_area, cc); 188 189 return cc; 190} 191EXPORT_SYMBOL(chsc); 192 193static inline int __rsch(struct subchannel_id schid) 194{ 195 unsigned long r1 = *(unsigned int *)&schid; 196 int ccode; 197 198 asm volatile( 199 " lgr 1,%[r1]\n" 200 " rsch\n" 201 " ipm %[cc]\n" 202 " srl %[cc],28\n" 203 : [cc] "=&d" (ccode) 204 : [r1] "d" (r1) 205 : "cc", "memory", "1"); 206 return ccode; 207} 208 209int rsch(struct subchannel_id schid) 210{ 211 int ccode; 212 213 ccode = __rsch(schid); 214 trace_s390_cio_rsch(schid, ccode); 215 216 return ccode; 217} 218 219static inline int __hsch(struct subchannel_id schid) 220{ 221 unsigned long r1 = *(unsigned int *)&schid; 222 int ccode; 223 224 asm volatile( 225 " lgr 1,%[r1]\n" 226 " hsch\n" 227 " ipm %[cc]\n" 228 " srl %[cc],28\n" 229 : [cc] "=&d" (ccode) 230 : [r1] "d" (r1) 231 : "cc", "1"); 232 return ccode; 233} 234 235int hsch(struct subchannel_id schid) 236{ 237 int ccode; 238 239 ccode = __hsch(schid); 240 trace_s390_cio_hsch(schid, ccode); 241 242 return ccode; 243} 244EXPORT_SYMBOL(hsch); 245 246static inline int __xsch(struct subchannel_id schid) 247{ 248 unsigned long r1 = *(unsigned int *)&schid; 249 int ccode; 250 251 asm volatile( 252 " lgr 1,%[r1]\n" 253 " xsch\n" 254 " ipm %[cc]\n" 255 " srl %[cc],28\n" 256 : [cc] "=&d" (ccode) 257 : [r1] "d" (r1) 258 : "cc", "1"); 259 return ccode; 260} 261 262int xsch(struct subchannel_id schid) 263{ 264 int ccode; 265 266 ccode = __xsch(schid); 267 trace_s390_cio_xsch(schid, ccode); 268 269 return ccode; 270} 271 272static inline int __stcrw(struct crw *crw) 273{ 274 int ccode; 275 276 asm volatile( 277 " stcrw %[crw]\n" 278 " ipm %[cc]\n" 279 " srl %[cc],28\n" 280 : [cc] "=&d" (ccode), [crw] "=Q" (*crw) 281 : 282 : "cc"); 283 return ccode; 284} 285 286static inline int _stcrw(struct crw *crw) 287{ 288#ifdef CONFIG_CIO_INJECT 289 if (static_branch_unlikely(&cio_inject_enabled)) { 290 if (stcrw_get_injected(crw) == 0) 291 return 0; 292 } 293#endif 294 295 return __stcrw(crw); 296} 297 298int stcrw(struct crw *crw) 299{ 300 int ccode; 301 302 ccode = _stcrw(crw); 303 trace_s390_cio_stcrw(crw, ccode); 304 305 return ccode; 306}