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