162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#ifndef __ASM_ARC_ENTRY_ARCV2_H 462306a36Sopenharmony_ci#define __ASM_ARC_ENTRY_ARCV2_H 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <asm/asm-offsets.h> 762306a36Sopenharmony_ci#include <asm/dsp-impl.h> 862306a36Sopenharmony_ci#include <asm/irqflags-arcv2.h> 962306a36Sopenharmony_ci#include <asm/thread_info.h> /* For THREAD_SIZE */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * Interrupt/Exception stack layout (pt_regs) for ARCv2 1362306a36Sopenharmony_ci * (End of struct aligned to end of page [unless nested]) 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * INTERRUPT EXCEPTION 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * manual --------------------- manual 1862306a36Sopenharmony_ci * | orig_r0 | 1962306a36Sopenharmony_ci * | event/ECR | 2062306a36Sopenharmony_ci * | bta | 2162306a36Sopenharmony_ci * | gp | 2262306a36Sopenharmony_ci * | fp | 2362306a36Sopenharmony_ci * | sp | 2462306a36Sopenharmony_ci * | r12 | 2562306a36Sopenharmony_ci * | r30 | 2662306a36Sopenharmony_ci * | r58 | 2762306a36Sopenharmony_ci * | r59 | 2862306a36Sopenharmony_ci * hw autosave --------------------- 2962306a36Sopenharmony_ci * optional | r0 | 3062306a36Sopenharmony_ci * | r1 | 3162306a36Sopenharmony_ci * ~ ~ 3262306a36Sopenharmony_ci * | r9 | 3362306a36Sopenharmony_ci * | r10 | 3462306a36Sopenharmony_ci * | r11 | 3562306a36Sopenharmony_ci * | blink | 3662306a36Sopenharmony_ci * | lpe | 3762306a36Sopenharmony_ci * | lps | 3862306a36Sopenharmony_ci * | lpc | 3962306a36Sopenharmony_ci * | ei base | 4062306a36Sopenharmony_ci * | ldi base | 4162306a36Sopenharmony_ci * | jli base | 4262306a36Sopenharmony_ci * --------------------- 4362306a36Sopenharmony_ci * hw autosave | pc / eret | 4462306a36Sopenharmony_ci * mandatory | stat32 / erstatus | 4562306a36Sopenharmony_ci * --------------------- 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/*------------------------------------------------------------------------*/ 4962306a36Sopenharmony_ci.macro INTERRUPT_PROLOGUE 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci ; Before jumping to Interrupt Vector, hardware micro-ops did following: 5262306a36Sopenharmony_ci ; 1. SP auto-switched to kernel mode stack 5362306a36Sopenharmony_ci ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0) 5462306a36Sopenharmony_ci ; 3. Auto save: (mandatory) Push PC and STAT32 on stack 5562306a36Sopenharmony_ci ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE 5662306a36Sopenharmony_ci ; 4a. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI 5762306a36Sopenharmony_ci ; 5862306a36Sopenharmony_ci ; Now 5962306a36Sopenharmony_ci ; 4b. If Auto-save (optional) not enabled in hw, manually save them 6062306a36Sopenharmony_ci ; 5. Manually save: r12,r30, sp,fp,gp, ACCL pair 6162306a36Sopenharmony_ci ; 6262306a36Sopenharmony_ci ; At the end, SP points to pt_regs 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 6562306a36Sopenharmony_ci ; carve pt_regs on stack (case #3), PC/STAT32 already on stack 6662306a36Sopenharmony_ci sub sp, sp, SZ_PT_REGS - 8 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci __SAVE_REGFILE_HARD 6962306a36Sopenharmony_ci#else 7062306a36Sopenharmony_ci ; carve pt_regs on stack (case #4), which grew partially already 7162306a36Sopenharmony_ci sub sp, sp, PT_r0 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci __SAVE_REGFILE_SOFT 7562306a36Sopenharmony_ci.endm 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/*------------------------------------------------------------------------*/ 7862306a36Sopenharmony_ci.macro EXCEPTION_PROLOGUE_KEEP_AE 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci ; Before jumping to Exception Vector, hardware micro-ops did following: 8162306a36Sopenharmony_ci ; 1. SP auto-switched to kernel mode stack 8262306a36Sopenharmony_ci ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0) 8362306a36Sopenharmony_ci ; 8462306a36Sopenharmony_ci ; Now manually save rest of reg file 8562306a36Sopenharmony_ci ; At the end, SP points to pt_regs 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci sub sp, sp, SZ_PT_REGS ; carve space for pt_regs 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci __SAVE_REGFILE_HARD 9262306a36Sopenharmony_ci __SAVE_REGFILE_SOFT 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci st r0, [sp] ; orig_r0 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci lr r10, [eret] 9762306a36Sopenharmony_ci lr r11, [erstatus] 9862306a36Sopenharmony_ci ST2 r10, r11, PT_ret 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci lr r10, [ecr] 10162306a36Sopenharmony_ci lr r11, [erbta] 10262306a36Sopenharmony_ci ST2 r10, r11, PT_event 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci ; OUTPUT: r10 has ECR expected by EV_Trap 10562306a36Sopenharmony_ci.endm 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci.macro EXCEPTION_PROLOGUE 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci lr r0, [efa] 11262306a36Sopenharmony_ci mov r1, sp 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci FAKE_RET_FROM_EXCPN ; clobbers r9 11562306a36Sopenharmony_ci.endm 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/*------------------------------------------------------------------------ 11862306a36Sopenharmony_ci * This macro saves the registers manually which would normally be autosaved 11962306a36Sopenharmony_ci * by hardware on taken interrupts. It is used by 12062306a36Sopenharmony_ci * - exception handlers (which don't have autosave) 12162306a36Sopenharmony_ci * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci.macro __SAVE_REGFILE_HARD 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci ST2 r0, r1, PT_r0 12662306a36Sopenharmony_ci ST2 r2, r3, PT_r2 12762306a36Sopenharmony_ci ST2 r4, r5, PT_r4 12862306a36Sopenharmony_ci ST2 r6, r7, PT_r6 12962306a36Sopenharmony_ci ST2 r8, r9, PT_r8 13062306a36Sopenharmony_ci ST2 r10, r11, PT_r10 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci st blink, [sp, PT_blink] 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci lr r10, [lp_end] 13562306a36Sopenharmony_ci lr r11, [lp_start] 13662306a36Sopenharmony_ci ST2 r10, r11, PT_lpe 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci st lp_count, [sp, PT_lpc] 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci ; skip JLI, LDI, EI for now 14162306a36Sopenharmony_ci.endm 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/*------------------------------------------------------------------------ 14462306a36Sopenharmony_ci * This macros saves a bunch of other registers which can't be autosaved for 14562306a36Sopenharmony_ci * various reasons: 14662306a36Sopenharmony_ci * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11 14762306a36Sopenharmony_ci * - r30: free reg, used by gcc as scratch 14862306a36Sopenharmony_ci * - ACCL/ACCH pair when they exist 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ci.macro __SAVE_REGFILE_SOFT 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci st fp, [sp, PT_fp] ; r27 15362306a36Sopenharmony_ci st r30, [sp, PT_r30] 15462306a36Sopenharmony_ci st r12, [sp, PT_r12] 15562306a36Sopenharmony_ci st r26, [sp, PT_r26] ; gp 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci ; Saving pt_regs->sp correctly requires some extra work due to the way 15862306a36Sopenharmony_ci ; Auto stack switch works 15962306a36Sopenharmony_ci ; - U mode: retrieve it from AUX_USER_SP 16062306a36Sopenharmony_ci ; - K mode: add the offset from current SP where H/w starts auto push 16162306a36Sopenharmony_ci ; 16262306a36Sopenharmony_ci ; 1. Utilize the fact that Z bit is set if Intr taken in U mode 16362306a36Sopenharmony_ci ; 2. Upon entry SP is always saved (for any inspection, unwinding etc), 16462306a36Sopenharmony_ci ; but on return, restored only if U mode 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci lr r10, [AUX_USER_SP] ; U mode SP 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci ; ISA requires ADD.nz to have same dest and src reg operands 16962306a36Sopenharmony_ci mov.nz r10, sp 17062306a36Sopenharmony_ci add2.nz r10, r10, SZ_PT_REGS/4 ; K mode SP 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci st r10, [sp, PT_sp] ; SP (pt_regs->sp) 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#ifdef CONFIG_ARC_HAS_ACCL_REGS 17562306a36Sopenharmony_ci ST2 r58, r59, PT_r58 17662306a36Sopenharmony_ci#endif 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* clobbers r10, r11 registers pair */ 17962306a36Sopenharmony_ci DSP_SAVE_REGFILE_IRQ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#ifdef CONFIG_ARC_CURR_IN_REG 18262306a36Sopenharmony_ci GET_CURR_TASK_ON_CPU gp 18362306a36Sopenharmony_ci#endif 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci.endm 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/*------------------------------------------------------------------------*/ 18862306a36Sopenharmony_ci.macro __RESTORE_REGFILE_SOFT 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ld fp, [sp, PT_fp] 19162306a36Sopenharmony_ci ld r30, [sp, PT_r30] 19262306a36Sopenharmony_ci ld r12, [sp, PT_r12] 19362306a36Sopenharmony_ci ld r26, [sp, PT_r26] 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci ; Restore SP (into AUX_USER_SP) only if returning to U mode 19662306a36Sopenharmony_ci ; - for K mode, it will be implicitly restored as stack is unwound 19762306a36Sopenharmony_ci ; - Z flag set on K is inverse of what hardware does on interrupt entry 19862306a36Sopenharmony_ci ; but that doesn't really matter 19962306a36Sopenharmony_ci bz 1f 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci ld r10, [sp, PT_sp] ; SP (pt_regs->sp) 20262306a36Sopenharmony_ci sr r10, [AUX_USER_SP] 20362306a36Sopenharmony_ci1: 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* clobbers r10, r11 registers pair */ 20662306a36Sopenharmony_ci DSP_RESTORE_REGFILE_IRQ 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#ifdef CONFIG_ARC_HAS_ACCL_REGS 20962306a36Sopenharmony_ci LD2 r58, r59, PT_r58 21062306a36Sopenharmony_ci#endif 21162306a36Sopenharmony_ci.endm 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/*------------------------------------------------------------------------*/ 21462306a36Sopenharmony_ci.macro __RESTORE_REGFILE_HARD 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci ld blink, [sp, PT_blink] 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci LD2 r10, r11, PT_lpe 21962306a36Sopenharmony_ci sr r10, [lp_end] 22062306a36Sopenharmony_ci sr r11, [lp_start] 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci ld r10, [sp, PT_lpc] ; lp_count can't be target of LD 22362306a36Sopenharmony_ci mov lp_count, r10 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci LD2 r0, r1, PT_r0 22662306a36Sopenharmony_ci LD2 r2, r3, PT_r2 22762306a36Sopenharmony_ci LD2 r4, r5, PT_r4 22862306a36Sopenharmony_ci LD2 r6, r7, PT_r6 22962306a36Sopenharmony_ci LD2 r8, r9, PT_r8 23062306a36Sopenharmony_ci LD2 r10, r11, PT_r10 23162306a36Sopenharmony_ci.endm 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/*------------------------------------------------------------------------*/ 23562306a36Sopenharmony_ci.macro INTERRUPT_EPILOGUE 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci ; INPUT: r0 has STAT32 of calling context 23862306a36Sopenharmony_ci ; INPUT: Z flag set if returning to K mode 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci ; _SOFT clobbers r10 restored by _HARD hence the order 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci __RESTORE_REGFILE_SOFT 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 24562306a36Sopenharmony_ci __RESTORE_REGFILE_HARD 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE 24862306a36Sopenharmony_ci add sp, sp, SZ_PT_REGS - 8 24962306a36Sopenharmony_ci#else 25062306a36Sopenharmony_ci add sp, sp, PT_r0 25162306a36Sopenharmony_ci#endif 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci.endm 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci/*------------------------------------------------------------------------*/ 25662306a36Sopenharmony_ci.macro EXCEPTION_EPILOGUE 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci ; INPUT: r0 has STAT32 of calling context 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci ld r10, [sp, PT_bta] 26362306a36Sopenharmony_ci sr r10, [erbta] 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci LD2 r10, r11, PT_ret 26662306a36Sopenharmony_ci sr r10, [eret] 26762306a36Sopenharmony_ci sr r11, [erstatus] 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci __RESTORE_REGFILE_SOFT 27062306a36Sopenharmony_ci __RESTORE_REGFILE_HARD 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci add sp, sp, SZ_PT_REGS 27362306a36Sopenharmony_ci.endm 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci.macro FAKE_RET_FROM_EXCPN 27662306a36Sopenharmony_ci lr r9, [status32] 27762306a36Sopenharmony_ci bclr r9, r9, STATUS_AE_BIT 27862306a36Sopenharmony_ci bset r9, r9, STATUS_IE_BIT 27962306a36Sopenharmony_ci kflag r9 28062306a36Sopenharmony_ci.endm 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* Get thread_info of "current" tsk */ 28362306a36Sopenharmony_ci.macro GET_CURR_THR_INFO_FROM_SP reg 28462306a36Sopenharmony_ci bmskn \reg, sp, THREAD_SHIFT - 1 28562306a36Sopenharmony_ci.endm 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci/* Get CPU-ID of this core */ 28862306a36Sopenharmony_ci.macro GET_CPU_ID reg 28962306a36Sopenharmony_ci lr \reg, [identity] 29062306a36Sopenharmony_ci xbfu \reg, \reg, 0xE8 /* 00111 01000 */ 29162306a36Sopenharmony_ci /* M = 8-1 N = 8 */ 29262306a36Sopenharmony_ci.endm 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci#endif 295