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