forked from rbowler/spinhawk
-
Notifications
You must be signed in to change notification settings - Fork 3
/
cpuint.h
740 lines (636 loc) · 25.4 KB
/
cpuint.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
/* CPUINT.H (c) Copyright Jan Jaeger, 2001-2009 */
/* Hercules Interrupt State and Mask Definitions */
/**********************************************************************
Interrupts_State & Interrupts_Mask bits definition (Initial_Mask=800E)
Machine check, PER and external interrupt subclass bit positions
are fixed by the architecture and cannot be changed
Floating interrupts are made pending to all CPUs, and are
recorded in the sysblk structure, CPU specific interrupts
are recorded in the regs structure.
hi0m mmmm pppp p00p xxxx xxxx xxxx h0hs : type U32
|| | |||| |||| |--| |||| |||| |||| |-|| h:mask is always '1'
|| | |||| |||| | | |||| |||| |||| | || s:state is always '1'
|| | |||| |||| | | |||| |||| |||| | |+--> '1' : PSW_WAIT
|| | |||| |||| | | |||| |||| |||| | +---> '1' : RESTART
|| | |||| |||| | | |||| |||| |||| | (available)
|| | |||| |||| | | |||| |||| |||| +-----> '1' : STORSTAT
|| | |||| |||| | | |||| |||| ||||
|| | |||| |||| | | |||| |||| |||+-------> '1' : ETR
|| | |||| |||| | | |||| |||| ||+--------> '1' : EXTSIG
|| | |||| |||| | | |||| |||| |+---------> '1' : INTKEY
|| | |||| |||| | | |||| |||| +----------> '1' : ITIMER
|| | |||| |||| | | |||| ||||
|| | |||| |||| | | |||| |||+------------> '1' : ECPS VTIMER
|| | |||| |||| | | |||| ||+-------------> '1' : SERVSIG
|| | |||| |||| | | |||| |+--------------> '1' : PTIMER
|| | |||| |||| | | |||| +---------------> '1' : CLKC
|| | |||| |||| | | ||||
|| | |||| |||| | | |||+-----------------> '1' : TODSYNC
|| | |||| |||| | | ||+------------------> '1' : EXTCALL
|| | |||| |||| | | |+-------------------> '1' : EMERSIG
|| | |||| |||| | | +--------------------> '1' : MALFALT
|| | |||| |||| | |
|| | |||| |||| | +----------------------> '1' : PER IFNUL
|| | |||| |||| |
|| | |||| |||| |
|| | |||| |||| +-------------------------> '1' : PER STURA
|| | |||| ||||
|| | |||| |||+---------------------------> '1' : PER GRA
|| | |||| ||+----------------------------> '1' : PER SA
|| | |||| |+-----------------------------> '1' : PER IF
|| | |||| +------------------------------> '1' : PER SB
|| | ||||
|| | |||+--------------------------------> '1' : WARNING
|| | ||+---------------------------------> '1' : XDMGRPT
|| | |+----------------------------------> '1' : DGRDRPT
|| | +-----------------------------------> '1' : RCVYRPT
|| |
|| +-------------------------------------> '1' : CHANRPT
||
|+---------------------------------------> '1' : IO
+----------------------------------------> '1' : INTERRUPT possible
**********************************************************************/
// Hercules internal bit# macro: bit numbers are referenced counting
// from the RIGHT to left (i.e. 31 <-- 0) and thus the numerical value
// of a set bit is equal to two raised to the power of the bit position.
// While this is the COMPLETE OPPOSITE from the way bit numbers are
// numbered in IBM architectural reference manuals, we do it this way
// anyway since that's the way Intel numbers their bits, thus allowing
// us to easily replace bit referencing statements with corresponding
// Intel assembler bit manipulation instructions (since Intel is still
// the predominant host architecture platform for Hercules)
/* The BIT() macro should only be used for bit numbers
strictly less than 32 */
#ifndef BIT
#define BIT(nr) ( 1 << (nr) ) // (bit# counting from the right)
#endif
/* The CPU_BIT macro is solely for manipulating
the CPU number as a CPU bit in a CPU_BITMAP */
#ifndef CPU_BIT
#define CPU_BIT(nr) ( (( CPU_BITMAP ) ( 1 ) ) << ( nr ) )
#endif
/* Interrupt bit numbers */
#define IC_INTERRUPT 31 /* 0x80000000 */
#define IC_IO 30 /* 0x40000000 */
#define IC_UNUSED_29 29 /* 0x20000000 */
#define IC_CHANRPT 28 /* 0x10000000 - Architecture dependent (CR14) */
#define IC_RCVYRPT 27 /* 0x08000000 - Architecture dependent (CR14) */
#define IC_DGRDRPT 26 /* 0x04000000 - Architecture dependent (CR14) */
#define IC_XDMGRPT 25 /* 0x02000000 - Architecture dependent (CR14) */
#define IC_WARNING 24 /* 0x01000000 - Architecture dependent (CR14) */
#define IC_PER_SB 23 /* 0x00800000 - Architecture dependent (CR9 >> 8) */
#define IC_PER_IF 22 /* 0x00400000 - Architecture dependent (CR9 >> 8) */
#define IC_PER_SA 21 /* 0x00200000 - Architecture dependent (CR9 >> 8) */
#define IC_PER_GRA 20 /* 0x00100000 - Architecture dependent (CR9 >> 8) */
#define IC_PER_STURA 19 /* 0x00080000 - Architecture dependent (CR9 >> 8) */
#define IC_UNUSED_18 18 /* 0x00040000 */
#define IC_UNUSED_17 17 /* 0x00020000 */
#define IC_PER_IFNUL 16 /* 0x00010000 - Architecture dependent (CR9 >> 8) */
#define IC_MALFALT 15 /* 0x00008000 - Architecture dependent (CR0) */
#define IC_EMERSIG 14 /* 0x00004000 - Architecture dependent (CR0) */
#define IC_EXTCALL 13 /* 0x00002000 - Architecture dependent (CR0) */
#define IC_TODSYNC 12 /* 0x00001000 - Architecture dependent (CR0) */
#define IC_CLKC 11 /* 0x00000800 - Architecture dependent (CR0) */
#define IC_PTIMER 10 /* 0x00000400 - Architecture dependent (CR0) */
#define IC_SERVSIG 9 /* 0x00000200 - Architecture dependent (CR0) */
#define IC_ECPSVTIMER 8 /* 0x00000100 - Not Architecture dependent */
#define IC_ITIMER 7 /* 0x00000080 - Architecture dependent (CR0) */
#define IC_INTKEY 6 /* 0x00000040 - Architecture dependent (CR0) */
#define IC_EXTSIG 5 /* 0x00000020 - Architecture dependent (CR0) */
#define IC_ETR 4 /* 0x00000010 - Architecture dependent (CR0) */
#define IC_STORSTAT 3 /* 0x00000008 */
#define IC_UNUSED_2 2 /* 0x00000004 */
#define IC_RESTART 1 /* 0x00000002 */
#define IC_PSW_WAIT 0 /* 0x00000001 */
/* Initial values */
#define IC_INITIAL_STATE BIT(IC_PSW_WAIT)
#define IC_INITIAL_MASK ( BIT(IC_INTERRUPT) \
| BIT(IC_RESTART) \
| BIT(IC_STORSTAT) \
)
#define SET_IC_INITIAL_MASK(_regs) (_regs)->ints_mask = IC_INITIAL_MASK
#define SET_IC_INITIAL_STATE(_regs) (_regs)->ints_state = IC_INITIAL_STATE
/* I/O interrupt subclasses */
#define IC_IOPENDING ( BIT(IC_IO) )
/* External interrupt subclasses in CR 0 */
#define IC_EXT_SCM_CR0 ( BIT(IC_MALFALT) \
| BIT(IC_EMERSIG) \
| BIT(IC_EXTCALL) \
| BIT(IC_TODSYNC) \
| BIT(IC_CLKC) \
| BIT(IC_PTIMER) \
| BIT(IC_SERVSIG) \
| BIT(IC_ITIMER) \
| BIT(IC_INTKEY) \
| BIT(IC_EXTSIG) \
| BIT(IC_ETR) \
)
/* External interrupt subclasses */
/*
* Adds ECPS:VM Vtimer which has no individual
* subclass mask in CR0
*/
#define IC_EXTPENDING ( BIT(IC_MALFALT) \
| BIT(IC_EMERSIG) \
| BIT(IC_EXTCALL) \
| BIT(IC_TODSYNC) \
| BIT(IC_CLKC) \
| BIT(IC_PTIMER) \
| BIT(IC_SERVSIG) \
| BIT(IC_ECPSVTIMER) \
| BIT(IC_ITIMER) \
| BIT(IC_INTKEY) \
| BIT(IC_EXTSIG) \
| BIT(IC_ETR) \
)
/* Machine check subclasses */
#define IC_MCKPENDING ( BIT(IC_CHANRPT) \
| BIT(IC_RCVYRPT) \
| BIT(IC_DGRDRPT) \
| BIT(IC_XDMGRPT) \
| BIT(IC_WARNING) \
)
/* Not disabled mask */
#define IC_OPEN_MASK ( IC_MCKPENDING \
| IC_EXTPENDING \
| IC_IOPENDING \
)
#define IC_PER_MASK ( BIT(IC_PER_SB) \
| BIT(IC_PER_IF) \
| BIT(IC_PER_SA) \
| BIT(IC_PER_GRA) \
| BIT(IC_PER_STURA) \
| BIT(IC_PER_IFNUL) \
)
/* SIE & Assist supported events */
#define IC_SIE_INT ( BIT(IC_IO) \
| BIT(IC_CLKC) \
| BIT(IC_PTIMER) \
| BIT(IC_ITIMER) \
)
#define IC_CR9_SHIFT 8
/* Mask bits are ONLY set by the associated cpu thread and
* therefore don't have to be serialized. The mask bits
* indicate which interrupts the CPU is willing to take at
* this time. We set the mask bits below in one fell swoop
* to avoid multiple updates to `ints_mask'.
*/
#undef IC_CR0_TO_INTMASK
#if defined(FEATURE_ECPSVM)
#define IC_CR0_TO_INTMASK(_regs) \
( ( (_regs)->CR(0) & IC_EXT_SCM_CR0) \
| (((_regs)->CR(0) & BIT(IC_ITIMER)) ? BIT(IC_ECPSVTIMER) : 0) )
#else
#define IC_CR0_TO_INTMASK(_regs) \
( (_regs)->CR(0) & IC_EXT_SCM_CR0)
#endif /* FEATURE_ECPSVM */
#define IC_MASK(_regs) \
( ( IC_INITIAL_MASK ) \
| ( ECMODE(&(_regs)->psw) \
? ( ((_regs)->psw.sysmask & PSW_IOMASK) ? BIT(IC_IO) : 0 ) \
: ( ((_regs)->psw.sysmask & 0xFE) ? BIT(IC_IO) : 0 ) \
) \
| ( MACHMASK(&(_regs)->psw) ? ((_regs)->CR(14) & IC_MCKPENDING) : 0 ) \
| ( PER_MODE((_regs)) ? ((_regs)->ints_mask & IC_PER_MASK) : 0 ) \
| ( ((_regs)->psw.sysmask & PSW_EXTMASK) ? (IC_CR0_TO_INTMASK((_regs))) : 0 ) \
| ( WAITSTATE(&(_regs)->psw) ? BIT(IC_PSW_WAIT) : 0 ) \
)
#define IC_ECMODE_MASK(_regs) \
( ( IC_INITIAL_MASK ) \
| ( ((_regs)->psw.sysmask & PSW_IOMASK) ? BIT(IC_IO) : 0 ) \
| ( MACHMASK(&(_regs)->psw) ? ((_regs)->CR(14) & IC_MCKPENDING) : 0 ) \
| ( PER_MODE((_regs)) ? ((_regs)->ints_mask & IC_PER_MASK) : 0 ) \
| ( ((_regs)->psw.sysmask & PSW_EXTMASK) ? (IC_CR0_TO_INTMASK((_regs))) : 0 ) \
| ( WAITSTATE(&(_regs)->psw) ? BIT(IC_PSW_WAIT) : 0 ) \
)
#define IC_BCMODE_MASK(_regs) \
( ( IC_INITIAL_MASK ) \
| ( ((_regs)->psw.sysmask & 0xFE) ? BIT(IC_IO) : 0 ) \
| ( MACHMASK(&(_regs)->psw) ? ((_regs)->CR(14) & IC_MCKPENDING) : 0 ) \
| ( PER_MODE((_regs)) ? ((_regs)->ints_mask & IC_PER_MASK) : 0 ) \
| ( ((_regs)->psw.sysmask & PSW_EXTMASK) ? (IC_CR0_TO_INTMASK((_regs))) : 0 ) \
| ( WAITSTATE(&(_regs)->psw) ? BIT(IC_PSW_WAIT) : 0 ) \
)
/* Note: if PER mode, invalidate the AIA to force instfetch to be called */
#define SET_IC_ECMODE_MASK(_regs) \
do { \
(_regs)->ints_mask = IC_ECMODE_MASK((_regs)); \
if ( ( (_regs)->permode = PER_MODE((_regs)) ) ) \
INVALIDATE_AIA((_regs)); \
} while (0)
#define SET_IC_BCMODE_MASK(_regs) \
do { \
(_regs)->ints_mask = IC_BCMODE_MASK((_regs)); \
if ( ( (_regs)->permode = PER_MODE((_regs)) ) ) \
INVALIDATE_AIA((_regs)); \
} while (0)
#undef SET_IC_MASK
#ifdef FEATURE_BCMODE
#define SET_IC_MASK(_regs) \
do { \
(_regs)->ints_mask = IC_MASK((_regs)); \
if ( ( (_regs)->permode = PER_MODE((_regs)) ) ) \
INVALIDATE_AIA((_regs)); \
} while (0)
#else
#define SET_IC_MASK(_regs) SET_IC_ECMODE_MASK(_regs)
#endif
/*
* State bits indicate what interrupts are possibly pending
* for a CPU. These bits can be set by any thread and therefore
* are serialized by the `intlock'.
* For PER, the state bits are set when CR9 is loaded and the mask
* bits are set when a PER event occurs
*/
#define SET_IC_TRACE \
do { \
int i; \
CPU_BITMAP mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) \
sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT); \
mask >>= 1; \
} \
} while (0)
#define SET_IC_PER(_regs) \
do { \
(_regs)->ints_state &= (~IC_PER_MASK); \
(_regs)->ints_state |= (((_regs)->CR(9) >> IC_CR9_SHIFT) & IC_PER_MASK); \
(_regs)->ints_mask &= (~IC_PER_MASK | (_regs)->ints_state); \
} while (0)
/* * * * * * * * * * * * * *
* Set state bit to '1' *
* * * * * * * * * * * * * */
#define ON_IC_INTERRUPT(_regs) \
do { \
(_regs)->ints_state |= BIT(IC_INTERRUPT); \
} while (0)
#define ON_IC_RESTART(_regs) \
do { \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_RESTART); \
} while (0)
#define ON_IC_STORSTAT(_regs) \
do { \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_STORSTAT); \
} while (0)
#define ON_IC_IOPENDING \
do { \
int i; CPU_BITMAP mask; \
if ( !(sysblk.ints_state & BIT(IC_IO)) ) { \
sysblk.ints_state |= BIT(IC_IO); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) { \
if ( sysblk.regs[i]->ints_mask & BIT(IC_IO) ) \
sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_IO); \
else \
sysblk.regs[i]->ints_state |= BIT(IC_IO); \
} \
mask >>= 1; \
} \
} \
} while (0)
#define ON_IC_CHANRPT \
do { \
int i; CPU_BITMAP mask; \
if ( !(sysblk.ints_state & BIT(IC_CHANRPT)) ) { \
sysblk.ints_state |= BIT(IC_CHANRPT); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) { \
if ( sysblk.regs[i]->ints_mask & BIT(IC_CHANRPT) ) \
sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_CHANRPT); \
else \
sysblk.regs[i]->ints_state |= BIT(IC_CHANRPT); \
} \
mask >>= 1; \
} \
} \
} while (0)
#define ON_IC_INTKEY \
do { \
int i; CPU_BITMAP mask; \
if ( !(sysblk.ints_state & BIT(IC_INTKEY)) ) { \
sysblk.ints_state |= BIT(IC_INTKEY); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) { \
if ( sysblk.regs[i]->ints_mask & BIT(IC_INTKEY) ) \
sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_INTKEY); \
else \
sysblk.regs[i]->ints_state |= BIT(IC_INTKEY); \
} \
mask >>= 1; \
} \
} \
} while (0)
#define ON_IC_SERVSIG \
do { \
int i; CPU_BITMAP mask; \
if ( !(sysblk.ints_state & BIT(IC_SERVSIG)) ) { \
sysblk.ints_state |= BIT(IC_SERVSIG); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) { \
if ( sysblk.regs[i]->ints_mask & BIT(IC_SERVSIG) ) \
sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_SERVSIG); \
else \
sysblk.regs[i]->ints_state |= BIT(IC_SERVSIG); \
} \
mask >>= 1; \
} \
} \
} while (0)
#define ON_IC_ITIMER(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_ITIMER) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_ITIMER); \
else \
(_regs)->ints_state |= BIT(IC_ITIMER); \
} while (0)
#define ON_IC_PTIMER(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_PTIMER) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_PTIMER); \
else \
(_regs)->ints_state |= BIT(IC_PTIMER); \
} while (0)
#define ON_IC_ECPSVTIMER(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_ECPSVTIMER) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_ECPSVTIMER); \
else \
(_regs)->ints_state |= BIT(IC_ECPSVTIMER); \
} while (0)
#define ON_IC_CLKC(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_CLKC) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_CLKC); \
else \
(_regs)->ints_state |= BIT(IC_CLKC); \
} while (0)
#define ON_IC_EXTCALL(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_EXTCALL) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_EXTCALL); \
else \
(_regs)->ints_state |= BIT(IC_EXTCALL); \
} while (0)
#define ON_IC_MALFALT(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_MALFALT) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_MALFALT); \
else \
(_regs)->ints_state |= BIT(IC_MALFALT); \
} while (0)
#define ON_IC_EMERSIG(_regs) \
do { \
if ( (_regs)->ints_mask & BIT(IC_EMERSIG) ) \
(_regs)->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_EMERSIG); \
else \
(_regs)->ints_state |= BIT(IC_EMERSIG); \
} while (0)
/*
* When a PER event occurs we set the bit in ints_mask instead of
* ints_state; therefore intlock does not need to be held.
* The ints_state bits are set when CR9 is loaded.
*/
#define ON_IC_PER_SB(_regs) \
do { \
(_regs)->ints_mask |= BIT(IC_PER_SB); \
} while (0)
#define ON_IC_PER_IF(_regs) \
do { \
(_regs)->ints_mask |= BIT(IC_PER_IF); \
} while (0)
#define ON_IC_PER_SA(_regs) \
do { \
(_regs)->ints_mask |= BIT(IC_PER_SA); \
} while (0)
#define ON_IC_PER_GRA(_regs) \
do { \
(_regs)->ints_mask |= BIT(IC_PER_GRA); \
} while (0)
#define ON_IC_PER_STURA(_regs) \
do { \
(_regs)->ints_mask |= BIT(IC_PER_STURA); \
} while (0)
#define ON_IC_PER_IFNUL(_regs) \
do { \
(_regs)->ints_mask |= BIT(IC_PER_IFNUL); \
} while (0)
/* * * * * * * * * * * * * *
* Set state bit to '0' *
* * * * * * * * * * * * * */
#define OFF_IC_INTERRUPT(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_INTERRUPT); \
} while (0)
#define OFF_IC_RESTART(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_RESTART); \
} while (0)
#define OFF_IC_STORSTAT(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_STORSTAT); \
} while (0)
#define OFF_IC_IOPENDING \
do { \
int i; CPU_BITMAP mask; \
if ( sysblk.ints_state & BIT(IC_IO) ) { \
sysblk.ints_state &= ~BIT(IC_IO); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) \
sysblk.regs[i]->ints_state &= ~BIT(IC_IO); \
mask >>= 1; \
} \
} \
} while (0)
#define OFF_IC_CHANRPT \
do { \
int i; CPU_BITMAP mask; \
if ( sysblk.ints_state & BIT(IC_CHANRPT) ) { \
sysblk.ints_state &= ~BIT(IC_CHANRPT); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) \
sysblk.regs[i]->ints_state &= ~BIT(IC_CHANRPT); \
mask >>= 1; \
} \
} \
} while (0)
#define OFF_IC_INTKEY \
do { \
int i; CPU_BITMAP mask; \
if ( sysblk.ints_state & BIT(IC_INTKEY) ) { \
sysblk.ints_state &= ~BIT(IC_INTKEY); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) \
sysblk.regs[i]->ints_state &= ~BIT(IC_INTKEY); \
mask >>= 1; \
} \
} \
} while (0)
#define OFF_IC_SERVSIG \
do { \
int i; CPU_BITMAP mask; \
if ( sysblk.ints_state & BIT(IC_SERVSIG) ) { \
sysblk.ints_state &= ~BIT(IC_SERVSIG); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) \
sysblk.regs[i]->ints_state &= ~BIT(IC_SERVSIG); \
mask >>= 1; \
} \
} \
} while (0)
#define OFF_IC_ITIMER(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_ITIMER); \
} while (0)
#define OFF_IC_PTIMER(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_PTIMER); \
} while (0)
#define OFF_IC_ECPSVTIMER(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_ECPSVTIMER); \
} while (0)
#define OFF_IC_CLKC(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_CLKC); \
} while (0)
#define OFF_IC_EXTCALL(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_EXTCALL); \
} while (0)
#define OFF_IC_MALFALT(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_MALFALT); \
} while (0)
#define OFF_IC_EMERSIG(_regs) \
do { \
(_regs)->ints_state &= ~BIT(IC_EMERSIG); \
} while (0)
#define OFF_IC_PER(_regs) \
do { \
(_regs)->ints_mask &= ~IC_PER_MASK; \
} while (0)
#define OFF_IC_PER_SB(_regs) \
do { \
(_regs)->ints_mask &= ~BIT(IC_PER_SB); \
} while (0)
#define OFF_IC_PER_IF(_regs) \
do { \
(_regs)->ints_mask &= ~BIT(IC_PER_IF); \
} while (0)
#define OFF_IC_PER_SA(_regs) \
do { \
(_regs)->ints_mask &= ~BIT(IC_PER_SA); \
} while (0)
#define OFF_IC_PER_GRA(_regs) \
do { \
(_regs)->ints_mask &= ~BIT(IC_PER_GRA); \
} while (0)
#define OFF_IC_PER_STURA(_regs) \
do { \
(_regs)->ints_mask &= ~BIT(IC_PER_STURA); \
} while (0)
#define OFF_IC_PER_IFNUL(_regs) \
do { \
(_regs)->ints_mask &= ~BIT(IC_PER_IFNUL); \
} while (0)
/* * * * * * * * * * * * * *
* Test interrupt state *
* * * * * * * * * * * * * */
#define IS_IC_INTERRUPT(_regs) ( (_regs)->ints_state & BIT(IC_INTERRUPT) )
#define IS_IC_RESTART(_regs) ( (_regs)->ints_state & BIT(IC_RESTART) )
#define IS_IC_STORSTAT(_regs) ( (_regs)->ints_state & BIT(IC_STORSTAT) )
#define IS_IC_IOPENDING ( sysblk.ints_state & BIT(IC_IO) )
#define IS_IC_MCKPENDING(_regs) ( (_regs)->ints_state & IC_MCKPENDING )
#define IS_IC_CHANRPT ( sysblk.ints_state & BIT(IC_CHANRPT) )
#define IS_IC_INTKEY ( sysblk.ints_state & BIT(IC_INTKEY) )
#define IS_IC_SERVSIG ( sysblk.ints_state & BIT(IC_SERVSIG) )
#define IS_IC_ITIMER(_regs) ( (_regs)->ints_state & BIT(IC_ITIMER) )
#define IS_IC_PTIMER(_regs) ( (_regs)->ints_state & BIT(IC_PTIMER) )
#define IS_IC_ECPSVTIMER(_regs) ( (_regs)->ints_state & BIT(IC_ECPSVTIMER))
#define IS_IC_CLKC(_regs) ( (_regs)->ints_state & BIT(IC_CLKC) )
#define IS_IC_EXTCALL(_regs) ( (_regs)->ints_state & BIT(IC_EXTCALL) )
#define IS_IC_MALFALT(_regs) ( (_regs)->ints_state & BIT(IC_MALFALT) )
#define IS_IC_EMERSIG(_regs) ( (_regs)->ints_state & BIT(IC_EMERSIG) )
#define IS_IC_PER(_regs) ( (_regs)->ints_mask & IC_PER_MASK )
#define IS_IC_PER_SB(_regs) ( (_regs)->ints_mask & BIT(IC_PER_SB) )
#define IS_IC_PER_IF(_regs) ( (_regs)->ints_mask & BIT(IC_PER_IF) )
#define IS_IC_PER_SA(_regs) ( (_regs)->ints_mask & BIT(IC_PER_SA) )
#define IS_IC_PER_GRA(_regs) ( (_regs)->ints_mask & BIT(IC_PER_GRA) )
#define IS_IC_PER_STURA(_regs) ( (_regs)->ints_mask & BIT(IC_PER_STURA) )
#define IS_IC_PER_IFNUL(_regs) ( (_regs)->ints_mask & BIT(IC_PER_IFNUL) )
/* * * * * * * * * * * * * *
* Disabled wait check *
* * * * * * * * * * * * * */
#define IS_IC_DISABLED_WAIT_PSW(_regs) \
( ((_regs)->ints_mask & IC_OPEN_MASK) == 0 )
/* * * * * * * * * * * * * *
* Test PER mask bits *
* * * * * * * * * * * * * */
#define EN_IC_PER(_regs) unlikely( (_regs)->permode )
#define EN_IC_PER_SB(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_SB)) )
#define EN_IC_PER_IF(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_IF)) )
#define EN_IC_PER_SA(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_SA)) )
#define EN_IC_PER_GRA(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_GRA)) )
#define EN_IC_PER_STURA(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_STURA)) )
#define EN_IC_PER_IFNUL(_regs) ( EN_IC_PER(_regs) && ((_regs)->ints_state & BIT(IC_PER_IFNUL)) )
/* * * * * * * * * * * * * * * * * * * * * * * * *
* Check for specific enabled pending interrupt *
* * * * * * * * * * * * * * * * * * * * * * * * */
#define OPEN_IC_MCKPENDING(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & IC_MCKPENDING )
#define OPEN_IC_IOPENDING(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & IC_IOPENDING )
#define OPEN_IC_CHANRPT(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_CHANRPT) )
#define OPEN_IC_EXTPENDING(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & IC_EXTPENDING )
#define OPEN_IC_ITIMER(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_ITIMER) )
#define OPEN_IC_PTIMER(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PTIMER) )
#define OPEN_IC_ECPSVTIMER(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_ECPSVTIMER) )
#define OPEN_IC_CLKC(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_CLKC) )
#define OPEN_IC_INTKEY(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_INTKEY) )
#define OPEN_IC_SERVSIG(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_SERVSIG) )
#define OPEN_IC_EXTCALL(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_EXTCALL) )
#define OPEN_IC_MALFALT(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_MALFALT) )
#define OPEN_IC_EMERSIG(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_EMERSIG) )
#define OPEN_IC_PER(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & IC_PER_MASK )
#define OPEN_IC_PER_SB(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_SB) )
#define OPEN_IC_PER_IF(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_IF) )
#define OPEN_IC_PER_SA(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_SA) )
#define OPEN_IC_PER_GRA(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_GRA) )
#define OPEN_IC_PER_STURA(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_STURA) )
#define OPEN_IC_PER_IFNUL(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask & BIT(IC_PER_IFNUL) )
/* * * * * * * * * * * * * * * * * * * * * * * * *
* Check for general enabled pending interrupt *
* * * * * * * * * * * * * * * * * * * * * * * * */
#define IC_INTERRUPT_CPU(_regs) \
( (_regs)->ints_state & (_regs)->ints_mask )
#define INTERRUPT_PENDING(_regs) IC_INTERRUPT_CPU((_regs))
#define SIE_IC_INTERRUPT_CPU(_regs) \
(((_regs)->ints_state|((_regs)->hostregs->ints_state&IC_SIE_INT)) & (_regs)->ints_mask)
#define SIE_INTERRUPT_PENDING(_regs) SIE_IC_INTERRUPT_CPU((_regs))