File indexing completed on 2025-05-11 08:24:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <rtems/asm.h>
0035 #include <rtems/score/percpu.h>
0036
0037
0038
0039
0040
0041
0042 .register %g2, #scratch
0043 .register %g3, #scratch
0044 .register %g6, #scratch
0045 .register %g7, #scratch
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 .align 4
0065 PUBLIC(_ISR_Handler)
0066 SYM(_ISR_Handler):
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 rdpr %tl, %g1
0105 cmp %g1, 1
0106 be 1f
0107 nop
0108
0109 0: ba 0b
0110 nop
0111
0112 1:
0113
0114 mov %sp, %g1
0115
0116 sub %sp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
0117 ! make space for Stack_Frame||ISF
0118
0119
0120 stx %g4, [%sp + STACK_BIAS + ISF_TSTATE_OFFSET]
0121 rdpr %pil, %g3
0122 rdpr %tpc, %g4
0123 rdpr %tnpc, %g5
0124 stx %g3, [%sp + STACK_BIAS + ISF_PIL_OFFSET]
0125 stx %g4, [%sp + STACK_BIAS + ISF_TPC_OFFSET]
0126 stx %g5, [%sp + STACK_BIAS + ISF_TNPC_OFFSET]
0127 stx %g2, [%sp + STACK_BIAS + ISF_TVEC_OFFSET]
0128
0129 rd %y, %g4 ! save y
0130 stx %g4, [%sp + STACK_BIAS + ISF_Y_OFFSET]
0131
0132 ! save interrupted frame's output regs
0133 stx %o0, [%sp + STACK_BIAS + ISF_O0_OFFSET] ! save o0
0134 stx %o1, [%sp + STACK_BIAS + ISF_O1_OFFSET] ! save o1
0135 stx %o2, [%sp + STACK_BIAS + ISF_O2_OFFSET] ! save o2
0136 stx %o3, [%sp + STACK_BIAS + ISF_O3_OFFSET] ! save o3
0137 stx %o4, [%sp + STACK_BIAS + ISF_O4_OFFSET] ! save o4
0138 stx %o5, [%sp + STACK_BIAS + ISF_O5_OFFSET] ! save o5
0139 stx %g1, [%sp + STACK_BIAS + ISF_O6_SP_OFFSET] ! save o6/sp
0140 stx %o7, [%sp + STACK_BIAS + ISF_O7_OFFSET] ! save o7
0141
0142 mov %g1, %o5 ! hold the old sp here for now
0143 mov %g2, %o1 ! we'll need trap # later
0144
0145
0146 wrpr %g0, 0, %tl
0147
0148
0149 #if defined (SUN4U)
0150
0151 #elif defined (SUN4V)
0152 wrpr %g0, 0, %gl
0153 #endif
0154
0155 wrpr %g0, SPARC_PSTATE_PRIV_MASK | SPARC_PSTATE_PEF_MASK, %pstate
0156
0157 ! save globals
0158 stx %g1, [%sp + STACK_BIAS + ISF_G1_OFFSET] ! save g1
0159 stx %g2, [%sp + STACK_BIAS + ISF_G2_OFFSET] ! save g2
0160 stx %g3, [%sp + STACK_BIAS + ISF_G3_OFFSET] ! save g3
0161 stx %g4, [%sp + STACK_BIAS + ISF_G4_OFFSET] ! save g4
0162 stx %g5, [%sp + STACK_BIAS + ISF_G5_OFFSET] ! save g5
0163 stx %g6, [%sp + STACK_BIAS + ISF_G6_OFFSET] ! save g6
0164 stx %g7, [%sp + STACK_BIAS + ISF_G7_OFFSET] ! save g7
0165
0166
0167 mov %o1, %g2 ! get the trap #
0168 mov %o5, %g7 ! store the interrupted %sp (preserve)
0169 mov %sp, %o1 ! 2nd arg to ISR Handler = address of ISF
0170 add %o1, STACK_BIAS, %o1 ! need to adjust for stack bias, 2nd arg = ISF
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 setx THREAD_DISPATCH_DISABLE_LEVEL, %o5, %g3
0188 lduw [%g3], %g5
0189 setx ISR_NEST_LEVEL, %o5, %g6
0190 lduw [%g6], %g4
0191
0192 add %g5, 1, %g5
0193 stuw %g5, [%g3]
0194
0195 add %g4, 1, %g4
0196 stuw %g4, [%g6]
0197
0198
0199
0200
0201
0202 subcc %g4, 1, %g4 ! outermost interrupt handler?
0203 bnz dont_switch_stacks ! No, then do not switch stacks
0204
0205 setx SYM(INTERRUPT_STACK_HIGH), %o5, %g1
0206 ldx [%g1], %sp
0207
0208
0209
0210
0211 sub %sp, STACK_BIAS, %sp
0212
0213
0214
0215
0216
0217
0218
0219 sub %sp, SPARC64_MINIMUM_STACK_FRAME_SIZE, %sp
0220
0221 dont_switch_stacks:
0222
0223
0224
0225
0226
0227
0228
0229
0230 and %g2, 0x0ff, %g1 ! is bottom byte of vector number [0x41,0x4f]?
0231
0232 subcc %g1, 0x41, %g0
0233 bl dont_fix_pil
0234 subcc %g1, 0x4f, %g0
0235 bg dont_fix_pil
0236 nop
0237 wrpr %g0, %g1, %pil
0238
0239 dont_fix_pil:
0240
0241
0242
0243
0244
0245
0246
0247 mov %g0, %g4
0248
0249 ! **** ENABLE TRAPS ****
0250 wrpr %g0, SPARC_PSTATE_PRIV_MASK | SPARC_PSTATE_PEF_MASK | \
0251 SPARC_PSTATE_IE_MASK, %pstate
0252
0253
0254
0255
0256
0257
0258
0259 setx SYM(_ISR_Vector_table), %o5, %g1
0260 and %g2, 0x1FF, %o5 ! remove synchronous trap indicator
0261 sll %o5, 3, %o5 ! o5 = offset into table
0262 ldx [%g1 + %o5], %g1 ! g1 = _ISR_Vector_table[ vector ]
0263
0264
0265 ! o1 = 2nd arg = address of the ISF
0266 ! WAS LOADED WHEN ISF WAS SAVED!!!
0267 mov %g2, %o0 ! o0 = 1st arg = vector number
0268 call %g1, 0
0269 nop ! delay slot
0270
0271
0272
0273
0274
0275 ! **** DISABLE TRAPS ****
0276 wrpr %g0, SPARC_PSTATE_PRIV_MASK, %pstate
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309 setx THREAD_DISPATCH_DISABLE_LEVEL, %o5, %g3
0310 lduw [%g3],%g5
0311 lduw [%g6],%g4
0312 sub %g5, 1, %g5
0313 stuw %g5, [%g3]
0314 sub %g4, 1, %g4
0315 stuw %g4, [%g6]
0316
0317 orcc %g4, %g0, %g0 ! ISRs still nested?
0318 bnz dont_restore_stack ! Yes then don't restore stack yet
0319 nop
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334 sub %g7, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
0335
0336 dont_restore_stack:
0337
0338
0339
0340
0341
0342
0343 orcc %g5, %g0, %g0 ! Is dispatching disabled?
0344 bnz simple_return ! Yes, then do a "simple" exit
0345 ! NOTE: Use the delay slot
0346 mov %g0, %g4 ! clear g4 for ofw
0347
0348 ! Are we dispatching from a previous ISR in the interrupted thread?
0349 setx SYM(_CPU_ISR_Dispatch_disable), %o5, %g5
0350 lduw [%g5], %o5
0351 orcc %o5, %g0, %g0 ! Is this thread already doing an ISR?
0352 bnz simple_return ! Yes, then do a "simple" exit
0353 nop
0354
0355 setx DISPATCH_NEEDED, %o5, %g7
0356
0357
0358
0359
0360
0361
0362
0363 ldub [%g7], %o5
0364
0365 orcc %o5, %g0, %g0 ! Is thread switch necessary?
0366 bz simple_return ! no, then do a simple return. otherwise fallthru
0367 nop
0368
0369
0370
0371
0372
0373 ! Set ISR dispatch nesting prevention flag
0374 mov 1, %o1
0375 setx SYM(_CPU_ISR_Dispatch_disable), %o5, %o2
0376 stuw %o1, [%o2]
0377
0378
0379 ! **** ENABLE TRAPS ****
0380 wrpr %g0, SPARC_PSTATE_PRIV_MASK | SPARC_PSTATE_PEF_MASK | \
0381 SPARC_PSTATE_IE_MASK, %pstate
0382 isr_dispatch:
0383 call SYM(_Thread_Dispatch), 0
0384 nop
0385
0386
0387
0388
0389
0390
0391
0392 mov 2, %g4 ! syscall (disable interrupts)
0393 ta 0 ! syscall (disable interrupts)
0394 mov 0, %g4
0395
0396
0397
0398
0399
0400
0401
0402 setx DISPATCH_NEEDED, %o5, %o1
0403 ldub [%o1], %o2
0404
0405 orcc %o2, %g0, %g0 ! Is thread switch necessary?
0406 bz allow_nest_again ! No, then clear out and return
0407 nop
0408
0409 ! Yes, then invoke the dispatcher
0410 dispatchAgain:
0411 mov 3, %g4 ! syscall (enable interrupts)
0412 ta 0 ! syscall (enable interrupts)
0413 ba isr_dispatch
0414 mov 0, %g4
0415
0416 allow_nest_again:
0417
0418 ! Zero out ISR stack nesting prevention flag
0419 setx SYM(_CPU_ISR_Dispatch_disable), %o5, %o1
0420 stuw %g0,[%o1]
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431 simple_return:
0432 flushw ! get register windows to a 'clean' state
0433
0434 ! **** DISABLE TRAPS ****
0435 wrpr %g0, SPARC_PSTATE_PRIV_MASK, %pstate
0436
0437 ldx [%sp + STACK_BIAS + ISF_Y_OFFSET], %o1 ! restore y
0438 wr %o1, 0, %y
0439
0440 ldx [%sp + STACK_BIAS + ISF_TSTATE_OFFSET], %g1
0441
0442 ! see if cwp is proper (tstate.cwp == cwp)
0443 and %g1, 0x1F, %g6
0444 rdpr %cwp, %g7
0445 cmp %g6, %g7
0446 bz good_window
0447 nop
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458 mov %sp, %g1
0459 stx %l0, [%sp + STACK_BIAS + CPU_STACK_FRAME_L0_OFFSET]
0460 stx %l1, [%sp + STACK_BIAS + CPU_STACK_FRAME_L1_OFFSET]
0461 stx %l2, [%sp + STACK_BIAS + CPU_STACK_FRAME_L2_OFFSET]
0462 stx %l3, [%sp + STACK_BIAS + CPU_STACK_FRAME_L3_OFFSET]
0463 stx %l4, [%sp + STACK_BIAS + CPU_STACK_FRAME_L4_OFFSET]
0464 stx %l5, [%sp + STACK_BIAS + CPU_STACK_FRAME_L5_OFFSET]
0465 stx %l6, [%sp + STACK_BIAS + CPU_STACK_FRAME_L6_OFFSET]
0466 stx %l7, [%sp + STACK_BIAS + CPU_STACK_FRAME_L7_OFFSET]
0467 stx %i0, [%sp + STACK_BIAS + CPU_STACK_FRAME_I0_OFFSET]
0468 stx %i1, [%sp + STACK_BIAS + CPU_STACK_FRAME_I1_OFFSET]
0469 stx %i2, [%sp + STACK_BIAS + CPU_STACK_FRAME_I2_OFFSET]
0470 stx %i3, [%sp + STACK_BIAS + CPU_STACK_FRAME_I3_OFFSET]
0471 stx %i4, [%sp + STACK_BIAS + CPU_STACK_FRAME_I4_OFFSET]
0472 stx %i5, [%sp + STACK_BIAS + CPU_STACK_FRAME_I5_OFFSET]
0473 stx %i6, [%sp + STACK_BIAS + CPU_STACK_FRAME_I6_FP_OFFSET]
0474 stx %i7, [%sp + STACK_BIAS + CPU_STACK_FRAME_I7_OFFSET]
0475 wrpr %g0, %g6, %cwp
0476 mov %g1, %sp
0477 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L0_OFFSET], %l0
0478 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L1_OFFSET], %l1
0479 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L2_OFFSET], %l2
0480 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L3_OFFSET], %l3
0481 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L4_OFFSET], %l4
0482 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L5_OFFSET], %l5
0483 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L6_OFFSET], %l6
0484 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_L7_OFFSET], %l7
0485 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I0_OFFSET], %i0
0486 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I1_OFFSET], %i1
0487 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I2_OFFSET], %i2
0488 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I3_OFFSET], %i3
0489 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I4_OFFSET], %i4
0490 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I5_OFFSET], %i5
0491 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I6_FP_OFFSET], %i6
0492 ldx [%sp + STACK_BIAS + CPU_STACK_FRAME_I7_OFFSET], %i7
0493
0494
0495 good_window:
0496
0497
0498
0499
0500
0501
0502 ldx [%sp + STACK_BIAS + ISF_G1_OFFSET], %g1 ! restore g1
0503 ldx [%sp + STACK_BIAS + ISF_G2_OFFSET], %g2 ! restore g2
0504 ldx [%sp + STACK_BIAS + ISF_G3_OFFSET], %g3 ! restore g3
0505 ldx [%sp + STACK_BIAS + ISF_G4_OFFSET], %g4 ! restore g4
0506 ldx [%sp + STACK_BIAS + ISF_G5_OFFSET], %g5 ! restore g5
0507 ldx [%sp + STACK_BIAS + ISF_G6_OFFSET], %g6 ! restore g6
0508 ldx [%sp + STACK_BIAS + ISF_G7_OFFSET], %g7 ! restore g7
0509
0510 ! Assume the interrupted context is in TL 0 with GL 0 / normal globals.
0511 ! When tstate is restored at done/retry, the interrupted context is restored.
0512 ! return to TL[1], GL[1], and restore TSTATE, TPC, and TNPC
0513 wrpr %g0, 1, %tl
0514
0515 ! return to GL=1 or AG
0516 #if defined(SUN4U)
0517 rdpr %pstate, %o1
0518 or %o1, SPARC_PSTATE_AG_MASK, %o1
0519 wrpr %o1, %g0, %pstate ! go to AG.
0520 #elif defined(SUN4V)
0521 wrpr %g0, 1, %gl
0522 #endif
0523
0524 ! now we can use global registers (at gl=1 or AG)
0525 ldx [%sp + STACK_BIAS + ISF_PIL_OFFSET], %g3
0526 ldx [%sp + STACK_BIAS + ISF_TPC_OFFSET], %g4
0527 ldx [%sp + STACK_BIAS + ISF_TNPC_OFFSET], %g5
0528 ldx [%sp + STACK_BIAS + ISF_TSTATE_OFFSET], %g1
0529 ldx [%sp + STACK_BIAS + ISF_TVEC_OFFSET], %g2
0530 wrpr %g0, %g3, %pil
0531 wrpr %g0, %g4, %tpc
0532 wrpr %g0, %g5, %tnpc
0533
0534 wrpr %g0, %g1, %tstate
0535
0536 ldx [%sp + STACK_BIAS + ISF_O0_OFFSET], %o0 ! restore o0
0537 ldx [%sp + STACK_BIAS + ISF_O1_OFFSET], %o1 ! restore o1
0538 ldx [%sp + STACK_BIAS + ISF_O2_OFFSET], %o2 ! restore o2
0539 ldx [%sp + STACK_BIAS + ISF_O3_OFFSET], %o3 ! restore o3
0540 ldx [%sp + STACK_BIAS + ISF_O4_OFFSET], %o4 ! restore o4
0541 ldx [%sp + STACK_BIAS + ISF_O5_OFFSET], %o5 ! restore o5
0542 ! sp is restored later
0543 ldx [%sp + STACK_BIAS + ISF_O7_OFFSET], %o7 ! restore o7
0544
0545 ldx [%sp + STACK_BIAS + ISF_O6_SP_OFFSET], %o6 ! restore o6/sp
0546
0547
0548
0549
0550
0551
0552
0553 andcc %g2, SPARC_SYNCHRONOUS_TRAP_BIT_MASK, %g0
0554 ! Is this a synchronous trap?
0555 be not_synch ! No, then skip trapping instruction
0556 mov 0, %g4
0557 retry ! re-execute trapping instruction
0558 not_synch:
0559 done ! skip trapping instruction
0560
0561