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