Merge tag 'kbuild-misc-v4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/masahi...
[sfrench/cifs-2.6.git] / arch / arc / include / asm / entry-arcv2.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2
3 #ifndef __ASM_ARC_ENTRY_ARCV2_H
4 #define __ASM_ARC_ENTRY_ARCV2_H
5
6 #include <asm/asm-offsets.h>
7 #include <asm/irqflags-arcv2.h>
8 #include <asm/thread_info.h>    /* For THREAD_SIZE */
9
10 /*------------------------------------------------------------------------*/
11 .macro INTERRUPT_PROLOGUE       called_from
12
13         ; Before jumping to Interrupt Vector, hardware micro-ops did following:
14         ;   1. SP auto-switched to kernel mode stack
15         ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
16         ;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
17         ;
18         ; Now manually save: r12, sp, fp, gp, r25
19
20 #ifdef CONFIG_ARC_HAS_ACCL_REGS
21         PUSH    r59
22         PUSH    r58
23 #endif
24
25         PUSH    r30
26         PUSH    r12
27
28         ; Saving pt_regs->sp correctly requires some extra work due to the way
29         ; Auto stack switch works
30         ;  - U mode: retrieve it from AUX_USER_SP
31         ;  - K mode: add the offset from current SP where H/w starts auto push
32         ;
33         ; Utilize the fact that Z bit is set if Intr taken in U mode
34         mov.nz  r9, sp
35         add.nz  r9, r9, SZ_PT_REGS - PT_sp - 4
36         bnz     1f
37
38         lr      r9, [AUX_USER_SP]
39 1:
40         PUSH    r9      ; SP
41
42         PUSH    fp
43         PUSH    gp
44
45 #ifdef CONFIG_ARC_CURR_IN_REG
46         PUSH    r25                     ; user_r25
47         GET_CURR_TASK_ON_CPU    r25
48 #else
49         sub     sp, sp, 4
50 #endif
51
52 .ifnc \called_from, exception
53         sub     sp, sp, 12      ; BTA/ECR/orig_r0 placeholder per pt_regs
54 .endif
55
56 .endm
57
58 /*------------------------------------------------------------------------*/
59 .macro INTERRUPT_EPILOGUE       called_from
60
61 .ifnc \called_from, exception
62         add     sp, sp, 12      ; skip BTA/ECR/orig_r0 placeholderss
63 .endif
64
65 #ifdef CONFIG_ARC_CURR_IN_REG
66         POP     r25
67 #else
68         add     sp, sp, 4
69 #endif
70
71         POP     gp
72         POP     fp
73
74         ; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
75         ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
76         add.z   sp, sp, 4
77         bz      1f
78
79         POPAX   AUX_USER_SP
80 1:
81         POP     r12
82         POP     r30
83
84 #ifdef CONFIG_ARC_HAS_ACCL_REGS
85         POP     r58
86         POP     r59
87 #endif
88
89 .endm
90
91 /*------------------------------------------------------------------------*/
92 .macro EXCEPTION_PROLOGUE
93
94         ; Before jumping to Exception Vector, hardware micro-ops did following:
95         ;   1. SP auto-switched to kernel mode stack
96         ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
97         ;
98         ; Now manually save the complete reg file
99
100         PUSH    r9              ; freeup a register: slot of erstatus
101
102         PUSHAX  eret
103         sub     sp, sp, 12      ; skip JLI, LDI, EI
104         PUSH    lp_count
105         PUSHAX  lp_start
106         PUSHAX  lp_end
107         PUSH    blink
108
109         PUSH    r11
110         PUSH    r10
111
112         ld.as   r9,  [sp, 10]   ; load stashed r9 (status32 stack slot)
113         lr      r10, [erstatus]
114         st.as   r10, [sp, 10]   ; save status32 at it's right stack slot
115
116         PUSH    r9
117         PUSH    r8
118         PUSH    r7
119         PUSH    r6
120         PUSH    r5
121         PUSH    r4
122         PUSH    r3
123         PUSH    r2
124         PUSH    r1
125         PUSH    r0
126
127         ; -- for interrupts, regs above are auto-saved by h/w in that order --
128         ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
129         ;
130         ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
131         ; Although H/w exception micro-ops do set Z flag for U mode (just like
132         ; for interrupts), it could get clobbered in case we soft land here from
133         ; a TLB Miss exception handler (tlbex.S)
134
135         and     r10, r10, STATUS_U_MASK
136         xor.f   0, r10, STATUS_U_MASK
137
138         INTERRUPT_PROLOGUE  exception
139
140         PUSHAX  erbta
141         PUSHAX  ecr             ; r9 contains ECR, expected by EV_Trap
142
143         PUSH    r0              ; orig_r0
144 .endm
145
146 /*------------------------------------------------------------------------*/
147 .macro EXCEPTION_EPILOGUE
148
149         ; Assumes r0 has PT_status32
150         btst   r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE
151
152         add     sp, sp, 8       ; orig_r0/ECR don't need restoring
153         POPAX   erbta
154
155         INTERRUPT_EPILOGUE  exception
156
157         POP     r0
158         POP     r1
159         POP     r2
160         POP     r3
161         POP     r4
162         POP     r5
163         POP     r6
164         POP     r7
165         POP     r8
166         POP     r9
167         POP     r10
168         POP     r11
169
170         POP     blink
171         POPAX   lp_end
172         POPAX   lp_start
173
174         POP     r9
175         mov     lp_count, r9
176
177         add     sp, sp, 12      ; skip JLI, LDI, EI
178         POPAX   eret
179         POPAX   erstatus
180
181         ld.as   r9, [sp, -12]   ; reload r9 which got clobbered
182 .endm
183
184 .macro FAKE_RET_FROM_EXCPN
185         lr      r9, [status32]
186         bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
187         or      r9, r9, (STATUS_L_MASK|STATUS_IE_MASK)
188         kflag   r9
189 .endm
190
191 /* Get thread_info of "current" tsk */
192 .macro GET_CURR_THR_INFO_FROM_SP  reg
193         bmskn \reg, sp, THREAD_SHIFT - 1
194 .endm
195
196 /* Get CPU-ID of this core */
197 .macro  GET_CPU_ID  reg
198         lr  \reg, [identity]
199         xbfu \reg, \reg, 0xE8   /* 00111    01000 */
200                                 /* M = 8-1  N = 8 */
201 .endm
202
203 #endif