Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Adjunct processor (AP) interfaces
0004  *
0005  * Copyright IBM Corp. 2017
0006  *
0007  * Author(s): Tony Krowiak <akrowia@linux.vnet.ibm.com>
0008  *        Martin Schwidefsky <schwidefsky@de.ibm.com>
0009  *        Harald Freudenberger <freude@de.ibm.com>
0010  */
0011 
0012 #ifndef _ASM_S390_AP_H_
0013 #define _ASM_S390_AP_H_
0014 
0015 #include <linux/io.h>
0016 #include <asm/asm-extable.h>
0017 
0018 /**
0019  * The ap_qid_t identifier of an ap queue.
0020  * If the AP facilities test (APFT) facility is available,
0021  * card and queue index are 8 bit values, otherwise
0022  * card index is 6 bit and queue index a 4 bit value.
0023  */
0024 typedef unsigned int ap_qid_t;
0025 
0026 #define AP_MKQID(_card, _queue) (((_card) & 0xff) << 8 | ((_queue) & 0xff))
0027 #define AP_QID_CARD(_qid) (((_qid) >> 8) & 0xff)
0028 #define AP_QID_QUEUE(_qid) ((_qid) & 0xff)
0029 
0030 /**
0031  * struct ap_queue_status - Holds the AP queue status.
0032  * @queue_empty: Shows if queue is empty
0033  * @replies_waiting: Waiting replies
0034  * @queue_full: Is 1 if the queue is full
0035  * @irq_enabled: Shows if interrupts are enabled for the AP
0036  * @response_code: Holds the 8 bit response code
0037  *
0038  * The ap queue status word is returned by all three AP functions
0039  * (PQAP, NQAP and DQAP).  There's a set of flags in the first
0040  * byte, followed by a 1 byte response code.
0041  */
0042 struct ap_queue_status {
0043     unsigned int queue_empty    : 1;
0044     unsigned int replies_waiting    : 1;
0045     unsigned int queue_full     : 1;
0046     unsigned int _pad1      : 4;
0047     unsigned int irq_enabled    : 1;
0048     unsigned int response_code  : 8;
0049     unsigned int _pad2      : 16;
0050 };
0051 
0052 /**
0053  * ap_intructions_available() - Test if AP instructions are available.
0054  *
0055  * Returns true if the AP instructions are installed, otherwise false.
0056  */
0057 static inline bool ap_instructions_available(void)
0058 {
0059     unsigned long reg0 = AP_MKQID(0, 0);
0060     unsigned long reg1 = 0;
0061 
0062     asm volatile(
0063         "   lgr 0,%[reg0]\n"        /* qid into gr0 */
0064         "   lghi    1,0\n"          /* 0 into gr1 */
0065         "   lghi    2,0\n"          /* 0 into gr2 */
0066         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(TAPQ) */
0067         "0: la  %[reg1],1\n"        /* 1 into reg1 */
0068         "1:\n"
0069         EX_TABLE(0b, 1b)
0070         : [reg1] "+&d" (reg1)
0071         : [reg0] "d" (reg0)
0072         : "cc", "0", "1", "2");
0073     return reg1 != 0;
0074 }
0075 
0076 /**
0077  * ap_tapq(): Test adjunct processor queue.
0078  * @qid: The AP queue number
0079  * @info: Pointer to queue descriptor
0080  *
0081  * Returns AP queue status structure.
0082  */
0083 static inline struct ap_queue_status ap_tapq(ap_qid_t qid, unsigned long *info)
0084 {
0085     struct ap_queue_status reg1;
0086     unsigned long reg2;
0087 
0088     asm volatile(
0089         "   lgr 0,%[qid]\n"     /* qid into gr0 */
0090         "   lghi    2,0\n"          /* 0 into gr2 */
0091         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(TAPQ) */
0092         "   lgr %[reg1],1\n"        /* gr1 (status) into reg1 */
0093         "   lgr %[reg2],2\n"        /* gr2 into reg2 */
0094         : [reg1] "=&d" (reg1), [reg2] "=&d" (reg2)
0095         : [qid] "d" (qid)
0096         : "cc", "0", "1", "2");
0097     if (info)
0098         *info = reg2;
0099     return reg1;
0100 }
0101 
0102 /**
0103  * ap_test_queue(): Test adjunct processor queue.
0104  * @qid: The AP queue number
0105  * @tbit: Test facilities bit
0106  * @info: Pointer to queue descriptor
0107  *
0108  * Returns AP queue status structure.
0109  */
0110 static inline struct ap_queue_status ap_test_queue(ap_qid_t qid,
0111                            int tbit,
0112                            unsigned long *info)
0113 {
0114     if (tbit)
0115         qid |= 1UL << 23; /* set T bit*/
0116     return ap_tapq(qid, info);
0117 }
0118 
0119 /**
0120  * ap_pqap_rapq(): Reset adjunct processor queue.
0121  * @qid: The AP queue number
0122  *
0123  * Returns AP queue status structure.
0124  */
0125 static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
0126 {
0127     unsigned long reg0 = qid | (1UL << 24);  /* fc 1UL is RAPQ */
0128     struct ap_queue_status reg1;
0129 
0130     asm volatile(
0131         "   lgr 0,%[reg0]\n"        /* qid arg into gr0 */
0132         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(RAPQ) */
0133         "   lgr %[reg1],1\n"        /* gr1 (status) into reg1 */
0134         : [reg1] "=&d" (reg1)
0135         : [reg0] "d" (reg0)
0136         : "cc", "0", "1");
0137     return reg1;
0138 }
0139 
0140 /**
0141  * ap_pqap_zapq(): Reset and zeroize adjunct processor queue.
0142  * @qid: The AP queue number
0143  *
0144  * Returns AP queue status structure.
0145  */
0146 static inline struct ap_queue_status ap_zapq(ap_qid_t qid)
0147 {
0148     unsigned long reg0 = qid | (2UL << 24);  /* fc 2UL is ZAPQ */
0149     struct ap_queue_status reg1;
0150 
0151     asm volatile(
0152         "   lgr 0,%[reg0]\n"        /* qid arg into gr0 */
0153         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(ZAPQ) */
0154         "   lgr %[reg1],1\n"        /* gr1 (status) into reg1 */
0155         : [reg1] "=&d" (reg1)
0156         : [reg0] "d" (reg0)
0157         : "cc", "0", "1");
0158     return reg1;
0159 }
0160 
0161 /**
0162  * struct ap_config_info - convenience struct for AP crypto
0163  * config info as returned by the ap_qci() function.
0164  */
0165 struct ap_config_info {
0166     unsigned int apsc    : 1;   /* S bit */
0167     unsigned int apxa    : 1;   /* N bit */
0168     unsigned int qact    : 1;   /* C bit */
0169     unsigned int rc8a    : 1;   /* R bit */
0170     unsigned char _reserved1 : 4;
0171     unsigned char _reserved2[3];
0172     unsigned char Na;       /* max # of APs - 1 */
0173     unsigned char Nd;       /* max # of Domains - 1 */
0174     unsigned char _reserved3[10];
0175     unsigned int apm[8];        /* AP ID mask */
0176     unsigned int aqm[8];        /* AP (usage) queue mask */
0177     unsigned int adm[8];        /* AP (control) domain mask */
0178     unsigned char _reserved4[16];
0179 } __aligned(8);
0180 
0181 /**
0182  * ap_qci(): Get AP configuration data
0183  *
0184  * Returns 0 on success, or -EOPNOTSUPP.
0185  */
0186 static inline int ap_qci(struct ap_config_info *config)
0187 {
0188     unsigned long reg0 = 4UL << 24;  /* fc 4UL is QCI */
0189     unsigned long reg1 = -EOPNOTSUPP;
0190     struct ap_config_info *reg2 = config;
0191 
0192     asm volatile(
0193         "   lgr 0,%[reg0]\n"        /* QCI fc into gr0 */
0194         "   lgr 2,%[reg2]\n"        /* ptr to config into gr2 */
0195         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(QCI) */
0196         "0: la  %[reg1],0\n"        /* good case, QCI fc available */
0197         "1:\n"
0198         EX_TABLE(0b, 1b)
0199         : [reg1] "+&d" (reg1)
0200         : [reg0] "d" (reg0), [reg2] "d" (reg2)
0201         : "cc", "memory", "0", "2");
0202 
0203     return reg1;
0204 }
0205 
0206 /*
0207  * struct ap_qirq_ctrl - convenient struct for easy invocation
0208  * of the ap_aqic() function. This struct is passed as GR1
0209  * parameter to the PQAP(AQIC) instruction. For details please
0210  * see the AR documentation.
0211  */
0212 struct ap_qirq_ctrl {
0213     unsigned int _res1 : 8;
0214     unsigned int zone  : 8; /* zone info */
0215     unsigned int ir    : 1; /* ir flag: enable (1) or disable (0) irq */
0216     unsigned int _res2 : 4;
0217     unsigned int gisc  : 3; /* guest isc field */
0218     unsigned int _res3 : 6;
0219     unsigned int gf    : 2; /* gisa format */
0220     unsigned int _res4 : 1;
0221     unsigned int gisa  : 27;    /* gisa origin */
0222     unsigned int _res5 : 1;
0223     unsigned int isc   : 3; /* irq sub class */
0224 };
0225 
0226 /**
0227  * ap_aqic(): Control interruption for a specific AP.
0228  * @qid: The AP queue number
0229  * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
0230  * @pa_ind: Physical address of the notification indicator byte
0231  *
0232  * Returns AP queue status.
0233  */
0234 static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
0235                          struct ap_qirq_ctrl qirqctrl,
0236                          phys_addr_t pa_ind)
0237 {
0238     unsigned long reg0 = qid | (3UL << 24);  /* fc 3UL is AQIC */
0239     union {
0240         unsigned long value;
0241         struct ap_qirq_ctrl qirqctrl;
0242         struct ap_queue_status status;
0243     } reg1;
0244     unsigned long reg2 = pa_ind;
0245 
0246     reg1.qirqctrl = qirqctrl;
0247 
0248     asm volatile(
0249         "   lgr 0,%[reg0]\n"        /* qid param into gr0 */
0250         "   lgr 1,%[reg1]\n"        /* irq ctrl into gr1 */
0251         "   lgr 2,%[reg2]\n"        /* ni addr into gr2 */
0252         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(AQIC) */
0253         "   lgr %[reg1],1\n"        /* gr1 (status) into reg1 */
0254         : [reg1] "+&d" (reg1)
0255         : [reg0] "d" (reg0), [reg2] "d" (reg2)
0256         : "cc", "0", "1", "2");
0257 
0258     return reg1.status;
0259 }
0260 
0261 /*
0262  * union ap_qact_ap_info - used together with the
0263  * ap_aqic() function to provide a convenient way
0264  * to handle the ap info needed by the qact function.
0265  */
0266 union ap_qact_ap_info {
0267     unsigned long val;
0268     struct {
0269         unsigned int      : 3;
0270         unsigned int mode : 3;
0271         unsigned int      : 26;
0272         unsigned int cat  : 8;
0273         unsigned int      : 8;
0274         unsigned char ver[2];
0275     };
0276 };
0277 
0278 /**
0279  * ap_qact(): Query AP combatibility type.
0280  * @qid: The AP queue number
0281  * @apinfo: On input the info about the AP queue. On output the
0282  *      alternate AP queue info provided by the qact function
0283  *      in GR2 is stored in.
0284  *
0285  * Returns AP queue status. Check response_code field for failures.
0286  */
0287 static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
0288                          union ap_qact_ap_info *apinfo)
0289 {
0290     unsigned long reg0 = qid | (5UL << 24) | ((ifbit & 0x01) << 22);
0291     union {
0292         unsigned long value;
0293         struct ap_queue_status status;
0294     } reg1;
0295     unsigned long reg2;
0296 
0297     reg1.value = apinfo->val;
0298 
0299     asm volatile(
0300         "   lgr 0,%[reg0]\n"        /* qid param into gr0 */
0301         "   lgr 1,%[reg1]\n"        /* qact in info into gr1 */
0302         "   .insn   rre,0xb2af0000,0,0\n"   /* PQAP(QACT) */
0303         "   lgr %[reg1],1\n"        /* gr1 (status) into reg1 */
0304         "   lgr %[reg2],2\n"        /* qact out info into reg2 */
0305         : [reg1] "+&d" (reg1), [reg2] "=&d" (reg2)
0306         : [reg0] "d" (reg0)
0307         : "cc", "0", "1", "2");
0308     apinfo->val = reg2;
0309     return reg1.status;
0310 }
0311 
0312 /**
0313  * ap_nqap(): Send message to adjunct processor queue.
0314  * @qid: The AP queue number
0315  * @psmid: The program supplied message identifier
0316  * @msg: The message text
0317  * @length: The message length
0318  *
0319  * Returns AP queue status structure.
0320  * Condition code 1 on NQAP can't happen because the L bit is 1.
0321  * Condition code 2 on NQAP also means the send is incomplete,
0322  * because a segment boundary was reached. The NQAP is repeated.
0323  */
0324 static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
0325                          unsigned long long psmid,
0326                          void *msg, size_t length)
0327 {
0328     unsigned long reg0 = qid | 0x40000000UL;  /* 0x4... is last msg part */
0329     union register_pair nqap_r1, nqap_r2;
0330     struct ap_queue_status reg1;
0331 
0332     nqap_r1.even = (unsigned int)(psmid >> 32);
0333     nqap_r1.odd  = psmid & 0xffffffff;
0334     nqap_r2.even = (unsigned long)msg;
0335     nqap_r2.odd  = (unsigned long)length;
0336 
0337     asm volatile (
0338         "   lgr 0,%[reg0]\n"  /* qid param in gr0 */
0339         "0: .insn   rre,0xb2ad0000,%[nqap_r1],%[nqap_r2]\n"
0340         "   brc 2,0b\n"       /* handle partial completion */
0341         "   lgr %[reg1],1\n"  /* gr1 (status) into reg1 */
0342         : [reg0] "+&d" (reg0), [reg1] "=&d" (reg1),
0343           [nqap_r2] "+&d" (nqap_r2.pair)
0344         : [nqap_r1] "d" (nqap_r1.pair)
0345         : "cc", "memory", "0", "1");
0346     return reg1;
0347 }
0348 
0349 /**
0350  * ap_dqap(): Receive message from adjunct processor queue.
0351  * @qid: The AP queue number
0352  * @psmid: Pointer to program supplied message identifier
0353  * @msg: The message text
0354  * @length: The message length
0355  * @reslength: Resitual length on return
0356  * @resgr0: input: gr0 value (only used if != 0), output: resitual gr0 content
0357  *
0358  * Returns AP queue status structure.
0359  * Condition code 1 on DQAP means the receive has taken place
0360  * but only partially.  The response is incomplete, hence the
0361  * DQAP is repeated.
0362  * Condition code 2 on DQAP also means the receive is incomplete,
0363  * this time because a segment boundary was reached. Again, the
0364  * DQAP is repeated.
0365  * Note that gpr2 is used by the DQAP instruction to keep track of
0366  * any 'residual' length, in case the instruction gets interrupted.
0367  * Hence it gets zeroed before the instruction.
0368  * If the message does not fit into the buffer, this function will
0369  * return with a truncated message and the reply in the firmware queue
0370  * is not removed. This is indicated to the caller with an
0371  * ap_queue_status response_code value of all bits on (0xFF) and (if
0372  * the reslength ptr is given) the remaining length is stored in
0373  * *reslength and (if the resgr0 ptr is given) the updated gr0 value
0374  * for further processing of this msg entry is stored in *resgr0. The
0375  * caller needs to detect this situation and should invoke ap_dqap
0376  * with a valid resgr0 ptr and a value in there != 0 to indicate that
0377  * *resgr0 is to be used instead of qid to further process this entry.
0378  */
0379 static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
0380                          unsigned long long *psmid,
0381                          void *msg, size_t length,
0382                          size_t *reslength,
0383                          unsigned long *resgr0)
0384 {
0385     unsigned long reg0 = resgr0 && *resgr0 ? *resgr0 : qid | 0x80000000UL;
0386     struct ap_queue_status reg1;
0387     unsigned long reg2;
0388     union register_pair rp1, rp2;
0389 
0390     rp1.even = 0UL;
0391     rp1.odd  = 0UL;
0392     rp2.even = (unsigned long)msg;
0393     rp2.odd  = (unsigned long)length;
0394 
0395     asm volatile(
0396         "   lgr 0,%[reg0]\n"   /* qid param into gr0 */
0397         "   lghi    2,0\n"         /* 0 into gr2 (res length) */
0398         "0: ltgr    %N[rp2],%N[rp2]\n" /* check buf len */
0399         "   jz  2f\n"          /* go out if buf len is 0 */
0400         "1: .insn   rre,0xb2ae0000,%[rp1],%[rp2]\n"
0401         "   brc 6,0b\n"        /* handle partial complete */
0402         "2: lgr %[reg0],0\n"   /* gr0 (qid + info) into reg0 */
0403         "   lgr %[reg1],1\n"   /* gr1 (status) into reg1 */
0404         "   lgr %[reg2],2\n"   /* gr2 (res length) into reg2 */
0405         : [reg0] "+&d" (reg0), [reg1] "=&d" (reg1), [reg2] "=&d" (reg2),
0406           [rp1] "+&d" (rp1.pair), [rp2] "+&d" (rp2.pair)
0407         :
0408         : "cc", "memory", "0", "1", "2");
0409 
0410     if (reslength)
0411         *reslength = reg2;
0412     if (reg2 != 0 && rp2.odd == 0) {
0413         /*
0414          * Partially complete, status in gr1 is not set.
0415          * Signal the caller that this dqap is only partially received
0416          * with a special status response code 0xFF and *resgr0 updated
0417          */
0418         reg1.response_code = 0xFF;
0419         if (resgr0)
0420             *resgr0 = reg0;
0421     } else {
0422         *psmid = (((unsigned long long)rp1.even) << 32) + rp1.odd;
0423         if (resgr0)
0424             *resgr0 = 0;
0425     }
0426 
0427     return reg1;
0428 }
0429 
0430 /*
0431  * Interface to tell the AP bus code that a configuration
0432  * change has happened. The bus code should at least do
0433  * an ap bus resource rescan.
0434  */
0435 #if IS_ENABLED(CONFIG_ZCRYPT)
0436 void ap_bus_cfg_chg(void);
0437 #else
0438 static inline void ap_bus_cfg_chg(void){}
0439 #endif
0440 
0441 #endif /* _ASM_S390_AP_H_ */