diff options
Diffstat (limited to 'arch/mips/kernel/octeon_switch.S')
| -rw-r--r-- | arch/mips/kernel/octeon_switch.S | 86 | 
1 files changed, 62 insertions, 24 deletions
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index 4204d76af85..f6547680c81 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S @@ -10,24 +10,12 @@   * Copyright (C) 2000 MIPS Technologies, Inc.   *    written by Carsten Langgaard, carstenl@mips.com   */ -#include <asm/asm.h> -#include <asm/cachectl.h> -#include <asm/fpregdef.h> -#include <asm/mipsregs.h> -#include <asm/asm-offsets.h> -#include <asm/pgtable-bits.h> -#include <asm/regdef.h> -#include <asm/stackframe.h> -#include <asm/thread_info.h> - -#include <asm/asmmacro.h> - -/* - * Offset to the current process status flags, the first 32 bytes of the - * stack are not used. - */ -#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) +#define USE_ALTERNATE_RESUME_IMPL 1 +	.set push +	.set arch=mips64r2 +#include "r4k_switch.S" +	.set pop  /*   * task_struct *resume(task_struct *prev, task_struct *next,   *		       struct thread_info *next_ti, int usedfpu) @@ -40,6 +28,61 @@  	cpu_save_nonscratch a0  	LONG_S	ra, THREAD_REG31(a0) +	/* +	 * check if we need to save FPU registers +	 */ +	PTR_L	t3, TASK_THREAD_INFO(a0) +	LONG_L	t0, TI_FLAGS(t3) +	li	t1, _TIF_USEDFPU +	and	t2, t0, t1 +	beqz	t2, 1f +	nor	t1, zero, t1 + +	and	t0, t0, t1 +	LONG_S	t0, TI_FLAGS(t3) + +	/* +	 * clear saved user stack CU1 bit +	 */ +	LONG_L	t0, ST_OFF(t3) +	li	t1, ~ST0_CU1 +	and	t0, t0, t1 +	LONG_S	t0, ST_OFF(t3) + +	.set push +	.set arch=mips64r2 +	fpu_save_double a0 t0 t1		# c0_status passed in t0 +						# clobbers t1 +	.set pop +1: + +	/* check if we need to save COP2 registers */ +	PTR_L	t2, TASK_THREAD_INFO(a0) +	LONG_L	t0, ST_OFF(t2) +	bbit0	t0, 30, 1f + +	/* Disable COP2 in the stored process state */ +	li	t1, ST0_CU2 +	xor	t0, t1 +	LONG_S	t0, ST_OFF(t2) + +	/* Enable COP2 so we can save it */ +	mfc0	t0, CP0_STATUS +	or	t0, t1 +	mtc0	t0, CP0_STATUS + +	/* Save COP2 */ +	daddu	a0, THREAD_CP2 +	jal octeon_cop2_save +	dsubu	a0, THREAD_CP2 + +	/* Disable COP2 now that we are done */ +	mfc0	t0, CP0_STATUS +	li	t1, ST0_CU2 +	xor	t0, t1 +	mtc0	t0, CP0_STATUS + +1:  #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0  	/* Check if we need to store CVMSEG state */  	mfc0	t0, $11,7	/* CvmMemCtl */ @@ -73,7 +116,7 @@  3:  #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) -	PTR_L	t8, __stack_chk_guard +	PTR_LA	t8, __stack_chk_guard  	LONG_L	t9, TASK_STACK_CANARY(a1)  	LONG_S	t9, 0(t8)  #endif @@ -85,12 +128,7 @@  	move	$28, a2  	cpu_restore_nonscratch a1 -#if (_THREAD_SIZE - 32) < 0x8000 -	PTR_ADDIU	t0, $28, _THREAD_SIZE - 32 -#else -	PTR_LI		t0, _THREAD_SIZE - 32 -	PTR_ADDU	t0, $28 -#endif +	PTR_ADDU	t0, $28, _THREAD_SIZE - 32  	set_saved_sp	t0, t1, t2  	mfc0	t1, CP0_STATUS		/* Do we really need this? */  | 
