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