1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright IBM Corp. 2016
4 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
6 * Adjunct processor bus inline assemblies.
15 * ap_intructions_available() - Test if AP instructions are available.
17 * Returns 0 if the AP instructions are installed.
19 static inline int ap_instructions_available(void)
21 register unsigned long reg0 asm ("0") = AP_MKQID(0, 0);
22 register unsigned long reg1 asm ("1") = -ENODEV;
23 register unsigned long reg2 asm ("2");
26 " .long 0xb2af0000\n" /* PQAP(TAPQ) */
30 : "+d" (reg1), "=d" (reg2)
37 * ap_tapq(): Test adjunct processor queue.
38 * @qid: The AP queue number
39 * @info: Pointer to queue descriptor
41 * Returns AP queue status structure.
43 static inline struct ap_queue_status ap_tapq(ap_qid_t qid, unsigned long *info)
45 register unsigned long reg0 asm ("0") = qid;
46 register struct ap_queue_status reg1 asm ("1");
47 register unsigned long reg2 asm ("2");
49 asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */
50 : "=d" (reg1), "=d" (reg2)
59 * ap_pqap_rapq(): Reset adjunct processor queue.
60 * @qid: The AP queue number
62 * Returns AP queue status structure.
64 static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
66 register unsigned long reg0 asm ("0") = qid | (1UL << 24);
67 register struct ap_queue_status reg1 asm ("1");
70 ".long 0xb2af0000" /* PQAP(RAPQ) */
78 * ap_pqap_zapq(): Reset and zeroize adjunct processor queue.
79 * @qid: The AP queue number
81 * Returns AP queue status structure.
83 static inline struct ap_queue_status ap_zapq(ap_qid_t qid)
85 register unsigned long reg0 asm ("0") = qid | (2UL << 24);
86 register struct ap_queue_status reg1 asm ("1");
89 ".long 0xb2af0000" /* PQAP(ZAPQ) */
97 * ap_aqic(): Control interruption for a specific AP.
98 * @qid: The AP queue number
99 * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
100 * @ind: The notification indicator byte
102 * Returns AP queue status.
104 static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
105 struct ap_qirq_ctrl qirqctrl,
108 register unsigned long reg0 asm ("0") = qid | (3UL << 24);
109 register struct ap_qirq_ctrl reg1_in asm ("1") = qirqctrl;
110 register struct ap_queue_status reg1_out asm ("1");
111 register void *reg2 asm ("2") = ind;
114 ".long 0xb2af0000" /* PQAP(AQIC) */
116 : "d" (reg0), "d" (reg1_in), "d" (reg2)
122 * ap_qci(): Get AP configuration data
124 * Returns 0 on success, or -EOPNOTSUPP.
126 static inline int ap_qci(void *config)
128 register unsigned long reg0 asm ("0") = 4UL << 24;
129 register unsigned long reg1 asm ("1") = -EINVAL;
130 register void *reg2 asm ("2") = (void *) config;
133 ".long 0xb2af0000\n" /* PQAP(QCI) */
138 : "d" (reg0), "d" (reg2)
145 * union ap_qact_ap_info - used together with the
146 * ap_aqic() function to provide a convenient way
147 * to handle the ap info needed by the qact function.
149 union ap_qact_ap_info {
153 unsigned int mode : 3;
155 unsigned int cat : 8;
157 unsigned char ver[2];
162 * ap_qact(): Query AP combatibility type.
163 * @qid: The AP queue number
164 * @apinfo: On input the info about the AP queue. On output the
165 * alternate AP queue info provided by the qact function
166 * in GR2 is stored in.
168 * Returns AP queue status. Check response_code field for failures.
170 static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
171 union ap_qact_ap_info *apinfo)
173 register unsigned long reg0 asm ("0") = qid | (5UL << 24)
174 | ((ifbit & 0x01) << 22);
175 register unsigned long reg1_in asm ("1") = apinfo->val;
176 register struct ap_queue_status reg1_out asm ("1");
177 register unsigned long reg2 asm ("2");
180 ".long 0xb2af0000" /* PQAP(QACT) */
181 : "+d" (reg1_in), "=d" (reg1_out), "=d" (reg2)
189 * ap_nqap(): Send message to adjunct processor queue.
190 * @qid: The AP queue number
191 * @psmid: The program supplied message identifier
192 * @msg: The message text
193 * @length: The message length
195 * Returns AP queue status structure.
196 * Condition code 1 on NQAP can't happen because the L bit is 1.
197 * Condition code 2 on NQAP also means the send is incomplete,
198 * because a segment boundary was reached. The NQAP is repeated.
200 static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
201 unsigned long long psmid,
202 void *msg, size_t length)
204 register unsigned long reg0 asm ("0") = qid | 0x40000000UL;
205 register struct ap_queue_status reg1 asm ("1");
206 register unsigned long reg2 asm ("2") = (unsigned long) msg;
207 register unsigned long reg3 asm ("3") = (unsigned long) length;
208 register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32);
209 register unsigned long reg5 asm ("5") = psmid & 0xffffffff;
212 "0: .long 0xb2ad0042\n" /* NQAP */
214 : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3)
215 : "d" (reg4), "d" (reg5)
221 * ap_dqap(): Receive message from adjunct processor queue.
222 * @qid: The AP queue number
223 * @psmid: Pointer to program supplied message identifier
224 * @msg: The message text
225 * @length: The message length
227 * Returns AP queue status structure.
228 * Condition code 1 on DQAP means the receive has taken place
229 * but only partially. The response is incomplete, hence the
231 * Condition code 2 on DQAP also means the receive is incomplete,
232 * this time because a segment boundary was reached. Again, the
234 * Note that gpr2 is used by the DQAP instruction to keep track of
235 * any 'residual' length, in case the instruction gets interrupted.
236 * Hence it gets zeroed before the instruction.
238 static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
239 unsigned long long *psmid,
240 void *msg, size_t length)
242 register unsigned long reg0 asm("0") = qid | 0x80000000UL;
243 register struct ap_queue_status reg1 asm ("1");
244 register unsigned long reg2 asm("2") = 0UL;
245 register unsigned long reg4 asm("4") = (unsigned long) msg;
246 register unsigned long reg5 asm("5") = (unsigned long) length;
247 register unsigned long reg6 asm("6") = 0UL;
248 register unsigned long reg7 asm("7") = 0UL;
252 "0: .long 0xb2ae0064\n" /* DQAP */
254 : "+d" (reg0), "=d" (reg1), "+d" (reg2),
255 "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7)
257 *psmid = (((unsigned long long) reg6) << 32) + reg7;
261 #endif /* _AP_ASM_H_ */