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