Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1994, 95, 96, 99, 2001 Ralf Baechle
0007  * Copyright (C) 1994, 1995, 1996 Paul M. Antoine.
0008  * Copyright (C) 1999 Silicon Graphics, Inc.
0009  * Copyright (C) 2007  Maciej W. Rozycki
0010  */
0011 #ifndef _ASM_STACKFRAME_H
0012 #define _ASM_STACKFRAME_H
0013 
0014 #include <linux/threads.h>
0015 
0016 #include <asm/asm.h>
0017 #include <asm/asmmacro.h>
0018 #include <asm/mipsregs.h>
0019 #include <asm/asm-offsets.h>
0020 #include <asm/thread_info.h>
0021 
0022 /* Make the addition of cfi info a little easier. */
0023     .macro cfi_rel_offset reg offset=0 docfi=0
0024     .if \docfi
0025     .cfi_rel_offset \reg, \offset
0026     .endif
0027     .endm
0028 
0029     .macro cfi_st reg offset=0 docfi=0
0030     LONG_S  \reg, \offset(sp)
0031     cfi_rel_offset \reg, \offset, \docfi
0032     .endm
0033 
0034     .macro cfi_restore reg offset=0 docfi=0
0035     .if \docfi
0036     .cfi_restore \reg
0037     .endif
0038     .endm
0039 
0040     .macro cfi_ld reg offset=0 docfi=0
0041     LONG_L  \reg, \offset(sp)
0042     cfi_restore \reg \offset \docfi
0043     .endm
0044 
0045 #if defined(CONFIG_CPU_R3000)
0046 #define STATMASK 0x3f
0047 #else
0048 #define STATMASK 0x1f
0049 #endif
0050 
0051         .macro  SAVE_AT docfi=0
0052         .set    push
0053         .set    noat
0054         cfi_st  $1, PT_R1, \docfi
0055         .set    pop
0056         .endm
0057 
0058         .macro  SAVE_TEMP docfi=0
0059 #ifdef CONFIG_CPU_HAS_SMARTMIPS
0060         mflhxu  v1
0061         LONG_S  v1, PT_LO(sp)
0062         mflhxu  v1
0063         LONG_S  v1, PT_HI(sp)
0064         mflhxu  v1
0065         LONG_S  v1, PT_ACX(sp)
0066 #elif !defined(CONFIG_CPU_MIPSR6)
0067         mfhi    v1
0068 #endif
0069 #ifdef CONFIG_32BIT
0070         cfi_st  $8, PT_R8, \docfi
0071         cfi_st  $9, PT_R9, \docfi
0072 #endif
0073         cfi_st  $10, PT_R10, \docfi
0074         cfi_st  $11, PT_R11, \docfi
0075         cfi_st  $12, PT_R12, \docfi
0076 #if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
0077         LONG_S  v1, PT_HI(sp)
0078         mflo    v1
0079 #endif
0080         cfi_st  $13, PT_R13, \docfi
0081         cfi_st  $14, PT_R14, \docfi
0082         cfi_st  $15, PT_R15, \docfi
0083         cfi_st  $24, PT_R24, \docfi
0084 #if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
0085         LONG_S  v1, PT_LO(sp)
0086 #endif
0087 #ifdef CONFIG_CPU_CAVIUM_OCTEON
0088         /*
0089          * The Octeon multiplier state is affected by general
0090          * multiply instructions. It must be saved before and
0091          * kernel code might corrupt it
0092          */
0093         jal     octeon_mult_save
0094 #endif
0095         .endm
0096 
0097         .macro  SAVE_STATIC docfi=0
0098         cfi_st  $16, PT_R16, \docfi
0099         cfi_st  $17, PT_R17, \docfi
0100         cfi_st  $18, PT_R18, \docfi
0101         cfi_st  $19, PT_R19, \docfi
0102         cfi_st  $20, PT_R20, \docfi
0103         cfi_st  $21, PT_R21, \docfi
0104         cfi_st  $22, PT_R22, \docfi
0105         cfi_st  $23, PT_R23, \docfi
0106         cfi_st  $30, PT_R30, \docfi
0107         .endm
0108 
0109 /*
0110  * get_saved_sp returns the SP for the current CPU by looking in the
0111  * kernelsp array for it.  If tosp is set, it stores the current sp in
0112  * k0 and loads the new value in sp.  If not, it clobbers k0 and
0113  * stores the new value in k1, leaving sp unaffected.
0114  */
0115 #ifdef CONFIG_SMP
0116 
0117         /* SMP variation */
0118         .macro  get_saved_sp docfi=0 tosp=0
0119         ASM_CPUID_MFC0  k0, ASM_SMP_CPUID_REG
0120 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
0121         lui k1, %hi(kernelsp)
0122 #else
0123         lui k1, %highest(kernelsp)
0124         daddiu  k1, %higher(kernelsp)
0125         dsll    k1, 16
0126         daddiu  k1, %hi(kernelsp)
0127         dsll    k1, 16
0128 #endif
0129         LONG_SRL    k0, SMP_CPUID_PTRSHIFT
0130         LONG_ADDU   k1, k0
0131         .if \tosp
0132         move    k0, sp
0133         .if \docfi
0134         .cfi_register sp, k0
0135         .endif
0136         LONG_L  sp, %lo(kernelsp)(k1)
0137         .else
0138         LONG_L  k1, %lo(kernelsp)(k1)
0139         .endif
0140         .endm
0141 
0142         .macro  set_saved_sp stackp temp temp2
0143         ASM_CPUID_MFC0  \temp, ASM_SMP_CPUID_REG
0144         LONG_SRL    \temp, SMP_CPUID_PTRSHIFT
0145         LONG_S  \stackp, kernelsp(\temp)
0146         .endm
0147 #else /* !CONFIG_SMP */
0148         /* Uniprocessor variation */
0149         .macro  get_saved_sp docfi=0 tosp=0
0150 #ifdef CONFIG_CPU_JUMP_WORKAROUNDS
0151         /*
0152          * Clear BTB (branch target buffer), forbid RAS (return address
0153          * stack) to workaround the Out-of-order Issue in Loongson2F
0154          * via its diagnostic register.
0155          */
0156         move    k0, ra
0157         jal 1f
0158          nop
0159 1:      jal 1f
0160          nop
0161 1:      jal 1f
0162          nop
0163 1:      jal 1f
0164          nop
0165 1:      move    ra, k0
0166         li  k0, 3
0167         mtc0    k0, $22
0168 #endif /* CONFIG_CPU_JUMP_WORKAROUNDS */
0169 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
0170         lui k1, %hi(kernelsp)
0171 #else
0172         lui k1, %highest(kernelsp)
0173         daddiu  k1, %higher(kernelsp)
0174         dsll    k1, k1, 16
0175         daddiu  k1, %hi(kernelsp)
0176         dsll    k1, k1, 16
0177 #endif
0178         .if \tosp
0179         move    k0, sp
0180         .if \docfi
0181         .cfi_register sp, k0
0182         .endif
0183         LONG_L  sp, %lo(kernelsp)(k1)
0184         .else
0185         LONG_L  k1, %lo(kernelsp)(k1)
0186         .endif
0187         .endm
0188 
0189         .macro  set_saved_sp stackp temp temp2
0190         LONG_S  \stackp, kernelsp
0191         .endm
0192 #endif
0193 
0194         .macro  SAVE_SOME docfi=0
0195         .set    push
0196         .set    noat
0197         .set    reorder
0198         mfc0    k0, CP0_STATUS
0199         sll k0, 3       /* extract cu0 bit */
0200         .set    noreorder
0201         bltz    k0, 8f
0202          move   k0, sp
0203         .if \docfi
0204         .cfi_register sp, k0
0205         .endif
0206 #ifdef CONFIG_EVA
0207         /*
0208          * Flush interAptiv's Return Prediction Stack (RPS) by writing
0209          * EntryHi. Toggling Config7.RPS is slower and less portable.
0210          *
0211          * The RPS isn't automatically flushed when exceptions are
0212          * taken, which can result in kernel mode speculative accesses
0213          * to user addresses if the RPS mispredicts. That's harmless
0214          * when user and kernel share the same address space, but with
0215          * EVA the same user segments may be unmapped to kernel mode,
0216          * even containing sensitive MMIO regions or invalid memory.
0217          *
0218          * This can happen when the kernel sets the return address to
0219          * ret_from_* and jr's to the exception handler, which looks
0220          * more like a tail call than a function call. If nested calls
0221          * don't evict the last user address in the RPS, it will
0222          * mispredict the return and fetch from a user controlled
0223          * address into the icache.
0224          *
0225          * More recent EVA-capable cores with MAAR to restrict
0226          * speculative accesses aren't affected.
0227          */
0228         MFC0    k0, CP0_ENTRYHI
0229         MTC0    k0, CP0_ENTRYHI
0230 #endif
0231         .set    reorder
0232         /* Called from user mode, new stack. */
0233         get_saved_sp docfi=\docfi tosp=1
0234 8:
0235 #ifdef CONFIG_CPU_DADDI_WORKAROUNDS
0236         .set    at=k1
0237 #endif
0238         PTR_SUBU sp, PT_SIZE
0239 #ifdef CONFIG_CPU_DADDI_WORKAROUNDS
0240         .set    noat
0241 #endif
0242         .if \docfi
0243         .cfi_def_cfa sp,0
0244         .endif
0245         cfi_st  k0, PT_R29, \docfi
0246         cfi_rel_offset  sp, PT_R29, \docfi
0247         cfi_st  v1, PT_R3, \docfi
0248         /*
0249          * You might think that you don't need to save $0,
0250          * but the FPU emulator and gdb remote debug stub
0251          * need it to operate correctly
0252          */
0253         LONG_S  $0, PT_R0(sp)
0254         mfc0    v1, CP0_STATUS
0255         cfi_st  v0, PT_R2, \docfi
0256         LONG_S  v1, PT_STATUS(sp)
0257         cfi_st  $4, PT_R4, \docfi
0258         mfc0    v1, CP0_CAUSE
0259         cfi_st  $5, PT_R5, \docfi
0260         LONG_S  v1, PT_CAUSE(sp)
0261         cfi_st  $6, PT_R6, \docfi
0262         cfi_st  ra, PT_R31, \docfi
0263         MFC0    ra, CP0_EPC
0264         cfi_st  $7, PT_R7, \docfi
0265 #ifdef CONFIG_64BIT
0266         cfi_st  $8, PT_R8, \docfi
0267         cfi_st  $9, PT_R9, \docfi
0268 #endif
0269         LONG_S  ra, PT_EPC(sp)
0270         .if \docfi
0271         .cfi_rel_offset ra, PT_EPC
0272         .endif
0273         cfi_st  $25, PT_R25, \docfi
0274         cfi_st  $28, PT_R28, \docfi
0275 
0276         /* Set thread_info if we're coming from user mode */
0277         mfc0    k0, CP0_STATUS
0278         sll k0, 3       /* extract cu0 bit */
0279         bltz    k0, 9f
0280 
0281         ori $28, sp, _THREAD_MASK
0282         xori    $28, _THREAD_MASK
0283 #ifdef CONFIG_CPU_CAVIUM_OCTEON
0284         .set    mips64
0285         pref    0, 0($28)       /* Prefetch the current pointer */
0286 #endif
0287 9:
0288         .set    pop
0289         .endm
0290 
0291         .macro  SAVE_ALL docfi=0
0292         SAVE_SOME \docfi
0293         SAVE_AT \docfi
0294         SAVE_TEMP \docfi
0295         SAVE_STATIC \docfi
0296         .endm
0297 
0298         .macro  RESTORE_AT docfi=0
0299         .set    push
0300         .set    noat
0301         cfi_ld  $1, PT_R1, \docfi
0302         .set    pop
0303         .endm
0304 
0305         .macro  RESTORE_TEMP docfi=0
0306 #ifdef CONFIG_CPU_CAVIUM_OCTEON
0307         /* Restore the Octeon multiplier state */
0308         jal octeon_mult_restore
0309 #endif
0310 #ifdef CONFIG_CPU_HAS_SMARTMIPS
0311         LONG_L  $24, PT_ACX(sp)
0312         mtlhx   $24
0313         LONG_L  $24, PT_HI(sp)
0314         mtlhx   $24
0315         LONG_L  $24, PT_LO(sp)
0316         mtlhx   $24
0317 #elif !defined(CONFIG_CPU_MIPSR6)
0318         LONG_L  $24, PT_LO(sp)
0319         mtlo    $24
0320         LONG_L  $24, PT_HI(sp)
0321         mthi    $24
0322 #endif
0323 #ifdef CONFIG_32BIT
0324         cfi_ld  $8, PT_R8, \docfi
0325         cfi_ld  $9, PT_R9, \docfi
0326 #endif
0327         cfi_ld  $10, PT_R10, \docfi
0328         cfi_ld  $11, PT_R11, \docfi
0329         cfi_ld  $12, PT_R12, \docfi
0330         cfi_ld  $13, PT_R13, \docfi
0331         cfi_ld  $14, PT_R14, \docfi
0332         cfi_ld  $15, PT_R15, \docfi
0333         cfi_ld  $24, PT_R24, \docfi
0334         .endm
0335 
0336         .macro  RESTORE_STATIC docfi=0
0337         cfi_ld  $16, PT_R16, \docfi
0338         cfi_ld  $17, PT_R17, \docfi
0339         cfi_ld  $18, PT_R18, \docfi
0340         cfi_ld  $19, PT_R19, \docfi
0341         cfi_ld  $20, PT_R20, \docfi
0342         cfi_ld  $21, PT_R21, \docfi
0343         cfi_ld  $22, PT_R22, \docfi
0344         cfi_ld  $23, PT_R23, \docfi
0345         cfi_ld  $30, PT_R30, \docfi
0346         .endm
0347 
0348         .macro  RESTORE_SP docfi=0
0349         cfi_ld  sp, PT_R29, \docfi
0350         .endm
0351 
0352 #if defined(CONFIG_CPU_R3000)
0353 
0354         .macro  RESTORE_SOME docfi=0
0355         .set    push
0356         .set    reorder
0357         .set    noat
0358         mfc0    a0, CP0_STATUS
0359         li  v1, ST0_CU1 | ST0_IM
0360         ori a0, STATMASK
0361         xori    a0, STATMASK
0362         mtc0    a0, CP0_STATUS
0363         and a0, v1
0364         LONG_L  v0, PT_STATUS(sp)
0365         nor v1, $0, v1
0366         and v0, v1
0367         or  v0, a0
0368         mtc0    v0, CP0_STATUS
0369         cfi_ld  $31, PT_R31, \docfi
0370         cfi_ld  $28, PT_R28, \docfi
0371         cfi_ld  $25, PT_R25, \docfi
0372         cfi_ld  $7,  PT_R7, \docfi
0373         cfi_ld  $6,  PT_R6, \docfi
0374         cfi_ld  $5,  PT_R5, \docfi
0375         cfi_ld  $4,  PT_R4, \docfi
0376         cfi_ld  $3,  PT_R3, \docfi
0377         cfi_ld  $2,  PT_R2, \docfi
0378         .set    pop
0379         .endm
0380 
0381         .macro  RESTORE_SP_AND_RET docfi=0
0382         .set    push
0383         .set    noreorder
0384         LONG_L  k0, PT_EPC(sp)
0385         RESTORE_SP \docfi
0386         jr  k0
0387          rfe
0388         .set    pop
0389         .endm
0390 
0391 #else
0392         .macro  RESTORE_SOME docfi=0
0393         .set    push
0394         .set    reorder
0395         .set    noat
0396         mfc0    a0, CP0_STATUS
0397         ori a0, STATMASK
0398         xori    a0, STATMASK
0399         mtc0    a0, CP0_STATUS
0400         li  v1, ST0_CU1 | ST0_FR | ST0_IM
0401         and a0, v1
0402         LONG_L  v0, PT_STATUS(sp)
0403         nor v1, $0, v1
0404         and v0, v1
0405         or  v0, a0
0406         mtc0    v0, CP0_STATUS
0407         LONG_L  v1, PT_EPC(sp)
0408         MTC0    v1, CP0_EPC
0409         cfi_ld  $31, PT_R31, \docfi
0410         cfi_ld  $28, PT_R28, \docfi
0411         cfi_ld  $25, PT_R25, \docfi
0412 #ifdef CONFIG_64BIT
0413         cfi_ld  $8, PT_R8, \docfi
0414         cfi_ld  $9, PT_R9, \docfi
0415 #endif
0416         cfi_ld  $7,  PT_R7, \docfi
0417         cfi_ld  $6,  PT_R6, \docfi
0418         cfi_ld  $5,  PT_R5, \docfi
0419         cfi_ld  $4,  PT_R4, \docfi
0420         cfi_ld  $3,  PT_R3, \docfi
0421         cfi_ld  $2,  PT_R2, \docfi
0422         .set    pop
0423         .endm
0424 
0425         .macro  RESTORE_SP_AND_RET docfi=0
0426         RESTORE_SP \docfi
0427 #if defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6)
0428         eretnc
0429 #else
0430         .set    push
0431         .set    arch=r4000
0432         eret
0433         .set    pop
0434 #endif
0435         .endm
0436 
0437 #endif
0438 
0439         .macro  RESTORE_ALL docfi=0
0440         RESTORE_TEMP \docfi
0441         RESTORE_STATIC \docfi
0442         RESTORE_AT \docfi
0443         RESTORE_SOME \docfi
0444         RESTORE_SP \docfi
0445         .endm
0446 
0447 /*
0448  * Move to kernel mode and disable interrupts.
0449  * Set cp0 enable bit as sign that we're running on the kernel stack
0450  */
0451         .macro  CLI
0452         mfc0    t0, CP0_STATUS
0453         li  t1, ST0_KERNEL_CUMASK | STATMASK
0454         or  t0, t1
0455         xori    t0, STATMASK
0456         mtc0    t0, CP0_STATUS
0457         irq_disable_hazard
0458         .endm
0459 
0460 /*
0461  * Move to kernel mode and enable interrupts.
0462  * Set cp0 enable bit as sign that we're running on the kernel stack
0463  */
0464         .macro  STI
0465         mfc0    t0, CP0_STATUS
0466         li  t1, ST0_KERNEL_CUMASK | STATMASK
0467         or  t0, t1
0468         xori    t0, STATMASK & ~1
0469         mtc0    t0, CP0_STATUS
0470         irq_enable_hazard
0471         .endm
0472 
0473 /*
0474  * Just move to kernel mode and leave interrupts as they are.  Note
0475  * for the R3000 this means copying the previous enable from IEp.
0476  * Set cp0 enable bit as sign that we're running on the kernel stack
0477  */
0478         .macro  KMODE
0479         mfc0    t0, CP0_STATUS
0480         li  t1, ST0_KERNEL_CUMASK | (STATMASK & ~1)
0481 #if defined(CONFIG_CPU_R3000)
0482         andi    t2, t0, ST0_IEP
0483         srl t2, 2
0484         or  t0, t2
0485 #endif
0486         or  t0, t1
0487         xori    t0, STATMASK & ~1
0488         mtc0    t0, CP0_STATUS
0489         irq_disable_hazard
0490         .endm
0491 
0492 #endif /* _ASM_STACKFRAME_H */