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