307 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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_INJECT289 if (static_branch_unlikely(&cio_inject_enabled)) {290 if (stcrw_get_injected(crw) == 0)291 return 0;292 }293#endif294 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}307