xref: /kernel/linux/linux-6.6/arch/s390/include/asm/ap.h (revision 62306a36)
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#include <linux/io.h>
16#include <asm/asm-extable.h>
17
18/**
19 * The ap_qid_t identifier of an ap queue.
20 * If the AP facilities test (APFT) facility is available,
21 * card and queue index are 8 bit values, otherwise
22 * card index is 6 bit and queue index a 4 bit value.
23 */
24typedef unsigned int ap_qid_t;
25
26#define AP_MKQID(_card, _queue) (((_card) & 0xff) << 8 | ((_queue) & 0xff))
27#define AP_QID_CARD(_qid) (((_qid) >> 8) & 0xff)
28#define AP_QID_QUEUE(_qid) ((_qid) & 0xff)
29
30/**
31 * struct ap_queue_status - Holds the AP queue status.
32 * @queue_empty: Shows if queue is empty
33 * @replies_waiting: Waiting replies
34 * @queue_full: Is 1 if the queue is full
35 * @irq_enabled: Shows if interrupts are enabled for the AP
36 * @response_code: Holds the 8 bit response code
37 *
38 * The ap queue status word is returned by all three AP functions
39 * (PQAP, NQAP and DQAP).  There's a set of flags in the first
40 * byte, followed by a 1 byte response code.
41 */
42struct ap_queue_status {
43	unsigned int queue_empty	: 1;
44	unsigned int replies_waiting	: 1;
45	unsigned int queue_full		: 1;
46	unsigned int			: 3;
47	unsigned int async		: 1;
48	unsigned int irq_enabled	: 1;
49	unsigned int response_code	: 8;
50	unsigned int			: 16;
51};
52
53/*
54 * AP queue status reg union to access the reg1
55 * register with the lower 32 bits comprising the
56 * ap queue status.
57 */
58union ap_queue_status_reg {
59	unsigned long value;
60	struct {
61		u32 _pad;
62		struct ap_queue_status status;
63	};
64};
65
66/**
67 * ap_intructions_available() - Test if AP instructions are available.
68 *
69 * Returns true if the AP instructions are installed, otherwise false.
70 */
71static inline bool ap_instructions_available(void)
72{
73	unsigned long reg0 = AP_MKQID(0, 0);
74	unsigned long reg1 = 0;
75
76	asm volatile(
77		"	lgr	0,%[reg0]\n"		/* qid into gr0 */
78		"	lghi	1,0\n"			/* 0 into gr1 */
79		"	lghi	2,0\n"			/* 0 into gr2 */
80		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(TAPQ) */
81		"0:	la	%[reg1],1\n"		/* 1 into reg1 */
82		"1:\n"
83		EX_TABLE(0b, 1b)
84		: [reg1] "+&d" (reg1)
85		: [reg0] "d" (reg0)
86		: "cc", "0", "1", "2");
87	return reg1 != 0;
88}
89
90/* TAPQ register GR2 response struct */
91struct ap_tapq_gr2 {
92	union {
93		unsigned long value;
94		struct {
95			unsigned int fac    : 32; /* facility bits */
96			unsigned int apinfo : 32; /* ap type, ... */
97		};
98		struct {
99			unsigned int s	   :  1; /* APSC */
100			unsigned int m	   :  1; /* AP4KM */
101			unsigned int c	   :  1; /* AP4KC */
102			unsigned int mode  :  3;
103			unsigned int n	   :  1; /* APXA */
104			unsigned int	   :  1;
105			unsigned int class :  8;
106			unsigned int bs	   :  2; /* SE bind/assoc */
107			unsigned int	   : 14;
108			unsigned int at	   :  8; /* ap type */
109			unsigned int nd	   :  8; /* nr of domains */
110			unsigned int	   :  4;
111			unsigned int ml	   :  4; /* apxl ml */
112			unsigned int	   :  4;
113			unsigned int qd	   :  4; /* queue depth */
114		};
115	};
116};
117
118/*
119 * Convenience defines to be used with the bs field from struct ap_tapq_gr2
120 */
121#define AP_BS_Q_USABLE		      0
122#define AP_BS_Q_USABLE_NO_SECURE_KEY  1
123#define AP_BS_Q_AVAIL_FOR_BINDING     2
124#define AP_BS_Q_UNUSABLE	      3
125
126/**
127 * ap_tapq(): Test adjunct processor queue.
128 * @qid: The AP queue number
129 * @info: Pointer to queue descriptor
130 *
131 * Returns AP queue status structure.
132 */
133static inline struct ap_queue_status ap_tapq(ap_qid_t qid, struct ap_tapq_gr2 *info)
134{
135	union ap_queue_status_reg reg1;
136	unsigned long reg2;
137
138	asm volatile(
139		"	lgr	0,%[qid]\n"		/* qid into gr0 */
140		"	lghi	2,0\n"			/* 0 into gr2 */
141		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(TAPQ) */
142		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
143		"	lgr	%[reg2],2\n"		/* gr2 into reg2 */
144		: [reg1] "=&d" (reg1.value), [reg2] "=&d" (reg2)
145		: [qid] "d" (qid)
146		: "cc", "0", "1", "2");
147	if (info)
148		info->value = reg2;
149	return reg1.status;
150}
151
152/**
153 * ap_test_queue(): Test adjunct processor queue.
154 * @qid: The AP queue number
155 * @tbit: Test facilities bit
156 * @info: Ptr to tapq gr2 struct
157 *
158 * Returns AP queue status structure.
159 */
160static inline struct ap_queue_status ap_test_queue(ap_qid_t qid, int tbit,
161						   struct ap_tapq_gr2 *info)
162{
163	if (tbit)
164		qid |= 1UL << 23; /* set T bit*/
165	return ap_tapq(qid, info);
166}
167
168/**
169 * ap_pqap_rapq(): Reset adjunct processor queue.
170 * @qid: The AP queue number
171 * @fbit: if != 0 set F bit
172 *
173 * Returns AP queue status structure.
174 */
175static inline struct ap_queue_status ap_rapq(ap_qid_t qid, int fbit)
176{
177	unsigned long reg0 = qid | (1UL << 24);  /* fc 1UL is RAPQ */
178	union ap_queue_status_reg reg1;
179
180	if (fbit)
181		reg0 |= 1UL << 22;
182
183	asm volatile(
184		"	lgr	0,%[reg0]\n"		/* qid arg into gr0 */
185		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(RAPQ) */
186		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
187		: [reg1] "=&d" (reg1.value)
188		: [reg0] "d" (reg0)
189		: "cc", "0", "1");
190	return reg1.status;
191}
192
193/**
194 * ap_pqap_zapq(): Reset and zeroize adjunct processor queue.
195 * @qid: The AP queue number
196 * @fbit: if != 0 set F bit
197 *
198 * Returns AP queue status structure.
199 */
200static inline struct ap_queue_status ap_zapq(ap_qid_t qid, int fbit)
201{
202	unsigned long reg0 = qid | (2UL << 24);  /* fc 2UL is ZAPQ */
203	union ap_queue_status_reg reg1;
204
205	if (fbit)
206		reg0 |= 1UL << 22;
207
208	asm volatile(
209		"	lgr	0,%[reg0]\n"		/* qid arg into gr0 */
210		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(ZAPQ) */
211		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
212		: [reg1] "=&d" (reg1.value)
213		: [reg0] "d" (reg0)
214		: "cc", "0", "1");
215	return reg1.status;
216}
217
218/**
219 * struct ap_config_info - convenience struct for AP crypto
220 * config info as returned by the ap_qci() function.
221 */
222struct ap_config_info {
223	unsigned int apsc	 : 1;	/* S bit */
224	unsigned int apxa	 : 1;	/* N bit */
225	unsigned int qact	 : 1;	/* C bit */
226	unsigned int rc8a	 : 1;	/* R bit */
227	unsigned int		 : 4;
228	unsigned int apsb	 : 1;	/* B bit */
229	unsigned int		 : 23;
230	unsigned char na;		/* max # of APs - 1 */
231	unsigned char nd;		/* max # of Domains - 1 */
232	unsigned char _reserved0[10];
233	unsigned int apm[8];		/* AP ID mask */
234	unsigned int aqm[8];		/* AP (usage) queue mask */
235	unsigned int adm[8];		/* AP (control) domain mask */
236	unsigned char _reserved1[16];
237} __aligned(8);
238
239/**
240 * ap_qci(): Get AP configuration data
241 *
242 * Returns 0 on success, or -EOPNOTSUPP.
243 */
244static inline int ap_qci(struct ap_config_info *config)
245{
246	unsigned long reg0 = 4UL << 24;  /* fc 4UL is QCI */
247	unsigned long reg1 = -EOPNOTSUPP;
248	struct ap_config_info *reg2 = config;
249
250	asm volatile(
251		"	lgr	0,%[reg0]\n"		/* QCI fc into gr0 */
252		"	lgr	2,%[reg2]\n"		/* ptr to config into gr2 */
253		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(QCI) */
254		"0:	la	%[reg1],0\n"		/* good case, QCI fc available */
255		"1:\n"
256		EX_TABLE(0b, 1b)
257		: [reg1] "+&d" (reg1)
258		: [reg0] "d" (reg0), [reg2] "d" (reg2)
259		: "cc", "memory", "0", "2");
260
261	return reg1;
262}
263
264/*
265 * struct ap_qirq_ctrl - convenient struct for easy invocation
266 * of the ap_aqic() function. This struct is passed as GR1
267 * parameter to the PQAP(AQIC) instruction. For details please
268 * see the AR documentation.
269 */
270union ap_qirq_ctrl {
271	unsigned long value;
272	struct {
273		unsigned int	   : 8;
274		unsigned int zone  : 8;	/* zone info */
275		unsigned int ir	   : 1;	/* ir flag: enable (1) or disable (0) irq */
276		unsigned int	   : 4;
277		unsigned int gisc  : 3;	/* guest isc field */
278		unsigned int	   : 6;
279		unsigned int gf	   : 2;	/* gisa format */
280		unsigned int	   : 1;
281		unsigned int gisa  : 27;	/* gisa origin */
282		unsigned int	   : 1;
283		unsigned int isc   : 3;	/* irq sub class */
284	};
285};
286
287/**
288 * ap_aqic(): Control interruption for a specific AP.
289 * @qid: The AP queue number
290 * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
291 * @pa_ind: Physical address of the notification indicator byte
292 *
293 * Returns AP queue status.
294 */
295static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
296					     union ap_qirq_ctrl qirqctrl,
297					     phys_addr_t pa_ind)
298{
299	unsigned long reg0 = qid | (3UL << 24);  /* fc 3UL is AQIC */
300	union ap_queue_status_reg reg1;
301	unsigned long reg2 = pa_ind;
302
303	reg1.value = qirqctrl.value;
304
305	asm volatile(
306		"	lgr	0,%[reg0]\n"		/* qid param into gr0 */
307		"	lgr	1,%[reg1]\n"		/* irq ctrl into gr1 */
308		"	lgr	2,%[reg2]\n"		/* ni addr into gr2 */
309		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(AQIC) */
310		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
311		: [reg1] "+&d" (reg1.value)
312		: [reg0] "d" (reg0), [reg2] "d" (reg2)
313		: "cc", "memory", "0", "1", "2");
314
315	return reg1.status;
316}
317
318/*
319 * union ap_qact_ap_info - used together with the
320 * ap_aqic() function to provide a convenient way
321 * to handle the ap info needed by the qact function.
322 */
323union ap_qact_ap_info {
324	unsigned long val;
325	struct {
326		unsigned int	  : 3;
327		unsigned int mode : 3;
328		unsigned int	  : 26;
329		unsigned int cat  : 8;
330		unsigned int	  : 8;
331		unsigned char ver[2];
332	};
333};
334
335/**
336 * ap_qact(): Query AP compatibility type.
337 * @qid: The AP queue number
338 * @apinfo: On input the info about the AP queue. On output the
339 *	    alternate AP queue info provided by the qact function
340 *	    in GR2 is stored in.
341 *
342 * Returns AP queue status. Check response_code field for failures.
343 */
344static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
345					     union ap_qact_ap_info *apinfo)
346{
347	unsigned long reg0 = qid | (5UL << 24) | ((ifbit & 0x01) << 22);
348	union ap_queue_status_reg reg1;
349	unsigned long reg2;
350
351	reg1.value = apinfo->val;
352
353	asm volatile(
354		"	lgr	0,%[reg0]\n"		/* qid param into gr0 */
355		"	lgr	1,%[reg1]\n"		/* qact in info into gr1 */
356		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(QACT) */
357		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
358		"	lgr	%[reg2],2\n"		/* qact out info into reg2 */
359		: [reg1] "+&d" (reg1.value), [reg2] "=&d" (reg2)
360		: [reg0] "d" (reg0)
361		: "cc", "0", "1", "2");
362	apinfo->val = reg2;
363	return reg1.status;
364}
365
366/*
367 * ap_bapq(): SE bind AP queue.
368 * @qid: The AP queue number
369 *
370 * Returns AP queue status structure.
371 *
372 * Invoking this function in a non-SE environment
373 * may case a specification exception.
374 */
375static inline struct ap_queue_status ap_bapq(ap_qid_t qid)
376{
377	unsigned long reg0 = qid | (7UL << 24);  /* fc 7 is BAPQ */
378	union ap_queue_status_reg reg1;
379
380	asm volatile(
381		"	lgr	0,%[reg0]\n"		/* qid arg into gr0 */
382		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(BAPQ) */
383		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
384		: [reg1] "=&d" (reg1.value)
385		: [reg0] "d" (reg0)
386		: "cc", "0", "1");
387
388	return reg1.status;
389}
390
391/*
392 * ap_aapq(): SE associate AP queue.
393 * @qid: The AP queue number
394 * @sec_idx: The secret index
395 *
396 * Returns AP queue status structure.
397 *
398 * Invoking this function in a non-SE environment
399 * may case a specification exception.
400 */
401static inline struct ap_queue_status ap_aapq(ap_qid_t qid, unsigned int sec_idx)
402{
403	unsigned long reg0 = qid | (8UL << 24);  /* fc 8 is AAPQ */
404	unsigned long reg2 = sec_idx;
405	union ap_queue_status_reg reg1;
406
407	asm volatile(
408		"	lgr	0,%[reg0]\n"		/* qid arg into gr0 */
409		"	lgr	2,%[reg2]\n"		/* secret index into gr2 */
410		"	.insn	rre,0xb2af0000,0,0\n"	/* PQAP(AAPQ) */
411		"	lgr	%[reg1],1\n"		/* gr1 (status) into reg1 */
412		: [reg1] "=&d" (reg1.value)
413		: [reg0] "d" (reg0), [reg2] "d" (reg2)
414		: "cc", "0", "1", "2");
415
416	return reg1.status;
417}
418
419/**
420 * ap_nqap(): Send message to adjunct processor queue.
421 * @qid: The AP queue number
422 * @psmid: The program supplied message identifier
423 * @msg: The message text
424 * @length: The message length
425 *
426 * Returns AP queue status structure.
427 * Condition code 1 on NQAP can't happen because the L bit is 1.
428 * Condition code 2 on NQAP also means the send is incomplete,
429 * because a segment boundary was reached. The NQAP is repeated.
430 */
431static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
432					     unsigned long long psmid,
433					     void *msg, size_t length)
434{
435	unsigned long reg0 = qid | 0x40000000UL;  /* 0x4... is last msg part */
436	union register_pair nqap_r1, nqap_r2;
437	union ap_queue_status_reg reg1;
438
439	nqap_r1.even = (unsigned int)(psmid >> 32);
440	nqap_r1.odd  = psmid & 0xffffffff;
441	nqap_r2.even = (unsigned long)msg;
442	nqap_r2.odd  = (unsigned long)length;
443
444	asm volatile (
445		"	lgr	0,%[reg0]\n"  /* qid param in gr0 */
446		"0:	.insn	rre,0xb2ad0000,%[nqap_r1],%[nqap_r2]\n"
447		"	brc	2,0b\n"       /* handle partial completion */
448		"	lgr	%[reg1],1\n"  /* gr1 (status) into reg1 */
449		: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1.value),
450		  [nqap_r2] "+&d" (nqap_r2.pair)
451		: [nqap_r1] "d" (nqap_r1.pair)
452		: "cc", "memory", "0", "1");
453	return reg1.status;
454}
455
456/**
457 * ap_dqap(): Receive message from adjunct processor queue.
458 * @qid: The AP queue number
459 * @psmid: Pointer to program supplied message identifier
460 * @msg: Pointer to message buffer
461 * @msglen: Message buffer size
462 * @length: Pointer to length of actually written bytes
463 * @reslength: Residual length on return
464 * @resgr0: input: gr0 value (only used if != 0), output: residual gr0 content
465 *
466 * Returns AP queue status structure.
467 * Condition code 1 on DQAP means the receive has taken place
468 * but only partially.	The response is incomplete, hence the
469 * DQAP is repeated.
470 * Condition code 2 on DQAP also means the receive is incomplete,
471 * this time because a segment boundary was reached. Again, the
472 * DQAP is repeated.
473 * Note that gpr2 is used by the DQAP instruction to keep track of
474 * any 'residual' length, in case the instruction gets interrupted.
475 * Hence it gets zeroed before the instruction.
476 * If the message does not fit into the buffer, this function will
477 * return with a truncated message and the reply in the firmware queue
478 * is not removed. This is indicated to the caller with an
479 * ap_queue_status response_code value of all bits on (0xFF) and (if
480 * the reslength ptr is given) the remaining length is stored in
481 * *reslength and (if the resgr0 ptr is given) the updated gr0 value
482 * for further processing of this msg entry is stored in *resgr0. The
483 * caller needs to detect this situation and should invoke ap_dqap
484 * with a valid resgr0 ptr and a value in there != 0 to indicate that
485 * *resgr0 is to be used instead of qid to further process this entry.
486 */
487static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
488					     unsigned long *psmid,
489					     void *msg, size_t msglen,
490					     size_t *length,
491					     size_t *reslength,
492					     unsigned long *resgr0)
493{
494	unsigned long reg0 = resgr0 && *resgr0 ? *resgr0 : qid | 0x80000000UL;
495	union ap_queue_status_reg reg1;
496	unsigned long reg2;
497	union register_pair rp1, rp2;
498
499	rp1.even = 0UL;
500	rp1.odd  = 0UL;
501	rp2.even = (unsigned long)msg;
502	rp2.odd  = (unsigned long)msglen;
503
504	asm volatile(
505		"	lgr	0,%[reg0]\n"   /* qid param into gr0 */
506		"	lghi	2,0\n"	       /* 0 into gr2 (res length) */
507		"0:	ltgr	%N[rp2],%N[rp2]\n" /* check buf len */
508		"	jz	2f\n"	       /* go out if buf len is 0 */
509		"1:	.insn	rre,0xb2ae0000,%[rp1],%[rp2]\n"
510		"	brc	6,0b\n"        /* handle partial complete */
511		"2:	lgr	%[reg0],0\n"   /* gr0 (qid + info) into reg0 */
512		"	lgr	%[reg1],1\n"   /* gr1 (status) into reg1 */
513		"	lgr	%[reg2],2\n"   /* gr2 (res length) into reg2 */
514		: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1.value),
515		  [reg2] "=&d" (reg2), [rp1] "+&d" (rp1.pair),
516		  [rp2] "+&d" (rp2.pair)
517		:
518		: "cc", "memory", "0", "1", "2");
519
520	if (reslength)
521		*reslength = reg2;
522	if (reg2 != 0 && rp2.odd == 0) {
523		/*
524		 * Partially complete, status in gr1 is not set.
525		 * Signal the caller that this dqap is only partially received
526		 * with a special status response code 0xFF and *resgr0 updated
527		 */
528		reg1.status.response_code = 0xFF;
529		if (resgr0)
530			*resgr0 = reg0;
531	} else {
532		*psmid = (rp1.even << 32) + rp1.odd;
533		if (resgr0)
534			*resgr0 = 0;
535	}
536
537	/* update *length with the nr of bytes stored into the msg buffer */
538	if (length)
539		*length = msglen - rp2.odd;
540
541	return reg1.status;
542}
543
544/*
545 * Interface to tell the AP bus code that a configuration
546 * change has happened. The bus code should at least do
547 * an ap bus resource rescan.
548 */
549#if IS_ENABLED(CONFIG_ZCRYPT)
550void ap_bus_cfg_chg(void);
551#else
552static inline void ap_bus_cfg_chg(void){}
553#endif
554
555#endif /* _ASM_S390_AP_H_ */
556