xref: /openbmc/linux/arch/s390/include/asm/ap.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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   */
24  typedef 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   */
42  struct 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   */
58  union 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   */
ap_instructions_available(void)71  static 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 */
91  struct 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   */
ap_tapq(ap_qid_t qid,struct ap_tapq_gr2 * info)133  static 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   */
ap_test_queue(ap_qid_t qid,int tbit,struct ap_tapq_gr2 * info)160  static 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   */
ap_rapq(ap_qid_t qid,int fbit)175  static 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   */
ap_zapq(ap_qid_t qid,int fbit)200  static 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   */
222  struct 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   */
ap_qci(struct ap_config_info * config)244  static 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   */
270  union 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   */
ap_aqic(ap_qid_t qid,union ap_qirq_ctrl qirqctrl,phys_addr_t pa_ind)295  static 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   */
323  union 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   */
ap_qact(ap_qid_t qid,int ifbit,union ap_qact_ap_info * apinfo)344  static 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   */
ap_bapq(ap_qid_t qid)375  static 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   */
ap_aapq(ap_qid_t qid,unsigned int sec_idx)401  static 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   */
ap_nqap(ap_qid_t qid,unsigned long long psmid,void * msg,size_t length)431  static 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   */
ap_dqap(ap_qid_t qid,unsigned long * psmid,void * msg,size_t msglen,size_t * length,size_t * reslength,unsigned long * resgr0)487  static 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)
550  void ap_bus_cfg_chg(void);
551  #else
ap_bus_cfg_chg(void)552  static inline void ap_bus_cfg_chg(void){}
553  #endif
554  
555  #endif /* _ASM_S390_AP_H_ */
556