linux/arch/s390/include/asm/ap.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Adjunct processor (AP) interfaces
   4 *
   5 * Copyright IBM Corp. 2017
   6 *
   7 * Author(s): Tony Krowiak <akrowia@linux.vnet.ibm.com>
   8 *            Martin Schwidefsky <schwidefsky@de.ibm.com>
   9 *            Harald Freudenberger <freude@de.ibm.com>
  10 */
  11
  12#ifndef _ASM_S390_AP_H_
  13#define _ASM_S390_AP_H_
  14
  15/**
  16 * The ap_qid_t identifier of an ap queue.
  17 * If the AP facilities test (APFT) facility is available,
  18 * card and queue index are 8 bit values, otherwise
  19 * card index is 6 bit and queue index a 4 bit value.
  20 */
  21typedef unsigned int ap_qid_t;
  22
  23#define AP_MKQID(_card, _queue) (((_card) & 0xff) << 8 | ((_queue) & 0xff))
  24#define AP_QID_CARD(_qid) (((_qid) >> 8) & 0xff)
  25#define AP_QID_QUEUE(_qid) ((_qid) & 0xff)
  26
  27/**
  28 * struct ap_queue_status - Holds the AP queue status.
  29 * @queue_empty: Shows if queue is empty
  30 * @replies_waiting: Waiting replies
  31 * @queue_full: Is 1 if the queue is full
  32 * @irq_enabled: Shows if interrupts are enabled for the AP
  33 * @response_code: Holds the 8 bit response code
  34 *
  35 * The ap queue status word is returned by all three AP functions
  36 * (PQAP, NQAP and DQAP).  There's a set of flags in the first
  37 * byte, followed by a 1 byte response code.
  38 */
  39struct ap_queue_status {
  40        unsigned int queue_empty        : 1;
  41        unsigned int replies_waiting    : 1;
  42        unsigned int queue_full         : 1;
  43        unsigned int _pad1              : 4;
  44        unsigned int irq_enabled        : 1;
  45        unsigned int response_code      : 8;
  46        unsigned int _pad2              : 16;
  47};
  48
  49/**
  50 * ap_intructions_available() - Test if AP instructions are available.
  51 *
  52 * Returns true if the AP instructions are installed, otherwise false.
  53 */
  54static inline bool ap_instructions_available(void)
  55{
  56        register unsigned long reg0 asm ("0") = AP_MKQID(0, 0);
  57        register unsigned long reg1 asm ("1") = 0;
  58        register unsigned long reg2 asm ("2") = 0;
  59
  60        asm volatile(
  61                "   .long 0xb2af0000\n"         /* PQAP(TAPQ) */
  62                "0: la    %0,1\n"
  63                "1:\n"
  64                EX_TABLE(0b, 1b)
  65                : "+d" (reg1), "+d" (reg2)
  66                : "d" (reg0)
  67                : "cc");
  68        return reg1 != 0;
  69}
  70
  71/**
  72 * ap_tapq(): Test adjunct processor queue.
  73 * @qid: The AP queue number
  74 * @info: Pointer to queue descriptor
  75 *
  76 * Returns AP queue status structure.
  77 */
  78static inline struct ap_queue_status ap_tapq(ap_qid_t qid, unsigned long *info)
  79{
  80        register unsigned long reg0 asm ("0") = qid;
  81        register struct ap_queue_status reg1 asm ("1");
  82        register unsigned long reg2 asm ("2");
  83
  84        asm volatile(".long 0xb2af0000"         /* PQAP(TAPQ) */
  85                     : "=d" (reg1), "=d" (reg2)
  86                     : "d" (reg0)
  87                     : "cc");
  88        if (info)
  89                *info = reg2;
  90        return reg1;
  91}
  92
  93/**
  94 * ap_test_queue(): Test adjunct processor queue.
  95 * @qid: The AP queue number
  96 * @tbit: Test facilities bit
  97 * @info: Pointer to queue descriptor
  98 *
  99 * Returns AP queue status structure.
 100 */
 101static inline struct ap_queue_status ap_test_queue(ap_qid_t qid,
 102                                                   int tbit,
 103                                                   unsigned long *info)
 104{
 105        if (tbit)
 106                qid |= 1UL << 23; /* set T bit*/
 107        return ap_tapq(qid, info);
 108}
 109
 110/**
 111 * ap_pqap_rapq(): Reset adjunct processor queue.
 112 * @qid: The AP queue number
 113 *
 114 * Returns AP queue status structure.
 115 */
 116static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
 117{
 118        register unsigned long reg0 asm ("0") = qid | (1UL << 24);
 119        register struct ap_queue_status reg1 asm ("1");
 120
 121        asm volatile(
 122                ".long 0xb2af0000"              /* PQAP(RAPQ) */
 123                : "=d" (reg1)
 124                : "d" (reg0)
 125                : "cc");
 126        return reg1;
 127}
 128
 129/**
 130 * ap_pqap_zapq(): Reset and zeroize adjunct processor queue.
 131 * @qid: The AP queue number
 132 *
 133 * Returns AP queue status structure.
 134 */
 135static inline struct ap_queue_status ap_zapq(ap_qid_t qid)
 136{
 137        register unsigned long reg0 asm ("0") = qid | (2UL << 24);
 138        register struct ap_queue_status reg1 asm ("1");
 139
 140        asm volatile(
 141                ".long 0xb2af0000"              /* PQAP(ZAPQ) */
 142                : "=d" (reg1)
 143                : "d" (reg0)
 144                : "cc");
 145        return reg1;
 146}
 147
 148/**
 149 * struct ap_config_info - convenience struct for AP crypto
 150 * config info as returned by the ap_qci() function.
 151 */
 152struct ap_config_info {
 153        unsigned int apsc        : 1;   /* S bit */
 154        unsigned int apxa        : 1;   /* N bit */
 155        unsigned int qact        : 1;   /* C bit */
 156        unsigned int rc8a        : 1;   /* R bit */
 157        unsigned char _reserved1 : 4;
 158        unsigned char _reserved2[3];
 159        unsigned char Na;               /* max # of APs - 1 */
 160        unsigned char Nd;               /* max # of Domains - 1 */
 161        unsigned char _reserved3[10];
 162        unsigned int apm[8];            /* AP ID mask */
 163        unsigned int aqm[8];            /* AP (usage) queue mask */
 164        unsigned int adm[8];            /* AP (control) domain mask */
 165        unsigned char _reserved4[16];
 166} __aligned(8);
 167
 168/**
 169 * ap_qci(): Get AP configuration data
 170 *
 171 * Returns 0 on success, or -EOPNOTSUPP.
 172 */
 173static inline int ap_qci(struct ap_config_info *config)
 174{
 175        register unsigned long reg0 asm ("0") = 4UL << 24;
 176        register unsigned long reg1 asm ("1") = -EOPNOTSUPP;
 177        register struct ap_config_info *reg2 asm ("2") = config;
 178
 179        asm volatile(
 180                ".long 0xb2af0000\n"            /* PQAP(QCI) */
 181                "0: la    %0,0\n"
 182                "1:\n"
 183                EX_TABLE(0b, 1b)
 184                : "+d" (reg1)
 185                : "d" (reg0), "d" (reg2)
 186                : "cc", "memory");
 187
 188        return reg1;
 189}
 190
 191/*
 192 * struct ap_qirq_ctrl - convenient struct for easy invocation
 193 * of the ap_aqic() function. This struct is passed as GR1
 194 * parameter to the PQAP(AQIC) instruction. For details please
 195 * see the AR documentation.
 196 */
 197struct ap_qirq_ctrl {
 198        unsigned int _res1 : 8;
 199        unsigned int zone  : 8; /* zone info */
 200        unsigned int ir    : 1; /* ir flag: enable (1) or disable (0) irq */
 201        unsigned int _res2 : 4;
 202        unsigned int gisc  : 3; /* guest isc field */
 203        unsigned int _res3 : 6;
 204        unsigned int gf    : 2; /* gisa format */
 205        unsigned int _res4 : 1;
 206        unsigned int gisa  : 27;        /* gisa origin */
 207        unsigned int _res5 : 1;
 208        unsigned int isc   : 3; /* irq sub class */
 209};
 210
 211/**
 212 * ap_aqic(): Control interruption for a specific AP.
 213 * @qid: The AP queue number
 214 * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
 215 * @ind: The notification indicator byte
 216 *
 217 * Returns AP queue status.
 218 */
 219static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
 220                                             struct ap_qirq_ctrl qirqctrl,
 221                                             void *ind)
 222{
 223        register unsigned long reg0 asm ("0") = qid | (3UL << 24);
 224        register union {
 225                unsigned long value;
 226                struct ap_qirq_ctrl qirqctrl;
 227                struct ap_queue_status status;
 228        } reg1 asm ("1");
 229        register void *reg2 asm ("2") = ind;
 230
 231        reg1.qirqctrl = qirqctrl;
 232
 233        asm volatile(
 234                ".long 0xb2af0000"              /* PQAP(AQIC) */
 235                : "+d" (reg1)
 236                : "d" (reg0), "d" (reg2)
 237                : "cc");
 238
 239        return reg1.status;
 240}
 241
 242/*
 243 * union ap_qact_ap_info - used together with the
 244 * ap_aqic() function to provide a convenient way
 245 * to handle the ap info needed by the qact function.
 246 */
 247union ap_qact_ap_info {
 248        unsigned long val;
 249        struct {
 250                unsigned int      : 3;
 251                unsigned int mode : 3;
 252                unsigned int      : 26;
 253                unsigned int cat  : 8;
 254                unsigned int      : 8;
 255                unsigned char ver[2];
 256        };
 257};
 258
 259/**
 260 * ap_qact(): Query AP combatibility type.
 261 * @qid: The AP queue number
 262 * @apinfo: On input the info about the AP queue. On output the
 263 *          alternate AP queue info provided by the qact function
 264 *          in GR2 is stored in.
 265 *
 266 * Returns AP queue status. Check response_code field for failures.
 267 */
 268static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
 269                                             union ap_qact_ap_info *apinfo)
 270{
 271        register unsigned long reg0 asm ("0") = qid | (5UL << 24)
 272                | ((ifbit & 0x01) << 22);
 273        register union {
 274                unsigned long value;
 275                struct ap_queue_status status;
 276        } reg1 asm ("1");
 277        register unsigned long reg2 asm ("2");
 278
 279        reg1.value = apinfo->val;
 280
 281        asm volatile(
 282                ".long 0xb2af0000"              /* PQAP(QACT) */
 283                : "+d" (reg1), "=d" (reg2)
 284                : "d" (reg0)
 285                : "cc");
 286        apinfo->val = reg2;
 287        return reg1.status;
 288}
 289
 290/**
 291 * ap_nqap(): Send message to adjunct processor queue.
 292 * @qid: The AP queue number
 293 * @psmid: The program supplied message identifier
 294 * @msg: The message text
 295 * @length: The message length
 296 *
 297 * Returns AP queue status structure.
 298 * Condition code 1 on NQAP can't happen because the L bit is 1.
 299 * Condition code 2 on NQAP also means the send is incomplete,
 300 * because a segment boundary was reached. The NQAP is repeated.
 301 */
 302static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
 303                                             unsigned long long psmid,
 304                                             void *msg, size_t length)
 305{
 306        register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
 307        register struct ap_queue_status reg1 asm ("1");
 308        register unsigned long reg2 asm ("2") = (unsigned long) msg;
 309        register unsigned long reg3 asm ("3") = (unsigned long) length;
 310        register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
 311        register unsigned long reg5 asm ("5") = psmid & 0xffffffff;
 312
 313        asm volatile (
 314                "0: .long 0xb2ad0042\n"         /* NQAP */
 315                "   brc   2,0b"
 316                : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
 317                : "d" (reg4), "d" (reg5)
 318                : "cc", "memory");
 319        return reg1;
 320}
 321
 322/**
 323 * ap_dqap(): Receive message from adjunct processor queue.
 324 * @qid: The AP queue number
 325 * @psmid: Pointer to program supplied message identifier
 326 * @msg: The message text
 327 * @length: The message length
 328 *
 329 * Returns AP queue status structure.
 330 * Condition code 1 on DQAP means the receive has taken place
 331 * but only partially.  The response is incomplete, hence the
 332 * DQAP is repeated.
 333 * Condition code 2 on DQAP also means the receive is incomplete,
 334 * this time because a segment boundary was reached. Again, the
 335 * DQAP is repeated.
 336 * Note that gpr2 is used by the DQAP instruction to keep track of
 337 * any 'residual' length, in case the instruction gets interrupted.
 338 * Hence it gets zeroed before the instruction.
 339 */
 340static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
 341                                             unsigned long long *psmid,
 342                                             void *msg, size_t length)
 343{
 344        register unsigned long reg0 asm("0") = qid | 0x80000000UL;
 345        register struct ap_queue_status reg1 asm ("1");
 346        register unsigned long reg2 asm("2") = 0UL;
 347        register unsigned long reg4 asm("4") = (unsigned long) msg;
 348        register unsigned long reg5 asm("5") = (unsigned long) length;
 349        register unsigned long reg6 asm("6") = 0UL;
 350        register unsigned long reg7 asm("7") = 0UL;
 351
 352
 353        asm volatile(
 354                "0: .long 0xb2ae0064\n"         /* DQAP */
 355                "   brc   6,0b\n"
 356                : "+d" (reg0), "=d" (reg1), "+d" (reg2),
 357                  "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7)
 358                : : "cc", "memory");
 359        *psmid = (((unsigned long long) reg6) << 32) + reg7;
 360        return reg1;
 361}
 362
 363/*
 364 * Interface to tell the AP bus code that a configuration
 365 * change has happened. The bus code should at least do
 366 * an ap bus resource rescan.
 367 */
 368#if IS_ENABLED(CONFIG_ZCRYPT)
 369void ap_bus_cfg_chg(void);
 370#else
 371static inline void ap_bus_cfg_chg(void){};
 372#endif
 373
 374#endif /* _ASM_S390_AP_H_ */
 375