/* SPDX-License-Identifier: GPL-2.0 */1/*2* Adjunct processor (AP) interfaces3*4* Copyright IBM Corp. 20175*6* Author(s): Tony Krowiak <[email protected]>7* Martin Schwidefsky <[email protected]>8* Harald Freudenberger <[email protected]>9*/1011#ifndef _ASM_S390_AP_H_12#define _ASM_S390_AP_H_1314#include <linux/io.h>15#include <asm/asm-extable.h>1617/**18* The ap_qid_t identifier of an ap queue.19* If the AP facilities test (APFT) facility is available,20* card and queue index are 8 bit values, otherwise21* card index is 6 bit and queue index a 4 bit value.22*/23typedef unsigned int ap_qid_t;2425#define AP_MKQID(_card, _queue) (((_card) & 0xff) << 8 | ((_queue) & 0xff))26#define AP_QID_CARD(_qid) (((_qid) >> 8) & 0xff)27#define AP_QID_QUEUE(_qid) ((_qid) & 0xff)2829/**30* struct ap_queue_status - Holds the AP queue status.31* @queue_empty: Shows if queue is empty32* @replies_waiting: Waiting replies33* @queue_full: Is 1 if the queue is full34* @irq_enabled: Shows if interrupts are enabled for the AP35* @response_code: Holds the 8 bit response code36*37* The ap queue status word is returned by all three AP functions38* (PQAP, NQAP and DQAP). There's a set of flags in the first39* byte, followed by a 1 byte response code.40*/41struct ap_queue_status {42unsigned int queue_empty : 1;43unsigned int replies_waiting : 1;44unsigned int queue_full : 1;45unsigned int : 3;46unsigned int async : 1;47unsigned int irq_enabled : 1;48unsigned int response_code : 8;49unsigned int : 16;50};5152/*53* AP queue status reg union to access the reg154* register with the lower 32 bits comprising the55* ap queue status.56*/57union ap_queue_status_reg {58unsigned long value;59struct {60u32 _pad;61struct ap_queue_status status;62};63};6465/**66* ap_intructions_available() - Test if AP instructions are available.67*68* Returns true if the AP instructions are installed, otherwise false.69*/70static inline bool ap_instructions_available(void)71{72unsigned long reg0 = AP_MKQID(0, 0);73unsigned long reg1 = 0;7475asm volatile(76" lgr 0,%[reg0]\n" /* qid into gr0 */77" lghi 1,0\n" /* 0 into gr1 */78" lghi 2,0\n" /* 0 into gr2 */79" .insn rre,0xb2af0000,0,0\n" /* PQAP(TAPQ) */80"0: la %[reg1],1\n" /* 1 into reg1 */81"1:\n"82EX_TABLE(0b, 1b)83: [reg1] "+&d" (reg1)84: [reg0] "d" (reg0)85: "cc", "0", "1", "2");86return reg1 != 0;87}8889/* TAPQ register GR2 response struct */90struct ap_tapq_hwinfo {91union {92unsigned long value;93struct {94unsigned int fac : 32; /* facility bits */95unsigned int apinfo : 32; /* ap type, ... */96};97struct {98unsigned int apsc : 1; /* APSC */99unsigned int mex4k : 1; /* AP4KM */100unsigned int crt4k : 1; /* AP4KC */101unsigned int cca : 1; /* D */102unsigned int accel : 1; /* A */103unsigned int ep11 : 1; /* X */104unsigned int apxa : 1; /* APXA */105unsigned int slcf : 1; /* Cmd filtering avail. */106unsigned int class : 8;107unsigned int bs : 2; /* SE bind/assoc */108unsigned int : 14;109unsigned int at : 8; /* ap type */110unsigned int nd : 8; /* nr of domains */111unsigned int : 4;112unsigned int ml : 4; /* apxl ml */113unsigned int : 4;114unsigned int qd : 4; /* queue depth */115};116};117};118119/*120* Convenience defines to be used with the bs field from struct ap_tapq_gr2121*/122#define AP_BS_Q_USABLE 0123#define AP_BS_Q_USABLE_NO_SECURE_KEY 1124#define AP_BS_Q_AVAIL_FOR_BINDING 2125#define AP_BS_Q_UNUSABLE 3126127/**128* ap_tapq(): Test adjunct processor queue.129* @qid: The AP queue number130* @info: Pointer to tapq hwinfo struct131*132* Returns AP queue status structure.133*/134static inline struct ap_queue_status ap_tapq(ap_qid_t qid,135struct ap_tapq_hwinfo *info)136{137union ap_queue_status_reg reg1;138unsigned long reg2;139140asm volatile(141" lgr 0,%[qid]\n" /* qid into gr0 */142" lghi 2,0\n" /* 0 into gr2 */143" .insn rre,0xb2af0000,0,0\n" /* PQAP(TAPQ) */144" lgr %[reg1],1\n" /* gr1 (status) into reg1 */145" lgr %[reg2],2\n" /* gr2 into reg2 */146: [reg1] "=&d" (reg1.value), [reg2] "=&d" (reg2)147: [qid] "d" (qid)148: "cc", "0", "1", "2");149if (info)150info->value = reg2;151return reg1.status;152}153154/**155* ap_test_queue(): Test adjunct processor queue.156* @qid: The AP queue number157* @tbit: Test facilities bit158* @info: Ptr to tapq gr2 struct159*160* Returns AP queue status structure.161*/162static inline struct ap_queue_status ap_test_queue(ap_qid_t qid, int tbit,163struct ap_tapq_hwinfo *info)164{165if (tbit)166qid |= 1UL << 23; /* set T bit*/167return ap_tapq(qid, info);168}169170/**171* ap_pqap_rapq(): Reset adjunct processor queue.172* @qid: The AP queue number173* @fbit: if != 0 set F bit174*175* Returns AP queue status structure.176*/177static inline struct ap_queue_status ap_rapq(ap_qid_t qid, int fbit)178{179unsigned long reg0 = qid | (1UL << 24); /* fc 1UL is RAPQ */180union ap_queue_status_reg reg1;181182if (fbit)183reg0 |= 1UL << 22;184185asm volatile(186" lgr 0,%[reg0]\n" /* qid arg into gr0 */187" .insn rre,0xb2af0000,0,0\n" /* PQAP(RAPQ) */188" lgr %[reg1],1\n" /* gr1 (status) into reg1 */189: [reg1] "=&d" (reg1.value)190: [reg0] "d" (reg0)191: "cc", "0", "1");192return reg1.status;193}194195/**196* ap_pqap_zapq(): Reset and zeroize adjunct processor queue.197* @qid: The AP queue number198* @fbit: if != 0 set F bit199*200* Returns AP queue status structure.201*/202static inline struct ap_queue_status ap_zapq(ap_qid_t qid, int fbit)203{204unsigned long reg0 = qid | (2UL << 24); /* fc 2UL is ZAPQ */205union ap_queue_status_reg reg1;206207if (fbit)208reg0 |= 1UL << 22;209210asm volatile(211" lgr 0,%[reg0]\n" /* qid arg into gr0 */212" .insn rre,0xb2af0000,0,0\n" /* PQAP(ZAPQ) */213" lgr %[reg1],1\n" /* gr1 (status) into reg1 */214: [reg1] "=&d" (reg1.value)215: [reg0] "d" (reg0)216: "cc", "0", "1");217return reg1.status;218}219220/**221* struct ap_config_info - convenience struct for AP crypto222* config info as returned by the ap_qci() function.223*/224struct ap_config_info {225union {226unsigned int flags;227struct {228unsigned int apsc : 1; /* S bit */229unsigned int apxa : 1; /* N bit */230unsigned int qact : 1; /* C bit */231unsigned int rc8a : 1; /* R bit */232unsigned int : 4;233unsigned int apsb : 1; /* B bit */234unsigned int : 23;235};236};237unsigned char na; /* max # of APs - 1 */238unsigned char nd; /* max # of Domains - 1 */239unsigned char _reserved0[10];240unsigned int apm[8]; /* AP ID mask */241unsigned int aqm[8]; /* AP (usage) queue mask */242unsigned int adm[8]; /* AP (control) domain mask */243unsigned char _reserved1[16];244} __aligned(8);245246/**247* ap_qci(): Get AP configuration data248*249* Returns 0 on success, or -EOPNOTSUPP.250*/251static inline int ap_qci(struct ap_config_info *config)252{253unsigned long reg0 = 4UL << 24; /* fc 4UL is QCI */254unsigned long reg1 = -EOPNOTSUPP;255struct ap_config_info *reg2 = config;256257asm volatile(258" lgr 0,%[reg0]\n" /* QCI fc into gr0 */259" lgr 2,%[reg2]\n" /* ptr to config into gr2 */260" .insn rre,0xb2af0000,0,0\n" /* PQAP(QCI) */261"0: la %[reg1],0\n" /* good case, QCI fc available */262"1:\n"263EX_TABLE(0b, 1b)264: [reg1] "+&d" (reg1)265: [reg0] "d" (reg0), [reg2] "d" (reg2)266: "cc", "memory", "0", "2");267268return reg1;269}270271/*272* struct ap_qirq_ctrl - convenient struct for easy invocation273* of the ap_aqic() function. This struct is passed as GR1274* parameter to the PQAP(AQIC) instruction. For details please275* see the AR documentation.276*/277union ap_qirq_ctrl {278unsigned long value;279struct {280unsigned int : 8;281unsigned int zone : 8; /* zone info */282unsigned int ir : 1; /* ir flag: enable (1) or disable (0) irq */283unsigned int : 4;284unsigned int gisc : 3; /* guest isc field */285unsigned int : 6;286unsigned int gf : 2; /* gisa format */287unsigned int : 1;288unsigned int gisa : 27; /* gisa origin */289unsigned int : 1;290unsigned int isc : 3; /* irq sub class */291};292};293294/**295* ap_aqic(): Control interruption for a specific AP.296* @qid: The AP queue number297* @qirqctrl: struct ap_qirq_ctrl (64 bit value)298* @pa_ind: Physical address of the notification indicator byte299*300* Returns AP queue status.301*/302static inline struct ap_queue_status ap_aqic(ap_qid_t qid,303union ap_qirq_ctrl qirqctrl,304phys_addr_t pa_ind)305{306unsigned long reg0 = qid | (3UL << 24); /* fc 3UL is AQIC */307union ap_queue_status_reg reg1;308unsigned long reg2 = pa_ind;309310reg1.value = qirqctrl.value;311312asm volatile(313" lgr 0,%[reg0]\n" /* qid param into gr0 */314" lgr 1,%[reg1]\n" /* irq ctrl into gr1 */315" lgr 2,%[reg2]\n" /* ni addr into gr2 */316" .insn rre,0xb2af0000,0,0\n" /* PQAP(AQIC) */317" lgr %[reg1],1\n" /* gr1 (status) into reg1 */318: [reg1] "+&d" (reg1.value)319: [reg0] "d" (reg0), [reg2] "d" (reg2)320: "cc", "memory", "0", "1", "2");321322return reg1.status;323}324325/*326* union ap_qact_ap_info - used together with the327* ap_aqic() function to provide a convenient way328* to handle the ap info needed by the qact function.329*/330union ap_qact_ap_info {331unsigned long val;332struct {333unsigned int : 3;334unsigned int mode : 3;335unsigned int : 26;336unsigned int cat : 8;337unsigned int : 8;338unsigned char ver[2];339};340};341342/**343* ap_qact(): Query AP compatibility type.344* @qid: The AP queue number345* @apinfo: On input the info about the AP queue. On output the346* alternate AP queue info provided by the qact function347* in GR2 is stored in.348*349* Returns AP queue status. Check response_code field for failures.350*/351static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,352union ap_qact_ap_info *apinfo)353{354unsigned long reg0 = qid | (5UL << 24) | ((ifbit & 0x01) << 22);355union ap_queue_status_reg reg1;356unsigned long reg2;357358reg1.value = apinfo->val;359360asm volatile(361" lgr 0,%[reg0]\n" /* qid param into gr0 */362" lgr 1,%[reg1]\n" /* qact in info into gr1 */363" .insn rre,0xb2af0000,0,0\n" /* PQAP(QACT) */364" lgr %[reg1],1\n" /* gr1 (status) into reg1 */365" lgr %[reg2],2\n" /* qact out info into reg2 */366: [reg1] "+&d" (reg1.value), [reg2] "=&d" (reg2)367: [reg0] "d" (reg0)368: "cc", "0", "1", "2");369apinfo->val = reg2;370return reg1.status;371}372373/*374* ap_bapq(): SE bind AP queue.375* @qid: The AP queue number376*377* Returns AP queue status structure.378*379* Invoking this function in a non-SE environment380* may case a specification exception.381*/382static inline struct ap_queue_status ap_bapq(ap_qid_t qid)383{384unsigned long reg0 = qid | (7UL << 24); /* fc 7 is BAPQ */385union ap_queue_status_reg reg1;386387asm volatile(388" lgr 0,%[reg0]\n" /* qid arg into gr0 */389" .insn rre,0xb2af0000,0,0\n" /* PQAP(BAPQ) */390" lgr %[reg1],1\n" /* gr1 (status) into reg1 */391: [reg1] "=&d" (reg1.value)392: [reg0] "d" (reg0)393: "cc", "0", "1");394395return reg1.status;396}397398/*399* ap_aapq(): SE associate AP queue.400* @qid: The AP queue number401* @sec_idx: The secret index402*403* Returns AP queue status structure.404*405* Invoking this function in a non-SE environment406* may case a specification exception.407*/408static inline struct ap_queue_status ap_aapq(ap_qid_t qid, unsigned int sec_idx)409{410unsigned long reg0 = qid | (8UL << 24); /* fc 8 is AAPQ */411unsigned long reg2 = sec_idx;412union ap_queue_status_reg reg1;413414asm volatile(415" lgr 0,%[reg0]\n" /* qid arg into gr0 */416" lgr 2,%[reg2]\n" /* secret index into gr2 */417" .insn rre,0xb2af0000,0,0\n" /* PQAP(AAPQ) */418" lgr %[reg1],1\n" /* gr1 (status) into reg1 */419: [reg1] "=&d" (reg1.value)420: [reg0] "d" (reg0), [reg2] "d" (reg2)421: "cc", "0", "1", "2");422423return reg1.status;424}425426/**427* ap_nqap(): Send message to adjunct processor queue.428* @qid: The AP queue number429* @psmid: The program supplied message identifier430* @msg: The message text431* @length: The message length432*433* Returns AP queue status structure.434* Condition code 1 on NQAP can't happen because the L bit is 1.435* Condition code 2 on NQAP also means the send is incomplete,436* because a segment boundary was reached. The NQAP is repeated.437*/438static inline struct ap_queue_status ap_nqap(ap_qid_t qid,439unsigned long long psmid,440void *msg, size_t length)441{442unsigned long reg0 = qid | 0x40000000UL; /* 0x4... is last msg part */443union register_pair nqap_r1, nqap_r2;444union ap_queue_status_reg reg1;445446nqap_r1.even = (unsigned int)(psmid >> 32);447nqap_r1.odd = psmid & 0xffffffff;448nqap_r2.even = (unsigned long)msg;449nqap_r2.odd = (unsigned long)length;450451asm volatile (452" lgr 0,%[reg0]\n" /* qid param in gr0 */453"0: .insn rre,0xb2ad0000,%[nqap_r1],%[nqap_r2]\n"454" brc 2,0b\n" /* handle partial completion */455" lgr %[reg1],1\n" /* gr1 (status) into reg1 */456: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1.value),457[nqap_r2] "+&d" (nqap_r2.pair)458: [nqap_r1] "d" (nqap_r1.pair)459: "cc", "memory", "0", "1");460return reg1.status;461}462463/**464* ap_dqap(): Receive message from adjunct processor queue.465* @qid: The AP queue number466* @psmid: Pointer to program supplied message identifier467* @msg: Pointer to message buffer468* @msglen: Message buffer size469* @length: Pointer to length of actually written bytes470* @reslength: Residual length on return471* @resgr0: input: gr0 value (only used if != 0), output: residual gr0 content472*473* Returns AP queue status structure.474* Condition code 1 on DQAP means the receive has taken place475* but only partially. The response is incomplete, hence the476* DQAP is repeated.477* Condition code 2 on DQAP also means the receive is incomplete,478* this time because a segment boundary was reached. Again, the479* DQAP is repeated.480* Note that gpr2 is used by the DQAP instruction to keep track of481* any 'residual' length, in case the instruction gets interrupted.482* Hence it gets zeroed before the instruction.483* If the message does not fit into the buffer, this function will484* return with a truncated message and the reply in the firmware queue485* is not removed. This is indicated to the caller with an486* ap_queue_status response_code value of all bits on (0xFF) and (if487* the reslength ptr is given) the remaining length is stored in488* *reslength and (if the resgr0 ptr is given) the updated gr0 value489* for further processing of this msg entry is stored in *resgr0. The490* caller needs to detect this situation and should invoke ap_dqap491* with a valid resgr0 ptr and a value in there != 0 to indicate that492* *resgr0 is to be used instead of qid to further process this entry.493*/494static inline struct ap_queue_status ap_dqap(ap_qid_t qid,495unsigned long *psmid,496void *msg, size_t msglen,497size_t *length,498size_t *reslength,499unsigned long *resgr0)500{501unsigned long reg0 = resgr0 && *resgr0 ? *resgr0 : qid | 0x80000000UL;502union ap_queue_status_reg reg1;503unsigned long reg2;504union register_pair rp1, rp2;505506rp1.even = 0UL;507rp1.odd = 0UL;508rp2.even = (unsigned long)msg;509rp2.odd = (unsigned long)msglen;510511asm volatile(512" lgr 0,%[reg0]\n" /* qid param into gr0 */513" lghi 2,0\n" /* 0 into gr2 (res length) */514"0: ltgr %N[rp2],%N[rp2]\n" /* check buf len */515" jz 2f\n" /* go out if buf len is 0 */516"1: .insn rre,0xb2ae0000,%[rp1],%[rp2]\n"517" brc 6,0b\n" /* handle partial complete */518"2: lgr %[reg0],0\n" /* gr0 (qid + info) into reg0 */519" lgr %[reg1],1\n" /* gr1 (status) into reg1 */520" lgr %[reg2],2\n" /* gr2 (res length) into reg2 */521: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1.value),522[reg2] "=&d" (reg2), [rp1] "+&d" (rp1.pair),523[rp2] "+&d" (rp2.pair)524:525: "cc", "memory", "0", "1", "2");526527if (reslength)528*reslength = reg2;529if (reg2 != 0 && rp2.odd == 0) {530/*531* Partially complete, status in gr1 is not set.532* Signal the caller that this dqap is only partially received533* with a special status response code 0xFF and *resgr0 updated534*/535reg1.status.response_code = 0xFF;536if (resgr0)537*resgr0 = reg0;538} else {539*psmid = (rp1.even << 32) + rp1.odd;540if (resgr0)541*resgr0 = 0;542}543544/* update *length with the nr of bytes stored into the msg buffer */545if (length)546*length = msglen - rp2.odd;547548return reg1.status;549}550551#endif /* _ASM_S390_AP_H_ */552553554