0001
0002
0003
0004
0005
0006 #include <linux/export.h>
0007
0008 #include <asm/asm-extable.h>
0009 #include <asm/chpid.h>
0010 #include <asm/schid.h>
0011 #include <asm/crw.h>
0012
0013 #include "ioasm.h"
0014 #include "orb.h"
0015 #include "cio.h"
0016 #include "cio_inject.h"
0017
0018 static inline int __stsch(struct subchannel_id schid, struct schib *addr)
0019 {
0020 unsigned long r1 = *(unsigned int *)&schid;
0021 int ccode = -EIO;
0022
0023 asm volatile(
0024 " lgr 1,%[r1]\n"
0025 " stsch %[addr]\n"
0026 "0: ipm %[cc]\n"
0027 " srl %[cc],28\n"
0028 "1:\n"
0029 EX_TABLE(0b, 1b)
0030 : [cc] "+&d" (ccode), [addr] "=Q" (*addr)
0031 : [r1] "d" (r1)
0032 : "cc", "1");
0033 return ccode;
0034 }
0035
0036 int stsch(struct subchannel_id schid, struct schib *addr)
0037 {
0038 int ccode;
0039
0040 ccode = __stsch(schid, addr);
0041 trace_s390_cio_stsch(schid, addr, ccode);
0042
0043 return ccode;
0044 }
0045 EXPORT_SYMBOL(stsch);
0046
0047 static inline int __msch(struct subchannel_id schid, struct schib *addr)
0048 {
0049 unsigned long r1 = *(unsigned int *)&schid;
0050 int ccode = -EIO;
0051
0052 asm volatile(
0053 " lgr 1,%[r1]\n"
0054 " msch %[addr]\n"
0055 "0: ipm %[cc]\n"
0056 " srl %[cc],28\n"
0057 "1:\n"
0058 EX_TABLE(0b, 1b)
0059 : [cc] "+&d" (ccode)
0060 : [r1] "d" (r1), [addr] "Q" (*addr)
0061 : "cc", "1");
0062 return ccode;
0063 }
0064
0065 int msch(struct subchannel_id schid, struct schib *addr)
0066 {
0067 int ccode;
0068
0069 ccode = __msch(schid, addr);
0070 trace_s390_cio_msch(schid, addr, ccode);
0071
0072 return ccode;
0073 }
0074
0075 static inline int __tsch(struct subchannel_id schid, struct irb *addr)
0076 {
0077 unsigned long r1 = *(unsigned int *)&schid;
0078 int ccode;
0079
0080 asm volatile(
0081 " lgr 1,%[r1]\n"
0082 " tsch %[addr]\n"
0083 " ipm %[cc]\n"
0084 " srl %[cc],28"
0085 : [cc] "=&d" (ccode), [addr] "=Q" (*addr)
0086 : [r1] "d" (r1)
0087 : "cc", "1");
0088 return ccode;
0089 }
0090
0091 int tsch(struct subchannel_id schid, struct irb *addr)
0092 {
0093 int ccode;
0094
0095 ccode = __tsch(schid, addr);
0096 trace_s390_cio_tsch(schid, addr, ccode);
0097
0098 return ccode;
0099 }
0100
0101 static inline int __ssch(struct subchannel_id schid, union orb *addr)
0102 {
0103 unsigned long r1 = *(unsigned int *)&schid;
0104 int ccode = -EIO;
0105
0106 asm volatile(
0107 " lgr 1,%[r1]\n"
0108 " ssch %[addr]\n"
0109 "0: ipm %[cc]\n"
0110 " srl %[cc],28\n"
0111 "1:\n"
0112 EX_TABLE(0b, 1b)
0113 : [cc] "+&d" (ccode)
0114 : [r1] "d" (r1), [addr] "Q" (*addr)
0115 : "cc", "memory", "1");
0116 return ccode;
0117 }
0118
0119 int ssch(struct subchannel_id schid, union orb *addr)
0120 {
0121 int ccode;
0122
0123 ccode = __ssch(schid, addr);
0124 trace_s390_cio_ssch(schid, addr, ccode);
0125
0126 return ccode;
0127 }
0128 EXPORT_SYMBOL(ssch);
0129
0130 static inline int __csch(struct subchannel_id schid)
0131 {
0132 unsigned long r1 = *(unsigned int *)&schid;
0133 int ccode;
0134
0135 asm volatile(
0136 " lgr 1,%[r1]\n"
0137 " csch\n"
0138 " ipm %[cc]\n"
0139 " srl %[cc],28\n"
0140 : [cc] "=&d" (ccode)
0141 : [r1] "d" (r1)
0142 : "cc", "1");
0143 return ccode;
0144 }
0145
0146 int csch(struct subchannel_id schid)
0147 {
0148 int ccode;
0149
0150 ccode = __csch(schid);
0151 trace_s390_cio_csch(schid, ccode);
0152
0153 return ccode;
0154 }
0155 EXPORT_SYMBOL(csch);
0156
0157 int tpi(struct tpi_info *addr)
0158 {
0159 int ccode;
0160
0161 asm volatile(
0162 " tpi %[addr]\n"
0163 " ipm %[cc]\n"
0164 " srl %[cc],28"
0165 : [cc] "=&d" (ccode), [addr] "=Q" (*addr)
0166 :
0167 : "cc");
0168 trace_s390_cio_tpi(addr, ccode);
0169
0170 return ccode;
0171 }
0172
0173 int chsc(void *chsc_area)
0174 {
0175 typedef struct { char _[4096]; } addr_type;
0176 int cc = -EIO;
0177
0178 asm volatile(
0179 " .insn rre,0xb25f0000,%[chsc_area],0\n"
0180 "0: ipm %[cc]\n"
0181 " srl %[cc],28\n"
0182 "1:\n"
0183 EX_TABLE(0b, 1b)
0184 : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area)
0185 : [chsc_area] "d" (chsc_area)
0186 : "cc");
0187 trace_s390_cio_chsc(chsc_area, cc);
0188
0189 return cc;
0190 }
0191 EXPORT_SYMBOL(chsc);
0192
0193 static inline int __rsch(struct subchannel_id schid)
0194 {
0195 unsigned long r1 = *(unsigned int *)&schid;
0196 int ccode;
0197
0198 asm volatile(
0199 " lgr 1,%[r1]\n"
0200 " rsch\n"
0201 " ipm %[cc]\n"
0202 " srl %[cc],28\n"
0203 : [cc] "=&d" (ccode)
0204 : [r1] "d" (r1)
0205 : "cc", "memory", "1");
0206 return ccode;
0207 }
0208
0209 int rsch(struct subchannel_id schid)
0210 {
0211 int ccode;
0212
0213 ccode = __rsch(schid);
0214 trace_s390_cio_rsch(schid, ccode);
0215
0216 return ccode;
0217 }
0218
0219 static inline int __hsch(struct subchannel_id schid)
0220 {
0221 unsigned long r1 = *(unsigned int *)&schid;
0222 int ccode;
0223
0224 asm volatile(
0225 " lgr 1,%[r1]\n"
0226 " hsch\n"
0227 " ipm %[cc]\n"
0228 " srl %[cc],28\n"
0229 : [cc] "=&d" (ccode)
0230 : [r1] "d" (r1)
0231 : "cc", "1");
0232 return ccode;
0233 }
0234
0235 int hsch(struct subchannel_id schid)
0236 {
0237 int ccode;
0238
0239 ccode = __hsch(schid);
0240 trace_s390_cio_hsch(schid, ccode);
0241
0242 return ccode;
0243 }
0244 EXPORT_SYMBOL(hsch);
0245
0246 static inline int __xsch(struct subchannel_id schid)
0247 {
0248 unsigned long r1 = *(unsigned int *)&schid;
0249 int ccode;
0250
0251 asm volatile(
0252 " lgr 1,%[r1]\n"
0253 " xsch\n"
0254 " ipm %[cc]\n"
0255 " srl %[cc],28\n"
0256 : [cc] "=&d" (ccode)
0257 : [r1] "d" (r1)
0258 : "cc", "1");
0259 return ccode;
0260 }
0261
0262 int xsch(struct subchannel_id schid)
0263 {
0264 int ccode;
0265
0266 ccode = __xsch(schid);
0267 trace_s390_cio_xsch(schid, ccode);
0268
0269 return ccode;
0270 }
0271
0272 static inline int __stcrw(struct crw *crw)
0273 {
0274 int ccode;
0275
0276 asm volatile(
0277 " stcrw %[crw]\n"
0278 " ipm %[cc]\n"
0279 " srl %[cc],28\n"
0280 : [cc] "=&d" (ccode), [crw] "=Q" (*crw)
0281 :
0282 : "cc");
0283 return ccode;
0284 }
0285
0286 static inline int _stcrw(struct crw *crw)
0287 {
0288 #ifdef CONFIG_CIO_INJECT
0289 if (static_branch_unlikely(&cio_inject_enabled)) {
0290 if (stcrw_get_injected(crw) == 0)
0291 return 0;
0292 }
0293 #endif
0294
0295 return __stcrw(crw);
0296 }
0297
0298 int stcrw(struct crw *crw)
0299 {
0300 int ccode;
0301
0302 ccode = _stcrw(crw);
0303 trace_s390_cio_stcrw(crw, ccode);
0304
0305 return ccode;
0306 }