diff options
Diffstat (limited to 'arch/mips/include/asm/stackframe.h')
| -rw-r--r-- | arch/mips/include/asm/stackframe.h | 259 | 
1 files changed, 26 insertions, 233 deletions
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index 58730c5ce4b..b188c797565 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -17,23 +17,14 @@  #include <asm/asmmacro.h>  #include <asm/mipsregs.h>  #include <asm/asm-offsets.h> +#include <asm/thread_info.h> -/* - * For SMTC kernel, global IE should be left set, and interrupts - * controlled exclusively via IXMT. - */ -#ifdef CONFIG_MIPS_MT_SMTC -#define STATMASK 0x1e -#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)  #define STATMASK 0x3f  #else  #define STATMASK 0x1f  #endif -#ifdef CONFIG_MIPS_MT_SMTC -#include <asm/mipsmtregs.h> -#endif /* CONFIG_MIPS_MT_SMTC */ -  		.macro	SAVE_AT  		.set	push  		.set	noat @@ -70,6 +61,14 @@  #ifndef CONFIG_CPU_HAS_SMARTMIPS  		LONG_S	v1, PT_LO(sp)  #endif +#ifdef CONFIG_CPU_CAVIUM_OCTEON +		/* +		 * The Octeon multiplier state is affected by general +		 * multiply instructions. It must be saved before and +		 * kernel code might corrupt it +		 */ +		jal     octeon_mult_save +#endif  		.endm  		.macro	SAVE_STATIC @@ -85,21 +84,8 @@  		.endm  #ifdef CONFIG_SMP -#ifdef CONFIG_MIPS_MT_SMTC -#define PTEBASE_SHIFT	19	/* TCBIND */ -#define CPU_ID_REG CP0_TCBIND -#define CPU_ID_MFC0 mfc0 -#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT) -#define PTEBASE_SHIFT	48	/* XCONTEXT */ -#define CPU_ID_REG CP0_XCONTEXT -#define CPU_ID_MFC0 MFC0 -#else -#define PTEBASE_SHIFT	23	/* CONTEXT */ -#define CPU_ID_REG CP0_CONTEXT -#define CPU_ID_MFC0 MFC0 -#endif  		.macro	get_saved_sp	/* SMP variation */ -		CPU_ID_MFC0	k0, CPU_ID_REG +		ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG  #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)  		lui	k1, %hi(kernelsp)  #else @@ -109,17 +95,17 @@  		daddiu	k1, %hi(kernelsp)  		dsll	k1, 16  #endif -		LONG_SRL	k0, PTEBASE_SHIFT +		LONG_SRL	k0, SMP_CPUID_PTRSHIFT  		LONG_ADDU	k1, k0  		LONG_L	k1, %lo(kernelsp)(k1)  		.endm  		.macro	set_saved_sp stackp temp temp2 -		CPU_ID_MFC0	\temp, CPU_ID_REG -		LONG_SRL	\temp, PTEBASE_SHIFT +		ASM_CPUID_MFC0	\temp, ASM_SMP_CPUID_REG +		LONG_SRL	\temp, SMP_CPUID_PTRSHIFT  		LONG_S	\stackp, kernelsp(\temp)  		.endm -#else +#else /* !CONFIG_SMP */  		.macro	get_saved_sp	/* Uniprocessor variation */  #ifdef CONFIG_CPU_JUMP_WORKAROUNDS  		/* @@ -139,7 +125,7 @@  1:		move	ra, k0  		li	k0, 3  		mtc0	k0, $22 -#endif /* CONFIG_CPU_LOONGSON2F */ +#endif /* CONFIG_CPU_JUMP_WORKAROUNDS */  #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)  		lui	k1, %hi(kernelsp)  #else @@ -189,46 +175,27 @@  		LONG_S	$0, PT_R0(sp)  		mfc0	v1, CP0_STATUS  		LONG_S	$2, PT_R2(sp) -#ifdef CONFIG_MIPS_MT_SMTC -		/* -		 * Ideally, these instructions would be shuffled in -		 * to cover the pipeline delay. -		 */ -		.set	mips32 -		mfc0	v1, CP0_TCSTATUS -		.set	mips0 -		LONG_S	v1, PT_TCSTATUS(sp) -#endif /* CONFIG_MIPS_MT_SMTC */ -		LONG_S	$4, PT_R4(sp) -		LONG_S	$5, PT_R5(sp)  		LONG_S	v1, PT_STATUS(sp) +		LONG_S	$4, PT_R4(sp)  		mfc0	v1, CP0_CAUSE -		LONG_S	$6, PT_R6(sp) -		LONG_S	$7, PT_R7(sp) +		LONG_S	$5, PT_R5(sp)  		LONG_S	v1, PT_CAUSE(sp) +		LONG_S	$6, PT_R6(sp)  		MFC0	v1, CP0_EPC +		LONG_S	$7, PT_R7(sp)  #ifdef CONFIG_64BIT  		LONG_S	$8, PT_R8(sp)  		LONG_S	$9, PT_R9(sp)  #endif +		LONG_S	v1, PT_EPC(sp)  		LONG_S	$25, PT_R25(sp)  		LONG_S	$28, PT_R28(sp)  		LONG_S	$31, PT_R31(sp) -		LONG_S	v1, PT_EPC(sp)  		ori	$28, sp, _THREAD_MASK  		xori	$28, _THREAD_MASK  #ifdef CONFIG_CPU_CAVIUM_OCTEON  		.set    mips64  		pref    0, 0($28)       /* Prefetch the current pointer */ -		pref    0, PT_R31(sp)   /* Prefetch the $31(ra) */ -		/* The Octeon multiplier state is affected by general multiply -		    instructions. It must be saved before and kernel code might -		    corrupt it */ -		jal     octeon_mult_save -		LONG_L  v1, 0($28)  /* Load the current pointer */ -			 /* Restore $31(ra) that was changed by the jal */ -		LONG_L  ra, PT_R31(sp) -		pref    0, 0(v1)    /* Prefetch the current thread */  #endif  		.set	pop  		.endm @@ -248,6 +215,10 @@  		.endm  		.macro	RESTORE_TEMP +#ifdef CONFIG_CPU_CAVIUM_OCTEON +		/* Restore the Octeon multiplier state */ +		jal	octeon_mult_restore +#endif  #ifdef CONFIG_CPU_HAS_SMARTMIPS  		LONG_L	$24, PT_ACX(sp)  		mtlhx	$24 @@ -330,40 +301,6 @@  		.set	push  		.set	reorder  		.set	noat -#ifdef CONFIG_MIPS_MT_SMTC -		.set	mips32r2 -		/* -		 * We need to make sure the read-modify-write -		 * of Status below isn't perturbed by an interrupt -		 * or cross-TC access, so we need to do at least a DMT, -		 * protected by an interrupt-inhibit. But setting IXMT -		 * also creates a few-cycle window where an IPI could -		 * be queued and not be detected before potentially -		 * returning to a WAIT or user-mode loop. It must be -		 * replayed. -		 * -		 * We're in the middle of a context switch, and -		 * we can't dispatch it directly without trashing -		 * some registers, so we'll try to detect this unlikely -		 * case and program a software interrupt in the VPE, -		 * as would be done for a cross-VPE IPI.  To accomodate -		 * the handling of that case, we're doing a DVPE instead -		 * of just a DMT here to protect against other threads. -		 * This is a lot of cruft to cover a tiny window. -		 * If you can find a better design, implement it! -		 * -		 */ -		mfc0	v0, CP0_TCSTATUS -		ori	v0, TCSTATUS_IXMT -		mtc0	v0, CP0_TCSTATUS -		_ehb -		DVPE	5				# dvpe a1 -		jal	mips_ihb -#endif /* CONFIG_MIPS_MT_SMTC */ -#ifdef CONFIG_CPU_CAVIUM_OCTEON -		/* Restore the Octeon multiplier state */ -		jal	octeon_mult_restore -#endif  		mfc0	a0, CP0_STATUS  		ori	a0, STATMASK  		xori	a0, STATMASK @@ -375,59 +312,6 @@  		and	v0, v1  		or	v0, a0  		mtc0	v0, CP0_STATUS -#ifdef CONFIG_MIPS_MT_SMTC -/* - * Only after EXL/ERL have been restored to status can we - * restore TCStatus.IXMT. - */ -		LONG_L	v1, PT_TCSTATUS(sp) -		_ehb -		mfc0	a0, CP0_TCSTATUS -		andi	v1, TCSTATUS_IXMT -		bnez	v1, 0f - -/* - * We'd like to detect any IPIs queued in the tiny window - * above and request an software interrupt to service them - * when we ERET. - * - * Computing the offset into the IPIQ array of the executing - * TC's IPI queue in-line would be tedious.  We use part of - * the TCContext register to hold 16 bits of offset that we - * can add in-line to find the queue head. - */ -		mfc0	v0, CP0_TCCONTEXT -		la	a2, IPIQ -		srl	v0, v0, 16 -		addu	a2, a2, v0 -		LONG_L	v0, 0(a2) -		beqz	v0, 0f -/* - * If we have a queue, provoke dispatch within the VPE by setting C_SW1 - */ -		mfc0	v0, CP0_CAUSE -		ori	v0, v0, C_SW1 -		mtc0	v0, CP0_CAUSE -0: -		/* -		 * This test should really never branch but -		 * let's be prudent here.  Having atomized -		 * the shared register modifications, we can -		 * now EVPE, and must do so before interrupts -		 * are potentially re-enabled. -		 */ -		andi	a1, a1, MVPCONTROL_EVP -		beqz	a1, 1f -		evpe -1: -		/* We know that TCStatua.IXMT should be set from above */ -		xori	a0, a0, TCSTATUS_IXMT -		or	a0, a0, v1 -		mtc0	a0, CP0_TCSTATUS -		_ehb - -		.set	mips0 -#endif /* CONFIG_MIPS_MT_SMTC */  		LONG_L	v1, PT_EPC(sp)  		MTC0	v1, CP0_EPC  		LONG_L	$31, PT_R31(sp) @@ -448,7 +332,7 @@  		.macro	RESTORE_SP_AND_RET  		LONG_L	sp, PT_R29(sp) -		.set	mips3 +		.set	arch=r4000  		eret  		.set	mips0  		.endm @@ -480,33 +364,11 @@   * Set cp0 enable bit as sign that we're running on the kernel stack   */  		.macro	CLI -#if !defined(CONFIG_MIPS_MT_SMTC)  		mfc0	t0, CP0_STATUS  		li	t1, ST0_CU0 | STATMASK  		or	t0, t1  		xori	t0, STATMASK  		mtc0	t0, CP0_STATUS -#else /* CONFIG_MIPS_MT_SMTC */ -		/* -		 * For SMTC, we need to set privilege -		 * and disable interrupts only for the -		 * current TC, using the TCStatus register. -		 */ -		mfc0	t0, CP0_TCSTATUS -		/* Fortunately CU 0 is in the same place in both registers */ -		/* Set TCU0, TMX, TKSU (for later inversion) and IXMT */ -		li	t1, ST0_CU0 | 0x08001c00 -		or	t0, t1 -		/* Clear TKSU, leave IXMT */ -		xori	t0, 0x00001800 -		mtc0	t0, CP0_TCSTATUS -		_ehb -		/* We need to leave the global IE bit set, but clear EXL...*/ -		mfc0	t0, CP0_STATUS -		ori	t0, ST0_EXL | ST0_ERL -		xori	t0, ST0_EXL | ST0_ERL -		mtc0	t0, CP0_STATUS -#endif /* CONFIG_MIPS_MT_SMTC */  		irq_disable_hazard  		.endm @@ -515,35 +377,11 @@   * Set cp0 enable bit as sign that we're running on the kernel stack   */  		.macro	STI -#if !defined(CONFIG_MIPS_MT_SMTC)  		mfc0	t0, CP0_STATUS  		li	t1, ST0_CU0 | STATMASK  		or	t0, t1  		xori	t0, STATMASK & ~1  		mtc0	t0, CP0_STATUS -#else /* CONFIG_MIPS_MT_SMTC */ -		/* -		 * For SMTC, we need to set privilege -		 * and enable interrupts only for the -		 * current TC, using the TCStatus register. -		 */ -		_ehb -		mfc0	t0, CP0_TCSTATUS -		/* Fortunately CU 0 is in the same place in both registers */ -		/* Set TCU0, TKSU (for later inversion) and IXMT */ -		li	t1, ST0_CU0 | 0x08001c00 -		or	t0, t1 -		/* Clear TKSU *and* IXMT */ -		xori	t0, 0x00001c00 -		mtc0	t0, CP0_TCSTATUS -		_ehb -		/* We need to leave the global IE bit set, but clear EXL...*/ -		mfc0	t0, CP0_STATUS -		ori	t0, ST0_EXL -		xori	t0, ST0_EXL -		mtc0	t0, CP0_STATUS -		/* irq_enable_hazard below should expand to EHB for 24K/34K cpus */ -#endif /* CONFIG_MIPS_MT_SMTC */  		irq_enable_hazard  		.endm @@ -553,32 +391,6 @@   * Set cp0 enable bit as sign that we're running on the kernel stack   */  		.macro	KMODE -#ifdef CONFIG_MIPS_MT_SMTC -		/* -		 * This gets baroque in SMTC.  We want to -		 * protect the non-atomic clearing of EXL -		 * with DMT/EMT, but we don't want to take -		 * an interrupt while DMT is still in effect. -		 */ - -		/* KMODE gets invoked from both reorder and noreorder code */ -		.set	push -		.set	mips32r2 -		.set	noreorder -		mfc0	v0, CP0_TCSTATUS -		andi	v1, v0, TCSTATUS_IXMT -		ori	v0, TCSTATUS_IXMT -		mtc0	v0, CP0_TCSTATUS -		_ehb -		DMT	2				# dmt	v0 -		/* -		 * We don't know a priori if ra is "live" -		 */ -		move	t0, ra -		jal	mips_ihb -		nop	/* delay slot */ -		move	ra, t0 -#endif /* CONFIG_MIPS_MT_SMTC */  		mfc0	t0, CP0_STATUS  		li	t1, ST0_CU0 | (STATMASK & ~1)  #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) @@ -589,25 +401,6 @@  		or	t0, t1  		xori	t0, STATMASK & ~1  		mtc0	t0, CP0_STATUS -#ifdef CONFIG_MIPS_MT_SMTC -		_ehb -		andi	v0, v0, VPECONTROL_TE -		beqz	v0, 2f -		nop	/* delay slot */ -		emt -2: -		mfc0	v0, CP0_TCSTATUS -		/* Clear IXMT, then OR in previous value */ -		ori	v0, TCSTATUS_IXMT -		xori	v0, TCSTATUS_IXMT -		or	v0, v1, v0 -		mtc0	v0, CP0_TCSTATUS -		/* -		 * irq_disable_hazard below should expand to EHB -		 * on 24K/34K CPUS -		 */ -		.set pop -#endif /* CONFIG_MIPS_MT_SMTC */  		irq_disable_hazard  		.endm  | 
