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 __rsch(struct subchannel_id schid) 187 { 188 register struct subchannel_id reg1 asm("1") = schid; 189 int ccode; 190 191 asm volatile( 192 " rsch\n" 193 " ipm %0\n" 194 " srl %0,28" 195 : "=d" (ccode) 196 : "d" (reg1) 197 : "cc", "memory"); 198 199 return ccode; 200 } 201 202 int rsch(struct subchannel_id schid) 203 { 204 int ccode; 205 206 ccode = __rsch(schid); 207 trace_s390_cio_rsch(schid, ccode); 208 209 return ccode; 210 } 211 212 static inline int __hsch(struct subchannel_id schid) 213 { 214 register struct subchannel_id reg1 asm("1") = schid; 215 int ccode; 216 217 asm volatile( 218 " hsch\n" 219 " ipm %0\n" 220 " srl %0,28" 221 : "=d" (ccode) 222 : "d" (reg1) 223 : "cc"); 224 return ccode; 225 } 226 227 int hsch(struct subchannel_id schid) 228 { 229 int ccode; 230 231 ccode = __hsch(schid); 232 trace_s390_cio_hsch(schid, ccode); 233 234 return ccode; 235 } 236 237 static inline int __xsch(struct subchannel_id schid) 238 { 239 register struct subchannel_id reg1 asm("1") = schid; 240 int ccode; 241 242 asm volatile( 243 " xsch\n" 244 " ipm %0\n" 245 " srl %0,28" 246 : "=d" (ccode) 247 : "d" (reg1) 248 : "cc"); 249 return ccode; 250 } 251 252 int xsch(struct subchannel_id schid) 253 { 254 int ccode; 255 256 ccode = __xsch(schid); 257 trace_s390_cio_xsch(schid, ccode); 258 259 return ccode; 260 } 261 262 int stcrw(struct crw *crw) 263 { 264 int ccode; 265 266 asm volatile( 267 " stcrw 0(%2)\n" 268 " ipm %0\n" 269 " srl %0,28\n" 270 : "=d" (ccode), "=m" (*crw) 271 : "a" (crw) 272 : "cc"); 273 trace_s390_cio_stcrw(crw, ccode); 274 275 return ccode; 276 } 277