hc
2023-11-22 983d7f83616922a6439b4352d1b3af488ee27f95
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
/* SPDX-License-Identifier: GPL-2.0 */
 
#ifndef __ASM_ARC_ENTRY_ARCV2_H
#define __ASM_ARC_ENTRY_ARCV2_H
 
#include <asm/asm-offsets.h>
#include <asm/irqflags-arcv2.h>
#include <asm/thread_info.h>    /* For THREAD_SIZE */
 
/*------------------------------------------------------------------------*/
.macro INTERRUPT_PROLOGUE    called_from
 
   ; Before jumping to Interrupt Vector, hardware micro-ops did following:
   ;   1. SP auto-switched to kernel mode stack
   ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
   ;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
   ;
   ; Now manually save: r12, sp, fp, gp, r25
 
#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
.ifnc \called_from, exception
   st.as    r9, [sp, -10]    ; save r9 in it's final stack slot
   sub    sp, sp, 12    ; skip JLI, LDI, EI
 
   PUSH    lp_count
   PUSHAX    lp_start
   PUSHAX    lp_end
   PUSH    blink
 
   PUSH    r11
   PUSH    r10
 
   sub    sp, sp, 4    ; skip r9
 
   PUSH    r8
   PUSH    r7
   PUSH    r6
   PUSH    r5
   PUSH    r4
   PUSH    r3
   PUSH    r2
   PUSH    r1
   PUSH    r0
.endif
#endif
 
#ifdef CONFIG_ARC_HAS_ACCL_REGS
   PUSH    r59
   PUSH    r58
#endif
 
   PUSH    r30
   PUSH    r12
 
   ; Saving pt_regs->sp correctly requires some extra work due to the way
   ; Auto stack switch works
   ;  - U mode: retrieve it from AUX_USER_SP
   ;  - K mode: add the offset from current SP where H/w starts auto push
   ;
   ; Utilize the fact that Z bit is set if Intr taken in U mode
   mov.nz    r9, sp
   add.nz    r9, r9, SZ_PT_REGS - PT_sp - 4
   bnz    1f
 
   lr    r9, [AUX_USER_SP]
1:
   PUSH    r9    ; SP
 
   PUSH    fp
   PUSH    gp
 
#ifdef CONFIG_ARC_CURR_IN_REG
   PUSH    r25            ; user_r25
   GET_CURR_TASK_ON_CPU    r25
#else
   sub    sp, sp, 4
#endif
 
.ifnc \called_from, exception
   sub    sp, sp, 12    ; BTA/ECR/orig_r0 placeholder per pt_regs
.endif
 
.endm
 
/*------------------------------------------------------------------------*/
.macro INTERRUPT_EPILOGUE    called_from
 
.ifnc \called_from, exception
   add    sp, sp, 12    ; skip BTA/ECR/orig_r0 placeholderss
.endif
 
#ifdef CONFIG_ARC_CURR_IN_REG
   POP    r25
#else
   add    sp, sp, 4
#endif
 
   POP    gp
   POP    fp
 
   ; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
   ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
   add.z    sp, sp, 4
   bz    1f
 
   POPAX    AUX_USER_SP
1:
   POP    r12
   POP    r30
 
#ifdef CONFIG_ARC_HAS_ACCL_REGS
   POP    r58
   POP    r59
#endif
 
#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
.ifnc \called_from, exception
   POP    r0
   POP    r1
   POP    r2
   POP    r3
   POP    r4
   POP    r5
   POP    r6
   POP    r7
   POP    r8
   POP    r9
   POP    r10
   POP    r11
 
   POP    blink
   POPAX    lp_end
   POPAX    lp_start
 
   POP    r9
   mov    lp_count, r9
 
   add    sp, sp, 12    ; skip JLI, LDI, EI
   ld.as    r9, [sp, -10]    ; reload r9 which got clobbered
.endif
#endif
 
.endm
 
/*------------------------------------------------------------------------*/
.macro EXCEPTION_PROLOGUE
 
   ; Before jumping to Exception Vector, hardware micro-ops did following:
   ;   1. SP auto-switched to kernel mode stack
   ;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
   ;
   ; Now manually save the complete reg file
 
   PUSH    r9        ; freeup a register: slot of erstatus
 
   PUSHAX    eret
   sub    sp, sp, 12    ; skip JLI, LDI, EI
   PUSH    lp_count
   PUSHAX    lp_start
   PUSHAX    lp_end
   PUSH    blink
 
   PUSH    r11
   PUSH    r10
 
   ld.as    r9,  [sp, 10]    ; load stashed r9 (status32 stack slot)
   lr    r10, [erstatus]
   st.as    r10, [sp, 10]    ; save status32 at it's right stack slot
 
   PUSH    r9
   PUSH    r8
   PUSH    r7
   PUSH    r6
   PUSH    r5
   PUSH    r4
   PUSH    r3
   PUSH    r2
   PUSH    r1
   PUSH    r0
 
   ; -- for interrupts, regs above are auto-saved by h/w in that order --
   ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
   ;
   ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
   ; Although H/w exception micro-ops do set Z flag for U mode (just like
   ; for interrupts), it could get clobbered in case we soft land here from
   ; a TLB Miss exception handler (tlbex.S)
 
   and    r10, r10, STATUS_U_MASK
   xor.f    0, r10, STATUS_U_MASK
 
   INTERRUPT_PROLOGUE  exception
 
   PUSHAX    erbta
   PUSHAX    ecr        ; r9 contains ECR, expected by EV_Trap
 
   PUSH    r0        ; orig_r0
.endm
 
/*------------------------------------------------------------------------*/
.macro EXCEPTION_EPILOGUE
 
   ; Assumes r0 has PT_status32
   btst   r0, STATUS_U_BIT    ; Z flag set if K, used in INTERRUPT_EPILOGUE
 
   add    sp, sp, 8    ; orig_r0/ECR don't need restoring
   POPAX    erbta
 
   INTERRUPT_EPILOGUE  exception
 
   POP    r0
   POP    r1
   POP    r2
   POP    r3
   POP    r4
   POP    r5
   POP    r6
   POP    r7
   POP    r8
   POP    r9
   POP    r10
   POP    r11
 
   POP    blink
   POPAX    lp_end
   POPAX    lp_start
 
   POP    r9
   mov    lp_count, r9
 
   add    sp, sp, 12    ; skip JLI, LDI, EI
   POPAX    eret
   POPAX    erstatus
 
   ld.as    r9, [sp, -12]    ; reload r9 which got clobbered
.endm
 
.macro FAKE_RET_FROM_EXCPN
   lr      r9, [status32]
   bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
   or      r9, r9, STATUS_IE_MASK
   kflag   r9
.endm
 
/* Get thread_info of "current" tsk */
.macro GET_CURR_THR_INFO_FROM_SP  reg
   bmskn \reg, sp, THREAD_SHIFT - 1
.endm
 
/* Get CPU-ID of this core */
.macro  GET_CPU_ID  reg
   lr  \reg, [identity]
   xbfu \reg, \reg, 0xE8    /* 00111    01000 */
               /* M = 8-1  N = 8 */
.endm
 
#endif