xref: /openbmc/linux/arch/arc/include/asm/entry-arcv2.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21f6ccfffSVineet Gupta 
31f6ccfffSVineet Gupta #ifndef __ASM_ARC_ENTRY_ARCV2_H
41f6ccfffSVineet Gupta #define __ASM_ARC_ENTRY_ARCV2_H
51f6ccfffSVineet Gupta 
61f6ccfffSVineet Gupta #include <asm/asm-offsets.h>
74827d0cfSEugeniy Paltsev #include <asm/dsp-impl.h>
81f6ccfffSVineet Gupta #include <asm/irqflags-arcv2.h>
91f6ccfffSVineet Gupta #include <asm/thread_info.h>	/* For THREAD_SIZE */
101f6ccfffSVineet Gupta 
1145869eb0SVineet Gupta /*
1245869eb0SVineet Gupta  * Interrupt/Exception stack layout (pt_regs) for ARCv2
1345869eb0SVineet Gupta  *   (End of struct aligned to end of page [unless nested])
1445869eb0SVineet Gupta  *
1545869eb0SVineet Gupta  *  INTERRUPT                          EXCEPTION
1645869eb0SVineet Gupta  *
1745869eb0SVineet Gupta  *    manual    ---------------------  manual
1845869eb0SVineet Gupta  *              |      orig_r0      |
1945869eb0SVineet Gupta  *              |      event/ECR    |
2045869eb0SVineet Gupta  *              |      bta          |
2145869eb0SVineet Gupta  *              |      gp           |
2245869eb0SVineet Gupta  *              |      fp           |
2345869eb0SVineet Gupta  *              |      sp           |
2445869eb0SVineet Gupta  *              |      r12          |
2545869eb0SVineet Gupta  *              |      r30          |
2645869eb0SVineet Gupta  *              |      r58          |
2745869eb0SVineet Gupta  *              |      r59          |
2845869eb0SVineet Gupta  *  hw autosave ---------------------
2945869eb0SVineet Gupta  *    optional  |      r0           |
3045869eb0SVineet Gupta  *              |      r1           |
3145869eb0SVineet Gupta  *              ~                   ~
3245869eb0SVineet Gupta  *              |      r9           |
3345869eb0SVineet Gupta  *              |      r10          |
3445869eb0SVineet Gupta  *              |      r11          |
3545869eb0SVineet Gupta  *              |      blink        |
3645869eb0SVineet Gupta  *              |      lpe          |
3745869eb0SVineet Gupta  *              |      lps          |
3845869eb0SVineet Gupta  *              |      lpc          |
3945869eb0SVineet Gupta  *              |      ei base      |
4045869eb0SVineet Gupta  *              |      ldi base     |
4145869eb0SVineet Gupta  *              |      jli base     |
4245869eb0SVineet Gupta  *              ---------------------
4345869eb0SVineet Gupta  *  hw autosave |       pc / eret   |
4445869eb0SVineet Gupta  *   mandatory  | stat32 / erstatus |
4545869eb0SVineet Gupta  *              ---------------------
4645869eb0SVineet Gupta  */
4745869eb0SVineet Gupta 
481f6ccfffSVineet Gupta /*------------------------------------------------------------------------*/
49a4880801SVineet Gupta .macro INTERRUPT_PROLOGUE
50a4880801SVineet Gupta 
51c505b0daSVineet Gupta 	; Before jumping to Interrupt Vector, hardware micro-ops did following:
521f6ccfffSVineet Gupta 	;   1. SP auto-switched to kernel mode stack
5345869eb0SVineet Gupta 	;   2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
5445869eb0SVineet Gupta 	;   3. Auto save: (mandatory) Push PC and STAT32 on stack
5545869eb0SVineet Gupta 	;                 hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
56c505b0daSVineet Gupta 	;  4a. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
571f6ccfffSVineet Gupta 	;
58c505b0daSVineet Gupta 	; Now
59c505b0daSVineet Gupta 	;  4b. If Auto-save (optional) not enabled in hw, manually save them
60c505b0daSVineet Gupta 	;   5. Manually save: r12,r30, sp,fp,gp, ACCL pair
61c505b0daSVineet Gupta 	;
62c505b0daSVineet Gupta 	; At the end, SP points to pt_regs
631f6ccfffSVineet Gupta 
64e494239aSVineet Gupta #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
65a4880801SVineet Gupta 	; carve pt_regs on stack (case #3), PC/STAT32 already on stack
66a4880801SVineet Gupta 	sub	sp, sp, SZ_PT_REGS - 8
67e494239aSVineet Gupta 
68a4880801SVineet Gupta 	__SAVE_REGFILE_HARD
691f6ccfffSVineet Gupta #else
70a4880801SVineet Gupta 	; carve pt_regs on stack (case #4), which grew partially already
71a4880801SVineet Gupta 	sub	sp, sp, PT_r0
721f6ccfffSVineet Gupta #endif
731f6ccfffSVineet Gupta 
74a4880801SVineet Gupta 	__SAVE_REGFILE_SOFT
751f6ccfffSVineet Gupta .endm
761f6ccfffSVineet Gupta 
771f6ccfffSVineet Gupta /*------------------------------------------------------------------------*/
7813347c10SVineet Gupta .macro EXCEPTION_PROLOGUE_KEEP_AE
791f6ccfffSVineet Gupta 
80c505b0daSVineet Gupta 	; Before jumping to Exception Vector, hardware micro-ops did following:
811f6ccfffSVineet Gupta 	;   1. SP auto-switched to kernel mode stack
8245869eb0SVineet Gupta 	;   2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
831f6ccfffSVineet Gupta 	;
84c505b0daSVineet Gupta 	; Now manually save rest of reg file
85c505b0daSVineet Gupta 	; At the end, SP points to pt_regs
861f6ccfffSVineet Gupta 
87c505b0daSVineet Gupta 	sub	sp, sp, SZ_PT_REGS	; carve space for pt_regs
881f6ccfffSVineet Gupta 
89a4880801SVineet Gupta 	; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
901f6ccfffSVineet Gupta 
91a4880801SVineet Gupta 	__SAVE_REGFILE_HARD
92a4880801SVineet Gupta 	__SAVE_REGFILE_SOFT
931f6ccfffSVineet Gupta 
94a4880801SVineet Gupta 	st	r0, [sp]	; orig_r0
951f6ccfffSVineet Gupta 
96a4880801SVineet Gupta 	lr	r10, [eret]
97a4880801SVineet Gupta 	lr	r11, [erstatus]
98a4880801SVineet Gupta 	ST2	r10, r11, PT_ret
991f6ccfffSVineet Gupta 
100a4880801SVineet Gupta 	lr	r10, [ecr]
101a4880801SVineet Gupta 	lr	r11, [erbta]
102a4880801SVineet Gupta 	ST2	r10, r11, PT_event
1031f6ccfffSVineet Gupta 
10468e5c6f0SVineet Gupta 	; OUTPUT: r10 has ECR expected by EV_Trap
1051f6ccfffSVineet Gupta .endm
1061f6ccfffSVineet Gupta 
10713347c10SVineet Gupta .macro EXCEPTION_PROLOGUE
10813347c10SVineet Gupta 
10913347c10SVineet Gupta 	EXCEPTION_PROLOGUE_KEEP_AE	; return ECR in r10
11013347c10SVineet Gupta 
11113347c10SVineet Gupta 	lr  r0, [efa]
11213347c10SVineet Gupta 	mov r1, sp
11313347c10SVineet Gupta 
11413347c10SVineet Gupta 	FAKE_RET_FROM_EXCPN		; clobbers r9
11513347c10SVineet Gupta .endm
11613347c10SVineet Gupta 
117a4880801SVineet Gupta /*------------------------------------------------------------------------
118a4880801SVineet Gupta  * This macro saves the registers manually which would normally be autosaved
119a4880801SVineet Gupta  * by hardware on taken interrupts. It is used by
120a4880801SVineet Gupta  *   - exception handlers (which don't have autosave)
121a4880801SVineet Gupta  *   - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
122a4880801SVineet Gupta  */
123a4880801SVineet Gupta .macro __SAVE_REGFILE_HARD
124a4880801SVineet Gupta 
125a4880801SVineet Gupta 	ST2	r0,  r1,  PT_r0
126a4880801SVineet Gupta 	ST2	r2,  r3,  PT_r2
127a4880801SVineet Gupta 	ST2	r4,  r5,  PT_r4
128a4880801SVineet Gupta 	ST2	r6,  r7,  PT_r6
129a4880801SVineet Gupta 	ST2	r8,  r9,  PT_r8
130a4880801SVineet Gupta 	ST2	r10, r11, PT_r10
131a4880801SVineet Gupta 
132a4880801SVineet Gupta 	st	blink, [sp, PT_blink]
133a4880801SVineet Gupta 
134a4880801SVineet Gupta 	lr	r10, [lp_end]
135a4880801SVineet Gupta 	lr	r11, [lp_start]
136a4880801SVineet Gupta 	ST2	r10, r11, PT_lpe
137a4880801SVineet Gupta 
138a4880801SVineet Gupta 	st	lp_count, [sp, PT_lpc]
139a4880801SVineet Gupta 
140a4880801SVineet Gupta 	; skip JLI, LDI, EI for now
141a4880801SVineet Gupta .endm
142a4880801SVineet Gupta 
143a4880801SVineet Gupta /*------------------------------------------------------------------------
144a4880801SVineet Gupta  * This macros saves a bunch of other registers which can't be autosaved for
145a4880801SVineet Gupta  * various reasons:
146a4880801SVineet Gupta  *   - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
147a4880801SVineet Gupta  *   - r30: free reg, used by gcc as scratch
148a4880801SVineet Gupta  *   - ACCL/ACCH pair when they exist
149a4880801SVineet Gupta  */
150a4880801SVineet Gupta .macro __SAVE_REGFILE_SOFT
151a4880801SVineet Gupta 
152*d4624bf6SVineet Gupta 	st	fp,  [sp, PT_fp]	; r27
153c505b0daSVineet Gupta 	st	r30, [sp, PT_r30]
154*d4624bf6SVineet Gupta 	st	r12, [sp, PT_r12]
155*d4624bf6SVineet Gupta 	st	r26, [sp, PT_r26]	; gp
156a4880801SVineet Gupta 
157a4880801SVineet Gupta 	; Saving pt_regs->sp correctly requires some extra work due to the way
158a4880801SVineet Gupta 	; Auto stack switch works
159a4880801SVineet Gupta 	;  - U mode: retrieve it from AUX_USER_SP
160a4880801SVineet Gupta 	;  - K mode: add the offset from current SP where H/w starts auto push
161a4880801SVineet Gupta 	;
162a4880801SVineet Gupta 	; 1. Utilize the fact that Z bit is set if Intr taken in U mode
163a4880801SVineet Gupta 	; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
164a4880801SVineet Gupta 	;    but on return, restored only if U mode
165a4880801SVineet Gupta 
166a4880801SVineet Gupta 	lr	r10, [AUX_USER_SP]	; U mode SP
167a4880801SVineet Gupta 
168a4880801SVineet Gupta 	; ISA requires ADD.nz to have same dest and src reg operands
169a4880801SVineet Gupta 	mov.nz	r10, sp
170656f18adSVineet Gupta 	add2.nz	r10, r10, SZ_PT_REGS/4	; K mode SP
171a4880801SVineet Gupta 
172a4880801SVineet Gupta 	st	r10, [sp, PT_sp]	; SP (pt_regs->sp)
173a4880801SVineet Gupta 
174a4880801SVineet Gupta #ifdef CONFIG_ARC_HAS_ACCL_REGS
1757ecc6c1dSEugeniy Paltsev 	ST2	r58, r59, PT_r58
176a4880801SVineet Gupta #endif
177a4880801SVineet Gupta 
1784827d0cfSEugeniy Paltsev 	/* clobbers r10, r11 registers pair */
1794827d0cfSEugeniy Paltsev 	DSP_SAVE_REGFILE_IRQ
180cfca4b5aSVineet Gupta 
181cfca4b5aSVineet Gupta #ifdef CONFIG_ARC_CURR_IN_REG
182cfca4b5aSVineet Gupta 	GET_CURR_TASK_ON_CPU	gp
183cfca4b5aSVineet Gupta #endif
184cfca4b5aSVineet Gupta 
185a4880801SVineet Gupta .endm
186a4880801SVineet Gupta 
187a4880801SVineet Gupta /*------------------------------------------------------------------------*/
188a4880801SVineet Gupta .macro __RESTORE_REGFILE_SOFT
189a4880801SVineet Gupta 
190*d4624bf6SVineet Gupta 	ld	fp,  [sp, PT_fp]
1917ecc6c1dSEugeniy Paltsev 	ld	r30, [sp, PT_r30]
192*d4624bf6SVineet Gupta 	ld	r12, [sp, PT_r12]
193*d4624bf6SVineet Gupta 	ld	r26, [sp, PT_r26]
194a4880801SVineet Gupta 
195a4880801SVineet Gupta 	; Restore SP (into AUX_USER_SP) only if returning to U mode
196a4880801SVineet Gupta 	;  - for K mode, it will be implicitly restored as stack is unwound
197a4880801SVineet Gupta 	;  - Z flag set on K is inverse of what hardware does on interrupt entry
198a4880801SVineet Gupta 	;    but that doesn't really matter
199a4880801SVineet Gupta 	bz	1f
200a4880801SVineet Gupta 
201a4880801SVineet Gupta 	ld	r10, [sp, PT_sp]	; SP (pt_regs->sp)
202a4880801SVineet Gupta 	sr	r10, [AUX_USER_SP]
203a4880801SVineet Gupta 1:
204a4880801SVineet Gupta 
2057321e2eaSEugeniy Paltsev 	/* clobbers r10, r11 registers pair */
2067321e2eaSEugeniy Paltsev 	DSP_RESTORE_REGFILE_IRQ
2077321e2eaSEugeniy Paltsev 
208a4880801SVineet Gupta #ifdef CONFIG_ARC_HAS_ACCL_REGS
2097ecc6c1dSEugeniy Paltsev 	LD2	r58, r59, PT_r58
210a4880801SVineet Gupta #endif
211a4880801SVineet Gupta .endm
212a4880801SVineet Gupta 
213a4880801SVineet Gupta /*------------------------------------------------------------------------*/
214a4880801SVineet Gupta .macro __RESTORE_REGFILE_HARD
215a4880801SVineet Gupta 
216a4880801SVineet Gupta 	ld	blink, [sp, PT_blink]
217a4880801SVineet Gupta 
218a4880801SVineet Gupta 	LD2	r10, r11, PT_lpe
219a4880801SVineet Gupta 	sr	r10, [lp_end]
220a4880801SVineet Gupta 	sr	r11, [lp_start]
221a4880801SVineet Gupta 
222a4880801SVineet Gupta 	ld	r10, [sp, PT_lpc]	; lp_count can't be target of LD
223a4880801SVineet Gupta 	mov	lp_count, r10
224a4880801SVineet Gupta 
225a4880801SVineet Gupta 	LD2	r0,  r1,  PT_r0
226a4880801SVineet Gupta 	LD2	r2,  r3,  PT_r2
227a4880801SVineet Gupta 	LD2	r4,  r5,  PT_r4
228a4880801SVineet Gupta 	LD2	r6,  r7,  PT_r6
229a4880801SVineet Gupta 	LD2	r8,  r9,  PT_r8
230a4880801SVineet Gupta 	LD2	r10, r11, PT_r10
231a4880801SVineet Gupta .endm
232a4880801SVineet Gupta 
233a4880801SVineet Gupta 
234a4880801SVineet Gupta /*------------------------------------------------------------------------*/
235a4880801SVineet Gupta .macro INTERRUPT_EPILOGUE
236a4880801SVineet Gupta 
237a4880801SVineet Gupta 	; INPUT: r0 has STAT32 of calling context
238a4880801SVineet Gupta 	; INPUT: Z flag set if returning to K mode
239a4880801SVineet Gupta 
240a4880801SVineet Gupta 	; _SOFT clobbers r10 restored by _HARD hence the order
241a4880801SVineet Gupta 
242a4880801SVineet Gupta 	__RESTORE_REGFILE_SOFT
243a4880801SVineet Gupta 
244a4880801SVineet Gupta #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
245a4880801SVineet Gupta 	__RESTORE_REGFILE_HARD
24649b41356SVineet Gupta 
24749b41356SVineet Gupta 	; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
248a4880801SVineet Gupta 	add	sp, sp, SZ_PT_REGS - 8
249a4880801SVineet Gupta #else
250a4880801SVineet Gupta 	add	sp, sp, PT_r0
251a4880801SVineet Gupta #endif
252a4880801SVineet Gupta 
253a4880801SVineet Gupta .endm
254a4880801SVineet Gupta 
2551f6ccfffSVineet Gupta /*------------------------------------------------------------------------*/
2561f6ccfffSVineet Gupta .macro EXCEPTION_EPILOGUE
2571f6ccfffSVineet Gupta 
25845869eb0SVineet Gupta 	; INPUT: r0 has STAT32 of calling context
2591f6ccfffSVineet Gupta 
260a4880801SVineet Gupta 	btst	r0, STATUS_U_BIT	; Z flag set if K, used in restoring SP
2611f6ccfffSVineet Gupta 
262c505b0daSVineet Gupta 	ld	r10, [sp, PT_bta]
263a4880801SVineet Gupta 	sr	r10, [erbta]
2641f6ccfffSVineet Gupta 
265a4880801SVineet Gupta 	LD2	r10, r11, PT_ret
266a4880801SVineet Gupta 	sr	r10, [eret]
267a4880801SVineet Gupta 	sr	r11, [erstatus]
2681f6ccfffSVineet Gupta 
269a4880801SVineet Gupta 	__RESTORE_REGFILE_SOFT
270a4880801SVineet Gupta 	__RESTORE_REGFILE_HARD
2711f6ccfffSVineet Gupta 
272a4880801SVineet Gupta 	add	sp, sp, SZ_PT_REGS
2731f6ccfffSVineet Gupta .endm
2741f6ccfffSVineet Gupta 
2751f6ccfffSVineet Gupta .macro FAKE_RET_FROM_EXCPN
2761f6ccfffSVineet Gupta 	lr      r9, [status32]
277dfb12071SVineet Gupta 	bclr    r9, r9, STATUS_AE_BIT
278dfb12071SVineet Gupta 	bset    r9, r9, STATUS_IE_BIT
2791f6ccfffSVineet Gupta 	kflag   r9
2801f6ccfffSVineet Gupta .endm
2811f6ccfffSVineet Gupta 
2821f6ccfffSVineet Gupta /* Get thread_info of "current" tsk */
2831f6ccfffSVineet Gupta .macro GET_CURR_THR_INFO_FROM_SP  reg
2841f6ccfffSVineet Gupta 	bmskn \reg, sp, THREAD_SHIFT - 1
2851f6ccfffSVineet Gupta .endm
2861f6ccfffSVineet Gupta 
2871f6ccfffSVineet Gupta /* Get CPU-ID of this core */
2881f6ccfffSVineet Gupta .macro  GET_CPU_ID  reg
2891f6ccfffSVineet Gupta 	lr  \reg, [identity]
2901f6ccfffSVineet Gupta 	xbfu \reg, \reg, 0xE8	/* 00111    01000 */
2911f6ccfffSVineet Gupta 				/* M = 8-1  N = 8 */
2921f6ccfffSVineet Gupta .endm
2931f6ccfffSVineet Gupta 
2941f6ccfffSVineet Gupta #endif
295