Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Channel subsystem I/O instructions.
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 }