Linux-libre 4.19.123-gnu
[librecmc/linux-libre.git] / arch / sparc / kernel / ivec.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2         /* The registers for cross calls will be:
3          *
4          * DATA 0: [low 32-bits]  Address of function to call, jmp to this
5          *         [high 32-bits] MMU Context Argument 0, place in %g5
6          * DATA 1: Address Argument 1, place in %g1
7          * DATA 2: Address Argument 2, place in %g7
8          *
9          * With this method we can do most of the cross-call tlb/cache
10          * flushing very quickly.
11          */
12         .align          32
13         .globl          do_ivec
14         .type           do_ivec,#function
15 do_ivec:
16         mov             0x40, %g3
17         ldxa            [%g3 + %g0] ASI_INTR_R, %g3
18         sethi           %hi(KERNBASE), %g4
19         cmp             %g3, %g4
20         bgeu,pn         %xcc, do_ivec_xcall
21          srlx           %g3, 32, %g5
22         stxa            %g0, [%g0] ASI_INTR_RECEIVE
23         membar          #Sync
24
25         sethi           %hi(ivector_table_pa), %g2
26         ldx             [%g2 + %lo(ivector_table_pa)], %g2
27         sllx            %g3, 4, %g3
28         add             %g2, %g3, %g3
29
30         TRAP_LOAD_IRQ_WORK_PA(%g6, %g1)
31
32         ldx             [%g6], %g5
33         stxa            %g5, [%g3] ASI_PHYS_USE_EC
34         stx             %g3, [%g6]
35         wr              %g0, 1 << PIL_DEVICE_IRQ, %set_softint
36         retry
37 do_ivec_xcall:
38         mov             0x50, %g1
39         ldxa            [%g1 + %g0] ASI_INTR_R, %g1
40         srl             %g3, 0, %g3
41
42         mov             0x60, %g7
43         ldxa            [%g7 + %g0] ASI_INTR_R, %g7
44         stxa            %g0, [%g0] ASI_INTR_RECEIVE
45         membar          #Sync
46         ba,pt           %xcc, 1f
47          nop
48
49         .align          32
50 1:      jmpl            %g3, %g0
51          nop
52         .size           do_ivec,.-do_ivec