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