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