Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 #ifndef __ASM_ARC_ENTRY_ARCV2_H
0004 #define __ASM_ARC_ENTRY_ARCV2_H
0005 
0006 #include <asm/asm-offsets.h>
0007 #include <asm/dsp-impl.h>
0008 #include <asm/irqflags-arcv2.h>
0009 #include <asm/thread_info.h>    /* For THREAD_SIZE */
0010 
0011 /*
0012  * Interrupt/Exception stack layout (pt_regs) for ARCv2
0013  *   (End of struct aligned to end of page [unless nested])
0014  *
0015  *  INTERRUPT                          EXCEPTION
0016  *
0017  *    manual    ---------------------  manual
0018  *              |      orig_r0      |
0019  *              |      event/ECR    |
0020  *              |      bta          |
0021  *              |      user_r25     |
0022  *              |      gp           |
0023  *              |      fp           |
0024  *              |      sp           |
0025  *              |      r12          |
0026  *              |      r30          |
0027  *              |      r58          |
0028  *              |      r59          |
0029  *  hw autosave ---------------------
0030  *    optional  |      r0           |
0031  *              |      r1           |
0032  *              ~                   ~
0033  *              |      r9           |
0034  *              |      r10          |
0035  *              |      r11          |
0036  *              |      blink        |
0037  *              |      lpe          |
0038  *              |      lps          |
0039  *              |      lpc          |
0040  *              |      ei base      |
0041  *              |      ldi base     |
0042  *              |      jli base     |
0043  *              ---------------------
0044  *  hw autosave |       pc / eret   |
0045  *   mandatory  | stat32 / erstatus |
0046  *              ---------------------
0047  */
0048 
0049 /*------------------------------------------------------------------------*/
0050 .macro INTERRUPT_PROLOGUE
0051 
0052     ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
0053     ;   1. SP auto-switched to kernel mode stack
0054     ;   2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
0055     ;   3. Auto save: (mandatory) Push PC and STAT32 on stack
0056     ;                 hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
0057     ;   4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
0058     ;
0059     ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
0060 
0061 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
0062     ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
0063     sub sp, sp, SZ_PT_REGS - 8
0064 
0065     __SAVE_REGFILE_HARD
0066 #else
0067     ; carve pt_regs on stack (case #4), which grew partially already
0068     sub sp, sp, PT_r0
0069 #endif
0070 
0071     __SAVE_REGFILE_SOFT
0072 .endm
0073 
0074 /*------------------------------------------------------------------------*/
0075 .macro EXCEPTION_PROLOGUE
0076 
0077     ; (A) Before jumping to Exception Vector, hardware micro-ops did following:
0078     ;   1. SP auto-switched to kernel mode stack
0079     ;   2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
0080     ;
0081     ; (B) Manually save the complete reg file below
0082 
0083     sub sp, sp, SZ_PT_REGS  ; carve pt_regs
0084 
0085     ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
0086 
0087     __SAVE_REGFILE_HARD
0088     __SAVE_REGFILE_SOFT
0089 
0090     st  r0, [sp]    ; orig_r0
0091 
0092     lr  r10, [eret]
0093     lr  r11, [erstatus]
0094     ST2 r10, r11, PT_ret
0095 
0096     lr  r10, [ecr]
0097     lr  r11, [erbta]
0098     ST2 r10, r11, PT_event
0099 
0100     ; OUTPUT: r10 has ECR expected by EV_Trap
0101 .endm
0102 
0103 /*------------------------------------------------------------------------
0104  * This macro saves the registers manually which would normally be autosaved
0105  * by hardware on taken interrupts. It is used by
0106  *   - exception handlers (which don't have autosave)
0107  *   - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
0108  */
0109 .macro __SAVE_REGFILE_HARD
0110 
0111     ST2 r0,  r1,  PT_r0
0112     ST2 r2,  r3,  PT_r2
0113     ST2 r4,  r5,  PT_r4
0114     ST2 r6,  r7,  PT_r6
0115     ST2 r8,  r9,  PT_r8
0116     ST2 r10, r11, PT_r10
0117 
0118     st  blink, [sp, PT_blink]
0119 
0120     lr  r10, [lp_end]
0121     lr  r11, [lp_start]
0122     ST2 r10, r11, PT_lpe
0123 
0124     st  lp_count, [sp, PT_lpc]
0125 
0126     ; skip JLI, LDI, EI for now
0127 .endm
0128 
0129 /*------------------------------------------------------------------------
0130  * This macros saves a bunch of other registers which can't be autosaved for
0131  * various reasons:
0132  *   - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
0133  *   - r30: free reg, used by gcc as scratch
0134  *   - ACCL/ACCH pair when they exist
0135  */
0136 .macro __SAVE_REGFILE_SOFT
0137 
0138     ST2 gp, fp, PT_r26      ; gp (r26), fp (r27)
0139 
0140     st  r12, [sp, PT_sp + 4]
0141     st  r30, [sp, PT_sp + 8]
0142 
0143     ; Saving pt_regs->sp correctly requires some extra work due to the way
0144     ; Auto stack switch works
0145     ;  - U mode: retrieve it from AUX_USER_SP
0146     ;  - K mode: add the offset from current SP where H/w starts auto push
0147     ;
0148     ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
0149     ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
0150     ;    but on return, restored only if U mode
0151 
0152     lr  r10, [AUX_USER_SP]  ; U mode SP
0153 
0154     ; ISA requires ADD.nz to have same dest and src reg operands
0155     mov.nz  r10, sp
0156     add.nz  r10, r10, SZ_PT_REGS    ; K mode SP
0157 
0158     st  r10, [sp, PT_sp]    ; SP (pt_regs->sp)
0159 
0160 #ifdef CONFIG_ARC_CURR_IN_REG
0161     st  r25, [sp, PT_user_r25]
0162     GET_CURR_TASK_ON_CPU    r25
0163 #endif
0164 
0165 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0166     ST2 r58, r59, PT_r58
0167 #endif
0168 
0169     /* clobbers r10, r11 registers pair */
0170     DSP_SAVE_REGFILE_IRQ
0171 .endm
0172 
0173 /*------------------------------------------------------------------------*/
0174 .macro __RESTORE_REGFILE_SOFT
0175 
0176     LD2 gp, fp, PT_r26      ; gp (r26), fp (r27)
0177 
0178     ld  r12, [sp, PT_r12]
0179     ld  r30, [sp, PT_r30]
0180 
0181     ; Restore SP (into AUX_USER_SP) only if returning to U mode
0182     ;  - for K mode, it will be implicitly restored as stack is unwound
0183     ;  - Z flag set on K is inverse of what hardware does on interrupt entry
0184     ;    but that doesn't really matter
0185     bz  1f
0186 
0187     ld  r10, [sp, PT_sp]    ; SP (pt_regs->sp)
0188     sr  r10, [AUX_USER_SP]
0189 1:
0190 
0191 #ifdef CONFIG_ARC_CURR_IN_REG
0192     ld  r25, [sp, PT_user_r25]
0193 #endif
0194 
0195     /* clobbers r10, r11 registers pair */
0196     DSP_RESTORE_REGFILE_IRQ
0197 
0198 #ifdef CONFIG_ARC_HAS_ACCL_REGS
0199     LD2 r58, r59, PT_r58
0200 #endif
0201 .endm
0202 
0203 /*------------------------------------------------------------------------*/
0204 .macro __RESTORE_REGFILE_HARD
0205 
0206     ld  blink, [sp, PT_blink]
0207 
0208     LD2 r10, r11, PT_lpe
0209     sr  r10, [lp_end]
0210     sr  r11, [lp_start]
0211 
0212     ld  r10, [sp, PT_lpc]   ; lp_count can't be target of LD
0213     mov lp_count, r10
0214 
0215     LD2 r0,  r1,  PT_r0
0216     LD2 r2,  r3,  PT_r2
0217     LD2 r4,  r5,  PT_r4
0218     LD2 r6,  r7,  PT_r6
0219     LD2 r8,  r9,  PT_r8
0220     LD2 r10, r11, PT_r10
0221 .endm
0222 
0223 
0224 /*------------------------------------------------------------------------*/
0225 .macro INTERRUPT_EPILOGUE
0226 
0227     ; INPUT: r0 has STAT32 of calling context
0228     ; INPUT: Z flag set if returning to K mode
0229 
0230     ; _SOFT clobbers r10 restored by _HARD hence the order
0231 
0232     __RESTORE_REGFILE_SOFT
0233 
0234 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
0235     __RESTORE_REGFILE_HARD
0236 
0237     ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
0238     add sp, sp, SZ_PT_REGS - 8
0239 #else
0240     add sp, sp, PT_r0
0241 #endif
0242 
0243 .endm
0244 
0245 /*------------------------------------------------------------------------*/
0246 .macro EXCEPTION_EPILOGUE
0247 
0248     ; INPUT: r0 has STAT32 of calling context
0249 
0250     btst    r0, STATUS_U_BIT    ; Z flag set if K, used in restoring SP
0251 
0252     ld  r10, [sp, PT_event + 4]
0253     sr  r10, [erbta]
0254 
0255     LD2 r10, r11, PT_ret
0256     sr  r10, [eret]
0257     sr  r11, [erstatus]
0258 
0259     __RESTORE_REGFILE_SOFT
0260     __RESTORE_REGFILE_HARD
0261 
0262     add sp, sp, SZ_PT_REGS
0263 .endm
0264 
0265 .macro FAKE_RET_FROM_EXCPN
0266     lr      r9, [status32]
0267     bic     r9, r9, STATUS_AE_MASK
0268     or      r9, r9, STATUS_IE_MASK
0269     kflag   r9
0270 .endm
0271 
0272 /* Get thread_info of "current" tsk */
0273 .macro GET_CURR_THR_INFO_FROM_SP  reg
0274     bmskn \reg, sp, THREAD_SHIFT - 1
0275 .endm
0276 
0277 /* Get CPU-ID of this core */
0278 .macro  GET_CPU_ID  reg
0279     lr  \reg, [identity]
0280     xbfu \reg, \reg, 0xE8   /* 00111    01000 */
0281                 /* M = 8-1  N = 8 */
0282 .endm
0283 
0284 #endif