linux/drivers/s390/crypto/ap_asm.h
<<
>>
Prefs
   1/*
   2 * Copyright IBM Corp. 2016
   3 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
   4 *
   5 * Adjunct processor bus inline assemblies.
   6 */
   7
   8#ifndef _AP_ASM_H_
   9#define _AP_ASM_H_
  10
  11#include <asm/isc.h>
  12
  13/**
  14 * ap_intructions_available() - Test if AP instructions are available.
  15 *
  16 * Returns 0 if the AP instructions are installed.
  17 */
  18static inline int ap_instructions_available(void)
  19{
  20        register unsigned long reg0 asm ("0") = AP_MKQID(0, 0);
  21        register unsigned long reg1 asm ("1") = -ENODEV;
  22        register unsigned long reg2 asm ("2") = 0UL;
  23
  24        asm volatile(
  25                "   .long 0xb2af0000\n"         /* PQAP(TAPQ) */
  26                "0: la    %1,0\n"
  27                "1:\n"
  28                EX_TABLE(0b, 1b)
  29                : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc");
  30        return reg1;
  31}
  32
  33/**
  34 * ap_tapq(): Test adjunct processor queue.
  35 * @qid: The AP queue number
  36 * @info: Pointer to queue descriptor
  37 *
  38 * Returns AP queue status structure.
  39 */
  40static inline struct ap_queue_status ap_tapq(ap_qid_t qid, unsigned long *info)
  41{
  42        register unsigned long reg0 asm ("0") = qid;
  43        register struct ap_queue_status reg1 asm ("1");
  44        register unsigned long reg2 asm ("2") = 0UL;
  45
  46        asm volatile(".long 0xb2af0000"         /* PQAP(TAPQ) */
  47                     : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
  48        if (info)
  49                *info = reg2;
  50        return reg1;
  51}
  52
  53/**
  54 * ap_pqap_rapq(): Reset adjunct processor queue.
  55 * @qid: The AP queue number
  56 *
  57 * Returns AP queue status structure.
  58 */
  59static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
  60{
  61        register unsigned long reg0 asm ("0") = qid | 0x01000000UL;
  62        register struct ap_queue_status reg1 asm ("1");
  63        register unsigned long reg2 asm ("2") = 0UL;
  64
  65        asm volatile(
  66                ".long 0xb2af0000"              /* PQAP(RAPQ) */
  67                : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc");
  68        return reg1;
  69}
  70
  71/**
  72 * ap_aqic(): Control interruption for a specific AP.
  73 * @qid: The AP queue number
  74 * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
  75 * @ind: The notification indicator byte
  76 *
  77 * Returns AP queue status.
  78 */
  79static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
  80                                             struct ap_qirq_ctrl qirqctrl,
  81                                             void *ind)
  82{
  83        register unsigned long reg0 asm ("0") = qid | (3UL << 24);
  84        register struct ap_qirq_ctrl reg1_in asm ("1") = qirqctrl;
  85        register struct ap_queue_status reg1_out asm ("1");
  86        register void *reg2 asm ("2") = ind;
  87
  88        asm volatile(
  89                ".long 0xb2af0000"              /* PQAP(AQIC) */
  90                : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
  91                :
  92                : "cc");
  93        return reg1_out;
  94}
  95
  96/**
  97 * ap_qci(): Get AP configuration data
  98 *
  99 * Returns 0 on success, or -EOPNOTSUPP.
 100 */
 101static inline int ap_qci(void *config)
 102{
 103        register unsigned long reg0 asm ("0") = 0x04000000UL;
 104        register unsigned long reg1 asm ("1") = -EINVAL;
 105        register void *reg2 asm ("2") = (void *) config;
 106
 107        asm volatile(
 108                ".long 0xb2af0000\n"            /* PQAP(QCI) */
 109                "0: la    %1,0\n"
 110                "1:\n"
 111                EX_TABLE(0b, 1b)
 112                : "+d" (reg0), "+d" (reg1), "+d" (reg2)
 113                :
 114                : "cc", "memory");
 115
 116        return reg1;
 117}
 118
 119/*
 120 * struct ap_qact_ap_info - used together with the
 121 * ap_aqic() function to provide a convenient way
 122 * to handle the ap info needed by the qact function.
 123 */
 124struct ap_qact_ap_info {
 125        unsigned int _res1   : 3;
 126        unsigned int mode    : 3;
 127        unsigned int _res2   : 26;
 128        unsigned int cat     : 8;
 129        unsigned int _res3   : 8;
 130        unsigned char ver[2];
 131};
 132
 133/**
 134 * ap_qact(): Query AP combatibility type.
 135 * @qid: The AP queue number
 136 * @apinfo: On input the info about the AP queue (content of GR1
 137 *          according to the AR). On output the alternate AP queue
 138 *          info provided by the qact function in GR2 is stored in.
 139 *
 140 * Returns AP queue status. Check response_code field for failures.
 141 */
 142static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
 143                                             struct ap_qact_ap_info *apinfo)
 144{
 145        register unsigned long reg0 asm ("0") = qid | (5UL << 24)
 146                | ((ifbit & 0x01) << 22);
 147        register struct ap_qact_ap_info reg1_in asm ("1") = *apinfo;
 148        register struct ap_queue_status reg1_out asm ("1");
 149        register unsigned long reg2_in asm ("2") = 0;
 150        register struct ap_qact_ap_info reg2_out asm ("2");
 151
 152        asm volatile(
 153                ".long 0xb2af0000"              /* PQAP(QACT) */
 154                : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out),
 155                  "+d" (reg2_in), "=d" (reg2_out)
 156                :
 157                : "cc");
 158        *apinfo = reg2_out;
 159        return reg1_out;
 160}
 161
 162/**
 163 * ap_nqap(): Send message to adjunct processor queue.
 164 * @qid: The AP queue number
 165 * @psmid: The program supplied message identifier
 166 * @msg: The message text
 167 * @length: The message length
 168 *
 169 * Returns AP queue status structure.
 170 * Condition code 1 on NQAP can't happen because the L bit is 1.
 171 * Condition code 2 on NQAP also means the send is incomplete,
 172 * because a segment boundary was reached. The NQAP is repeated.
 173 */
 174static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
 175                                             unsigned long long psmid,
 176                                             void *msg, size_t length)
 177{
 178        register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
 179        register struct ap_queue_status reg1 asm ("1");
 180        register unsigned long reg2 asm ("2") = (unsigned long) msg;
 181        register unsigned long reg3 asm ("3") = (unsigned long) length;
 182        register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
 183        register unsigned long reg5 asm ("5") = psmid & 0xffffffff;
 184
 185        asm volatile (
 186                "0: .long 0xb2ad0042\n"         /* NQAP */
 187                "   brc   2,0b"
 188                : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
 189                : "d" (reg4), "d" (reg5)
 190                : "cc", "memory");
 191        return reg1;
 192}
 193
 194/**
 195 * ap_dqap(): Receive message from adjunct processor queue.
 196 * @qid: The AP queue number
 197 * @psmid: Pointer to program supplied message identifier
 198 * @msg: The message text
 199 * @length: The message length
 200 *
 201 * Returns AP queue status structure.
 202 * Condition code 1 on DQAP means the receive has taken place
 203 * but only partially.  The response is incomplete, hence the
 204 * DQAP is repeated.
 205 * Condition code 2 on DQAP also means the receive is incomplete,
 206 * this time because a segment boundary was reached. Again, the
 207 * DQAP is repeated.
 208 * Note that gpr2 is used by the DQAP instruction to keep track of
 209 * any 'residual' length, in case the instruction gets interrupted.
 210 * Hence it gets zeroed before the instruction.
 211 */
 212static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
 213                                             unsigned long long *psmid,
 214                                             void *msg, size_t length)
 215{
 216        register unsigned long reg0 asm("0") = qid | 0x80000000UL;
 217        register struct ap_queue_status reg1 asm ("1");
 218        register unsigned long reg2 asm("2") = 0UL;
 219        register unsigned long reg4 asm("4") = (unsigned long) msg;
 220        register unsigned long reg5 asm("5") = (unsigned long) length;
 221        register unsigned long reg6 asm("6") = 0UL;
 222        register unsigned long reg7 asm("7") = 0UL;
 223
 224
 225        asm volatile(
 226                "0: .long 0xb2ae0064\n"         /* DQAP */
 227                "   brc   6,0b\n"
 228                : "+d" (reg0), "=d" (reg1), "+d" (reg2),
 229                  "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7)
 230                : : "cc", "memory");
 231        *psmid = (((unsigned long long) reg6) << 32) + reg7;
 232        return reg1;
 233}
 234
 235#endif /* _AP_ASM_H_ */
 236