162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 1994, 95, 96, 99, 2001 Ralf Baechle 762306a36Sopenharmony_ci * Copyright (C) 1994, 1995, 1996 Paul M. Antoine. 862306a36Sopenharmony_ci * Copyright (C) 1999 Silicon Graphics, Inc. 962306a36Sopenharmony_ci * Copyright (C) 2007 Maciej W. Rozycki 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#ifndef _ASM_STACKFRAME_H 1262306a36Sopenharmony_ci#define _ASM_STACKFRAME_H 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/threads.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <asm/asm.h> 1762306a36Sopenharmony_ci#include <asm/asmmacro.h> 1862306a36Sopenharmony_ci#include <asm/mipsregs.h> 1962306a36Sopenharmony_ci#include <asm/asm-offsets.h> 2062306a36Sopenharmony_ci#include <asm/thread_info.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* Make the addition of cfi info a little easier. */ 2362306a36Sopenharmony_ci .macro cfi_rel_offset reg offset=0 docfi=0 2462306a36Sopenharmony_ci .if \docfi 2562306a36Sopenharmony_ci .cfi_rel_offset \reg, \offset 2662306a36Sopenharmony_ci .endif 2762306a36Sopenharmony_ci .endm 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci .macro cfi_st reg offset=0 docfi=0 3062306a36Sopenharmony_ci LONG_S \reg, \offset(sp) 3162306a36Sopenharmony_ci cfi_rel_offset \reg, \offset, \docfi 3262306a36Sopenharmony_ci .endm 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci .macro cfi_restore reg offset=0 docfi=0 3562306a36Sopenharmony_ci .if \docfi 3662306a36Sopenharmony_ci .cfi_restore \reg 3762306a36Sopenharmony_ci .endif 3862306a36Sopenharmony_ci .endm 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci .macro cfi_ld reg offset=0 docfi=0 4162306a36Sopenharmony_ci LONG_L \reg, \offset(sp) 4262306a36Sopenharmony_ci cfi_restore \reg \offset \docfi 4362306a36Sopenharmony_ci .endm 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#if defined(CONFIG_CPU_R3000) 4662306a36Sopenharmony_ci#define STATMASK 0x3f 4762306a36Sopenharmony_ci#else 4862306a36Sopenharmony_ci#define STATMASK 0x1f 4962306a36Sopenharmony_ci#endif 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci .macro SAVE_AT docfi=0 5262306a36Sopenharmony_ci .set push 5362306a36Sopenharmony_ci .set noat 5462306a36Sopenharmony_ci cfi_st $1, PT_R1, \docfi 5562306a36Sopenharmony_ci .set pop 5662306a36Sopenharmony_ci .endm 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci .macro SAVE_TEMP docfi=0 5962306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_SMARTMIPS 6062306a36Sopenharmony_ci mflhxu v1 6162306a36Sopenharmony_ci LONG_S v1, PT_LO(sp) 6262306a36Sopenharmony_ci mflhxu v1 6362306a36Sopenharmony_ci LONG_S v1, PT_HI(sp) 6462306a36Sopenharmony_ci mflhxu v1 6562306a36Sopenharmony_ci LONG_S v1, PT_ACX(sp) 6662306a36Sopenharmony_ci#elif !defined(CONFIG_CPU_MIPSR6) 6762306a36Sopenharmony_ci mfhi v1 6862306a36Sopenharmony_ci#endif 6962306a36Sopenharmony_ci#ifdef CONFIG_32BIT 7062306a36Sopenharmony_ci cfi_st $8, PT_R8, \docfi 7162306a36Sopenharmony_ci cfi_st $9, PT_R9, \docfi 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci cfi_st $10, PT_R10, \docfi 7462306a36Sopenharmony_ci cfi_st $11, PT_R11, \docfi 7562306a36Sopenharmony_ci cfi_st $12, PT_R12, \docfi 7662306a36Sopenharmony_ci#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6) 7762306a36Sopenharmony_ci LONG_S v1, PT_HI(sp) 7862306a36Sopenharmony_ci mflo v1 7962306a36Sopenharmony_ci#endif 8062306a36Sopenharmony_ci cfi_st $13, PT_R13, \docfi 8162306a36Sopenharmony_ci cfi_st $14, PT_R14, \docfi 8262306a36Sopenharmony_ci cfi_st $15, PT_R15, \docfi 8362306a36Sopenharmony_ci cfi_st $24, PT_R24, \docfi 8462306a36Sopenharmony_ci#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6) 8562306a36Sopenharmony_ci LONG_S v1, PT_LO(sp) 8662306a36Sopenharmony_ci#endif 8762306a36Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON 8862306a36Sopenharmony_ci /* 8962306a36Sopenharmony_ci * The Octeon multiplier state is affected by general 9062306a36Sopenharmony_ci * multiply instructions. It must be saved before and 9162306a36Sopenharmony_ci * kernel code might corrupt it 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci jal octeon_mult_save 9462306a36Sopenharmony_ci#endif 9562306a36Sopenharmony_ci .endm 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci .macro SAVE_STATIC docfi=0 9862306a36Sopenharmony_ci cfi_st $16, PT_R16, \docfi 9962306a36Sopenharmony_ci cfi_st $17, PT_R17, \docfi 10062306a36Sopenharmony_ci cfi_st $18, PT_R18, \docfi 10162306a36Sopenharmony_ci cfi_st $19, PT_R19, \docfi 10262306a36Sopenharmony_ci cfi_st $20, PT_R20, \docfi 10362306a36Sopenharmony_ci cfi_st $21, PT_R21, \docfi 10462306a36Sopenharmony_ci cfi_st $22, PT_R22, \docfi 10562306a36Sopenharmony_ci cfi_st $23, PT_R23, \docfi 10662306a36Sopenharmony_ci cfi_st $30, PT_R30, \docfi 10762306a36Sopenharmony_ci .endm 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* 11062306a36Sopenharmony_ci * get_saved_sp returns the SP for the current CPU by looking in the 11162306a36Sopenharmony_ci * kernelsp array for it. If tosp is set, it stores the current sp in 11262306a36Sopenharmony_ci * k0 and loads the new value in sp. If not, it clobbers k0 and 11362306a36Sopenharmony_ci * stores the new value in k1, leaving sp unaffected. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci#ifdef CONFIG_SMP 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* SMP variation */ 11862306a36Sopenharmony_ci .macro get_saved_sp docfi=0 tosp=0 11962306a36Sopenharmony_ci ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG 12062306a36Sopenharmony_ci#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) 12162306a36Sopenharmony_ci lui k1, %hi(kernelsp) 12262306a36Sopenharmony_ci#else 12362306a36Sopenharmony_ci lui k1, %highest(kernelsp) 12462306a36Sopenharmony_ci daddiu k1, %higher(kernelsp) 12562306a36Sopenharmony_ci dsll k1, 16 12662306a36Sopenharmony_ci daddiu k1, %hi(kernelsp) 12762306a36Sopenharmony_ci dsll k1, 16 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci LONG_SRL k0, SMP_CPUID_PTRSHIFT 13062306a36Sopenharmony_ci LONG_ADDU k1, k0 13162306a36Sopenharmony_ci .if \tosp 13262306a36Sopenharmony_ci move k0, sp 13362306a36Sopenharmony_ci .if \docfi 13462306a36Sopenharmony_ci .cfi_register sp, k0 13562306a36Sopenharmony_ci .endif 13662306a36Sopenharmony_ci LONG_L sp, %lo(kernelsp)(k1) 13762306a36Sopenharmony_ci .else 13862306a36Sopenharmony_ci LONG_L k1, %lo(kernelsp)(k1) 13962306a36Sopenharmony_ci .endif 14062306a36Sopenharmony_ci .endm 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci .macro set_saved_sp stackp temp temp2 14362306a36Sopenharmony_ci ASM_CPUID_MFC0 \temp, ASM_SMP_CPUID_REG 14462306a36Sopenharmony_ci LONG_SRL \temp, SMP_CPUID_PTRSHIFT 14562306a36Sopenharmony_ci LONG_S \stackp, kernelsp(\temp) 14662306a36Sopenharmony_ci .endm 14762306a36Sopenharmony_ci#else /* !CONFIG_SMP */ 14862306a36Sopenharmony_ci /* Uniprocessor variation */ 14962306a36Sopenharmony_ci .macro get_saved_sp docfi=0 tosp=0 15062306a36Sopenharmony_ci#ifdef CONFIG_CPU_JUMP_WORKAROUNDS 15162306a36Sopenharmony_ci /* 15262306a36Sopenharmony_ci * Clear BTB (branch target buffer), forbid RAS (return address 15362306a36Sopenharmony_ci * stack) to workaround the Out-of-order Issue in Loongson2F 15462306a36Sopenharmony_ci * via its diagnostic register. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci move k0, ra 15762306a36Sopenharmony_ci jal 1f 15862306a36Sopenharmony_ci nop 15962306a36Sopenharmony_ci1: jal 1f 16062306a36Sopenharmony_ci nop 16162306a36Sopenharmony_ci1: jal 1f 16262306a36Sopenharmony_ci nop 16362306a36Sopenharmony_ci1: jal 1f 16462306a36Sopenharmony_ci nop 16562306a36Sopenharmony_ci1: move ra, k0 16662306a36Sopenharmony_ci li k0, 3 16762306a36Sopenharmony_ci mtc0 k0, $22 16862306a36Sopenharmony_ci#endif /* CONFIG_CPU_JUMP_WORKAROUNDS */ 16962306a36Sopenharmony_ci#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) 17062306a36Sopenharmony_ci lui k1, %hi(kernelsp) 17162306a36Sopenharmony_ci#else 17262306a36Sopenharmony_ci lui k1, %highest(kernelsp) 17362306a36Sopenharmony_ci daddiu k1, %higher(kernelsp) 17462306a36Sopenharmony_ci dsll k1, k1, 16 17562306a36Sopenharmony_ci daddiu k1, %hi(kernelsp) 17662306a36Sopenharmony_ci dsll k1, k1, 16 17762306a36Sopenharmony_ci#endif 17862306a36Sopenharmony_ci .if \tosp 17962306a36Sopenharmony_ci move k0, sp 18062306a36Sopenharmony_ci .if \docfi 18162306a36Sopenharmony_ci .cfi_register sp, k0 18262306a36Sopenharmony_ci .endif 18362306a36Sopenharmony_ci LONG_L sp, %lo(kernelsp)(k1) 18462306a36Sopenharmony_ci .else 18562306a36Sopenharmony_ci LONG_L k1, %lo(kernelsp)(k1) 18662306a36Sopenharmony_ci .endif 18762306a36Sopenharmony_ci .endm 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci .macro set_saved_sp stackp temp temp2 19062306a36Sopenharmony_ci LONG_S \stackp, kernelsp 19162306a36Sopenharmony_ci .endm 19262306a36Sopenharmony_ci#endif 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci .macro SAVE_SOME docfi=0 19562306a36Sopenharmony_ci .set push 19662306a36Sopenharmony_ci .set noat 19762306a36Sopenharmony_ci .set reorder 19862306a36Sopenharmony_ci mfc0 k0, CP0_STATUS 19962306a36Sopenharmony_ci sll k0, 3 /* extract cu0 bit */ 20062306a36Sopenharmony_ci .set noreorder 20162306a36Sopenharmony_ci bltz k0, 8f 20262306a36Sopenharmony_ci move k0, sp 20362306a36Sopenharmony_ci .if \docfi 20462306a36Sopenharmony_ci .cfi_register sp, k0 20562306a36Sopenharmony_ci .endif 20662306a36Sopenharmony_ci#ifdef CONFIG_EVA 20762306a36Sopenharmony_ci /* 20862306a36Sopenharmony_ci * Flush interAptiv's Return Prediction Stack (RPS) by writing 20962306a36Sopenharmony_ci * EntryHi. Toggling Config7.RPS is slower and less portable. 21062306a36Sopenharmony_ci * 21162306a36Sopenharmony_ci * The RPS isn't automatically flushed when exceptions are 21262306a36Sopenharmony_ci * taken, which can result in kernel mode speculative accesses 21362306a36Sopenharmony_ci * to user addresses if the RPS mispredicts. That's harmless 21462306a36Sopenharmony_ci * when user and kernel share the same address space, but with 21562306a36Sopenharmony_ci * EVA the same user segments may be unmapped to kernel mode, 21662306a36Sopenharmony_ci * even containing sensitive MMIO regions or invalid memory. 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * This can happen when the kernel sets the return address to 21962306a36Sopenharmony_ci * ret_from_* and jr's to the exception handler, which looks 22062306a36Sopenharmony_ci * more like a tail call than a function call. If nested calls 22162306a36Sopenharmony_ci * don't evict the last user address in the RPS, it will 22262306a36Sopenharmony_ci * mispredict the return and fetch from a user controlled 22362306a36Sopenharmony_ci * address into the icache. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * More recent EVA-capable cores with MAAR to restrict 22662306a36Sopenharmony_ci * speculative accesses aren't affected. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci MFC0 k0, CP0_ENTRYHI 22962306a36Sopenharmony_ci MTC0 k0, CP0_ENTRYHI 23062306a36Sopenharmony_ci#endif 23162306a36Sopenharmony_ci .set reorder 23262306a36Sopenharmony_ci /* Called from user mode, new stack. */ 23362306a36Sopenharmony_ci get_saved_sp docfi=\docfi tosp=1 23462306a36Sopenharmony_ci8: 23562306a36Sopenharmony_ci#ifdef CONFIG_CPU_DADDI_WORKAROUNDS 23662306a36Sopenharmony_ci .set at=k1 23762306a36Sopenharmony_ci#endif 23862306a36Sopenharmony_ci PTR_SUBU sp, PT_SIZE 23962306a36Sopenharmony_ci#ifdef CONFIG_CPU_DADDI_WORKAROUNDS 24062306a36Sopenharmony_ci .set noat 24162306a36Sopenharmony_ci#endif 24262306a36Sopenharmony_ci .if \docfi 24362306a36Sopenharmony_ci .cfi_def_cfa sp,0 24462306a36Sopenharmony_ci .endif 24562306a36Sopenharmony_ci cfi_st k0, PT_R29, \docfi 24662306a36Sopenharmony_ci cfi_rel_offset sp, PT_R29, \docfi 24762306a36Sopenharmony_ci cfi_st v1, PT_R3, \docfi 24862306a36Sopenharmony_ci /* 24962306a36Sopenharmony_ci * You might think that you don't need to save $0, 25062306a36Sopenharmony_ci * but the FPU emulator and gdb remote debug stub 25162306a36Sopenharmony_ci * need it to operate correctly 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_ci LONG_S $0, PT_R0(sp) 25462306a36Sopenharmony_ci mfc0 v1, CP0_STATUS 25562306a36Sopenharmony_ci cfi_st v0, PT_R2, \docfi 25662306a36Sopenharmony_ci LONG_S v1, PT_STATUS(sp) 25762306a36Sopenharmony_ci cfi_st $4, PT_R4, \docfi 25862306a36Sopenharmony_ci mfc0 v1, CP0_CAUSE 25962306a36Sopenharmony_ci cfi_st $5, PT_R5, \docfi 26062306a36Sopenharmony_ci LONG_S v1, PT_CAUSE(sp) 26162306a36Sopenharmony_ci cfi_st $6, PT_R6, \docfi 26262306a36Sopenharmony_ci cfi_st ra, PT_R31, \docfi 26362306a36Sopenharmony_ci MFC0 ra, CP0_EPC 26462306a36Sopenharmony_ci cfi_st $7, PT_R7, \docfi 26562306a36Sopenharmony_ci#ifdef CONFIG_64BIT 26662306a36Sopenharmony_ci cfi_st $8, PT_R8, \docfi 26762306a36Sopenharmony_ci cfi_st $9, PT_R9, \docfi 26862306a36Sopenharmony_ci#endif 26962306a36Sopenharmony_ci LONG_S ra, PT_EPC(sp) 27062306a36Sopenharmony_ci .if \docfi 27162306a36Sopenharmony_ci .cfi_rel_offset ra, PT_EPC 27262306a36Sopenharmony_ci .endif 27362306a36Sopenharmony_ci cfi_st $25, PT_R25, \docfi 27462306a36Sopenharmony_ci cfi_st $28, PT_R28, \docfi 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* Set thread_info if we're coming from user mode */ 27762306a36Sopenharmony_ci mfc0 k0, CP0_STATUS 27862306a36Sopenharmony_ci sll k0, 3 /* extract cu0 bit */ 27962306a36Sopenharmony_ci bltz k0, 9f 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci ori $28, sp, _THREAD_MASK 28262306a36Sopenharmony_ci xori $28, _THREAD_MASK 28362306a36Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON 28462306a36Sopenharmony_ci .set mips64 28562306a36Sopenharmony_ci pref 0, 0($28) /* Prefetch the current pointer */ 28662306a36Sopenharmony_ci#endif 28762306a36Sopenharmony_ci9: 28862306a36Sopenharmony_ci .set pop 28962306a36Sopenharmony_ci .endm 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci .macro SAVE_ALL docfi=0 29262306a36Sopenharmony_ci SAVE_SOME \docfi 29362306a36Sopenharmony_ci SAVE_AT \docfi 29462306a36Sopenharmony_ci SAVE_TEMP \docfi 29562306a36Sopenharmony_ci SAVE_STATIC \docfi 29662306a36Sopenharmony_ci .endm 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci .macro RESTORE_AT docfi=0 29962306a36Sopenharmony_ci .set push 30062306a36Sopenharmony_ci .set noat 30162306a36Sopenharmony_ci cfi_ld $1, PT_R1, \docfi 30262306a36Sopenharmony_ci .set pop 30362306a36Sopenharmony_ci .endm 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci .macro RESTORE_TEMP docfi=0 30662306a36Sopenharmony_ci#ifdef CONFIG_CPU_CAVIUM_OCTEON 30762306a36Sopenharmony_ci /* Restore the Octeon multiplier state */ 30862306a36Sopenharmony_ci jal octeon_mult_restore 30962306a36Sopenharmony_ci#endif 31062306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_SMARTMIPS 31162306a36Sopenharmony_ci LONG_L $24, PT_ACX(sp) 31262306a36Sopenharmony_ci mtlhx $24 31362306a36Sopenharmony_ci LONG_L $24, PT_HI(sp) 31462306a36Sopenharmony_ci mtlhx $24 31562306a36Sopenharmony_ci LONG_L $24, PT_LO(sp) 31662306a36Sopenharmony_ci mtlhx $24 31762306a36Sopenharmony_ci#elif !defined(CONFIG_CPU_MIPSR6) 31862306a36Sopenharmony_ci LONG_L $24, PT_LO(sp) 31962306a36Sopenharmony_ci mtlo $24 32062306a36Sopenharmony_ci LONG_L $24, PT_HI(sp) 32162306a36Sopenharmony_ci mthi $24 32262306a36Sopenharmony_ci#endif 32362306a36Sopenharmony_ci#ifdef CONFIG_32BIT 32462306a36Sopenharmony_ci cfi_ld $8, PT_R8, \docfi 32562306a36Sopenharmony_ci cfi_ld $9, PT_R9, \docfi 32662306a36Sopenharmony_ci#endif 32762306a36Sopenharmony_ci cfi_ld $10, PT_R10, \docfi 32862306a36Sopenharmony_ci cfi_ld $11, PT_R11, \docfi 32962306a36Sopenharmony_ci cfi_ld $12, PT_R12, \docfi 33062306a36Sopenharmony_ci cfi_ld $13, PT_R13, \docfi 33162306a36Sopenharmony_ci cfi_ld $14, PT_R14, \docfi 33262306a36Sopenharmony_ci cfi_ld $15, PT_R15, \docfi 33362306a36Sopenharmony_ci cfi_ld $24, PT_R24, \docfi 33462306a36Sopenharmony_ci .endm 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci .macro RESTORE_STATIC docfi=0 33762306a36Sopenharmony_ci cfi_ld $16, PT_R16, \docfi 33862306a36Sopenharmony_ci cfi_ld $17, PT_R17, \docfi 33962306a36Sopenharmony_ci cfi_ld $18, PT_R18, \docfi 34062306a36Sopenharmony_ci cfi_ld $19, PT_R19, \docfi 34162306a36Sopenharmony_ci cfi_ld $20, PT_R20, \docfi 34262306a36Sopenharmony_ci cfi_ld $21, PT_R21, \docfi 34362306a36Sopenharmony_ci cfi_ld $22, PT_R22, \docfi 34462306a36Sopenharmony_ci cfi_ld $23, PT_R23, \docfi 34562306a36Sopenharmony_ci cfi_ld $30, PT_R30, \docfi 34662306a36Sopenharmony_ci .endm 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci .macro RESTORE_SP docfi=0 34962306a36Sopenharmony_ci cfi_ld sp, PT_R29, \docfi 35062306a36Sopenharmony_ci .endm 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci#if defined(CONFIG_CPU_R3000) 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci .macro RESTORE_SOME docfi=0 35562306a36Sopenharmony_ci .set push 35662306a36Sopenharmony_ci .set reorder 35762306a36Sopenharmony_ci .set noat 35862306a36Sopenharmony_ci mfc0 a0, CP0_STATUS 35962306a36Sopenharmony_ci li v1, ST0_CU1 | ST0_IM 36062306a36Sopenharmony_ci ori a0, STATMASK 36162306a36Sopenharmony_ci xori a0, STATMASK 36262306a36Sopenharmony_ci mtc0 a0, CP0_STATUS 36362306a36Sopenharmony_ci and a0, v1 36462306a36Sopenharmony_ci LONG_L v0, PT_STATUS(sp) 36562306a36Sopenharmony_ci nor v1, $0, v1 36662306a36Sopenharmony_ci and v0, v1 36762306a36Sopenharmony_ci or v0, a0 36862306a36Sopenharmony_ci mtc0 v0, CP0_STATUS 36962306a36Sopenharmony_ci cfi_ld $31, PT_R31, \docfi 37062306a36Sopenharmony_ci cfi_ld $28, PT_R28, \docfi 37162306a36Sopenharmony_ci cfi_ld $25, PT_R25, \docfi 37262306a36Sopenharmony_ci cfi_ld $7, PT_R7, \docfi 37362306a36Sopenharmony_ci cfi_ld $6, PT_R6, \docfi 37462306a36Sopenharmony_ci cfi_ld $5, PT_R5, \docfi 37562306a36Sopenharmony_ci cfi_ld $4, PT_R4, \docfi 37662306a36Sopenharmony_ci cfi_ld $3, PT_R3, \docfi 37762306a36Sopenharmony_ci cfi_ld $2, PT_R2, \docfi 37862306a36Sopenharmony_ci .set pop 37962306a36Sopenharmony_ci .endm 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci .macro RESTORE_SP_AND_RET docfi=0 38262306a36Sopenharmony_ci .set push 38362306a36Sopenharmony_ci .set noreorder 38462306a36Sopenharmony_ci LONG_L k0, PT_EPC(sp) 38562306a36Sopenharmony_ci RESTORE_SP \docfi 38662306a36Sopenharmony_ci jr k0 38762306a36Sopenharmony_ci rfe 38862306a36Sopenharmony_ci .set pop 38962306a36Sopenharmony_ci .endm 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci#else 39262306a36Sopenharmony_ci .macro RESTORE_SOME docfi=0 39362306a36Sopenharmony_ci .set push 39462306a36Sopenharmony_ci .set reorder 39562306a36Sopenharmony_ci .set noat 39662306a36Sopenharmony_ci mfc0 a0, CP0_STATUS 39762306a36Sopenharmony_ci ori a0, STATMASK 39862306a36Sopenharmony_ci xori a0, STATMASK 39962306a36Sopenharmony_ci mtc0 a0, CP0_STATUS 40062306a36Sopenharmony_ci li v1, ST0_CU1 | ST0_FR | ST0_IM 40162306a36Sopenharmony_ci and a0, v1 40262306a36Sopenharmony_ci LONG_L v0, PT_STATUS(sp) 40362306a36Sopenharmony_ci nor v1, $0, v1 40462306a36Sopenharmony_ci and v0, v1 40562306a36Sopenharmony_ci or v0, a0 40662306a36Sopenharmony_ci mtc0 v0, CP0_STATUS 40762306a36Sopenharmony_ci LONG_L v1, PT_EPC(sp) 40862306a36Sopenharmony_ci MTC0 v1, CP0_EPC 40962306a36Sopenharmony_ci cfi_ld $31, PT_R31, \docfi 41062306a36Sopenharmony_ci cfi_ld $28, PT_R28, \docfi 41162306a36Sopenharmony_ci cfi_ld $25, PT_R25, \docfi 41262306a36Sopenharmony_ci#ifdef CONFIG_64BIT 41362306a36Sopenharmony_ci cfi_ld $8, PT_R8, \docfi 41462306a36Sopenharmony_ci cfi_ld $9, PT_R9, \docfi 41562306a36Sopenharmony_ci#endif 41662306a36Sopenharmony_ci cfi_ld $7, PT_R7, \docfi 41762306a36Sopenharmony_ci cfi_ld $6, PT_R6, \docfi 41862306a36Sopenharmony_ci cfi_ld $5, PT_R5, \docfi 41962306a36Sopenharmony_ci cfi_ld $4, PT_R4, \docfi 42062306a36Sopenharmony_ci cfi_ld $3, PT_R3, \docfi 42162306a36Sopenharmony_ci cfi_ld $2, PT_R2, \docfi 42262306a36Sopenharmony_ci .set pop 42362306a36Sopenharmony_ci .endm 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci .macro RESTORE_SP_AND_RET docfi=0 42662306a36Sopenharmony_ci RESTORE_SP \docfi 42762306a36Sopenharmony_ci#if defined(CONFIG_CPU_MIPSR5) || defined(CONFIG_CPU_MIPSR6) 42862306a36Sopenharmony_ci eretnc 42962306a36Sopenharmony_ci#else 43062306a36Sopenharmony_ci .set push 43162306a36Sopenharmony_ci .set arch=r4000 43262306a36Sopenharmony_ci eret 43362306a36Sopenharmony_ci .set pop 43462306a36Sopenharmony_ci#endif 43562306a36Sopenharmony_ci .endm 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci#endif 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci .macro RESTORE_ALL docfi=0 44062306a36Sopenharmony_ci RESTORE_TEMP \docfi 44162306a36Sopenharmony_ci RESTORE_STATIC \docfi 44262306a36Sopenharmony_ci RESTORE_AT \docfi 44362306a36Sopenharmony_ci RESTORE_SOME \docfi 44462306a36Sopenharmony_ci RESTORE_SP \docfi 44562306a36Sopenharmony_ci .endm 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci/* 44862306a36Sopenharmony_ci * Move to kernel mode and disable interrupts. 44962306a36Sopenharmony_ci * Set cp0 enable bit as sign that we're running on the kernel stack 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_ci .macro CLI 45262306a36Sopenharmony_ci mfc0 t0, CP0_STATUS 45362306a36Sopenharmony_ci li t1, ST0_KERNEL_CUMASK | STATMASK 45462306a36Sopenharmony_ci or t0, t1 45562306a36Sopenharmony_ci xori t0, STATMASK 45662306a36Sopenharmony_ci mtc0 t0, CP0_STATUS 45762306a36Sopenharmony_ci irq_disable_hazard 45862306a36Sopenharmony_ci .endm 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci/* 46162306a36Sopenharmony_ci * Move to kernel mode and enable interrupts. 46262306a36Sopenharmony_ci * Set cp0 enable bit as sign that we're running on the kernel stack 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci .macro STI 46562306a36Sopenharmony_ci mfc0 t0, CP0_STATUS 46662306a36Sopenharmony_ci li t1, ST0_KERNEL_CUMASK | STATMASK 46762306a36Sopenharmony_ci or t0, t1 46862306a36Sopenharmony_ci xori t0, STATMASK & ~1 46962306a36Sopenharmony_ci mtc0 t0, CP0_STATUS 47062306a36Sopenharmony_ci irq_enable_hazard 47162306a36Sopenharmony_ci .endm 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci/* 47462306a36Sopenharmony_ci * Just move to kernel mode and leave interrupts as they are. Note 47562306a36Sopenharmony_ci * for the R3000 this means copying the previous enable from IEp. 47662306a36Sopenharmony_ci * Set cp0 enable bit as sign that we're running on the kernel stack 47762306a36Sopenharmony_ci */ 47862306a36Sopenharmony_ci .macro KMODE 47962306a36Sopenharmony_ci mfc0 t0, CP0_STATUS 48062306a36Sopenharmony_ci li t1, ST0_KERNEL_CUMASK | (STATMASK & ~1) 48162306a36Sopenharmony_ci#if defined(CONFIG_CPU_R3000) 48262306a36Sopenharmony_ci andi t2, t0, ST0_IEP 48362306a36Sopenharmony_ci srl t2, 2 48462306a36Sopenharmony_ci or t0, t2 48562306a36Sopenharmony_ci#endif 48662306a36Sopenharmony_ci or t0, t1 48762306a36Sopenharmony_ci xori t0, STATMASK & ~1 48862306a36Sopenharmony_ci mtc0 t0, CP0_STATUS 48962306a36Sopenharmony_ci irq_disable_hazard 49062306a36Sopenharmony_ci .endm 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci#endif /* _ASM_STACKFRAME_H */ 493