diff options
Diffstat (limited to 'arch/mips/kernel/octeon_switch.S')
| -rw-r--r-- | arch/mips/kernel/octeon_switch.S | 171 | 
1 files changed, 94 insertions, 77 deletions
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index dd18b26a358..f6547680c81 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S @@ -4,34 +4,21 @@   * for more details.   *   * Copyright (C) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1996 David S. Miller (davem@davemloft.net)   * Copyright (C) 1994, 1995, 1996, by Andreas Busse   * Copyright (C) 1999 Silicon Graphics, Inc.   * 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/page.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) + *		       struct thread_info *next_ti, int usedfpu)   */  	.align	7  	LEAF(resume) @@ -41,6 +28,34 @@  	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) @@ -70,7 +85,7 @@  1:  #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0  	/* Check if we need to store CVMSEG state */ -	mfc0	t0, $11,7 	/* CvmMemCtl */ +	mfc0	t0, $11,7	/* CvmMemCtl */  	bbit0	t0, 6, 3f	/* Is user access enabled? */  	/* Store the CVMSEG state */ @@ -78,8 +93,8 @@  	andi	t0, 0x3f  	/* Multiply * (cache line size/sizeof(long)/2) */  	sll	t0, 7-LONGLOG-1 -	li	t1, -32768 	/* Base address of CVMSEG */ -	LONG_ADDI t2, a0, THREAD_CVMSEG	/* Where to store CVMSEG to */ +	li	t1, -32768	/* Base address of CVMSEG */ +	LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */  	synciobdma  2:  	.set noreorder @@ -90,15 +105,22 @@  	LONG_S	t8, 0(t2)	/* Store CVMSEG to thread storage */  	LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */  	bnez	t0, 2b		/* Loop until we've copied it all */ -	 LONG_S	t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */ +	 LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */  	.set reorder  	/* Disable access to CVMSEG */ -	mfc0	t0, $11,7 	/* CvmMemCtl */ +	mfc0	t0, $11,7	/* CvmMemCtl */  	xori	t0, t0, 0x40	/* Bit 6 is CVMSEG user enable */ -	mtc0	t0, $11,7 	/* CvmMemCtl */ +	mtc0	t0, $11,7	/* CvmMemCtl */  #endif  3: + +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) +	PTR_LA	t8, __stack_chk_guard +	LONG_L	t9, TASK_STACK_CANARY(a1) +	LONG_S	t9, 0(t8) +#endif +  	/*  	 * The order of restoring the registers takes care of the race  	 * updating $28, $29 and kernelsp without disabling ints. @@ -106,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? */ @@ -134,7 +151,7 @@  	dmfc0	t9, $9,7	/* CvmCtl register. */ -        /* Save the COP2 CRC state */ +	/* Save the COP2 CRC state */  	dmfc2	t0, 0x0201  	dmfc2	t1, 0x0202  	dmfc2	t2, 0x0200 @@ -150,30 +167,30 @@  	sd	t0, OCTEON_CP2_LLM_DAT(a0)  	sd	t1, OCTEON_CP2_LLM_DAT+8(a0) -1:      bbit1	t9, 26, 3f	/* done if CvmCtl[NOCRYPTO] set */ +1:	bbit1	t9, 26, 3f	/* done if CvmCtl[NOCRYPTO] set */  	/* Save the COP2 crypto state */ -        /* this part is mostly common to both pass 1 and later revisions */ -	dmfc2 	t0, 0x0084 -	dmfc2 	t1, 0x0080 -	dmfc2 	t2, 0x0081 -	dmfc2 	t3, 0x0082 +	/* this part is mostly common to both pass 1 and later revisions */ +	dmfc2	t0, 0x0084 +	dmfc2	t1, 0x0080 +	dmfc2	t2, 0x0081 +	dmfc2	t3, 0x0082  	sd	t0, OCTEON_CP2_3DES_IV(a0) -	dmfc2 	t0, 0x0088 +	dmfc2	t0, 0x0088  	sd	t1, OCTEON_CP2_3DES_KEY(a0) -	dmfc2 	t1, 0x0111                      /* only necessary for pass 1 */ +	dmfc2	t1, 0x0111			/* only necessary for pass 1 */  	sd	t2, OCTEON_CP2_3DES_KEY+8(a0) -	dmfc2 	t2, 0x0102 +	dmfc2	t2, 0x0102  	sd	t3, OCTEON_CP2_3DES_KEY+16(a0) -	dmfc2 	t3, 0x0103 +	dmfc2	t3, 0x0103  	sd	t0, OCTEON_CP2_3DES_RESULT(a0) -	dmfc2 	t0, 0x0104 -	sd	t1, OCTEON_CP2_AES_INP0(a0)     /* only necessary for pass 1 */ -	dmfc2 	t1, 0x0105 +	dmfc2	t0, 0x0104 +	sd	t1, OCTEON_CP2_AES_INP0(a0)	/* only necessary for pass 1 */ +	dmfc2	t1, 0x0105  	sd	t2, OCTEON_CP2_AES_IV(a0)  	dmfc2	t2, 0x0106  	sd	t3, OCTEON_CP2_AES_IV+8(a0) -	dmfc2 	t3, 0x0107 +	dmfc2	t3, 0x0107  	sd	t0, OCTEON_CP2_AES_KEY(a0)  	dmfc2	t0, 0x0110  	sd	t1, OCTEON_CP2_AES_KEY+8(a0) @@ -181,7 +198,7 @@  	sd	t2, OCTEON_CP2_AES_KEY+16(a0)  	dmfc2	t2, 0x0101  	sd	t3, OCTEON_CP2_AES_KEY+24(a0) -	mfc0	t3, $15,0 	/* Get the processor ID register */ +	mfc0	t3, $15,0	/* Get the processor ID register */  	sd	t0, OCTEON_CP2_AES_KEYLEN(a0)  	li	t0, 0x000d0000	/* This is the processor ID of Octeon Pass1 */  	sd	t1, OCTEON_CP2_AES_RESULT(a0) @@ -189,7 +206,7 @@  	/* Skip to the Pass1 version of the remainder of the COP2 state */  	beq	t3, t0, 2f -        /* the non-pass1 state when !CvmCtl[NOCRYPTO] */ +	/* the non-pass1 state when !CvmCtl[NOCRYPTO] */  	dmfc2	t1, 0x0240  	dmfc2	t2, 0x0241  	dmfc2	t3, 0x0242 @@ -215,7 +232,7 @@  	sd	t2, OCTEON_CP2_HSH_DATW+72(a0)  	dmfc2	t2, 0x024D  	sd	t3, OCTEON_CP2_HSH_DATW+80(a0) -	dmfc2 	t3, 0x024E +	dmfc2	t3, 0x024E  	sd	t0, OCTEON_CP2_HSH_DATW+88(a0)  	dmfc2	t0, 0x0250  	sd	t1, OCTEON_CP2_HSH_DATW+96(a0) @@ -233,9 +250,9 @@  	sd	t3, OCTEON_CP2_HSH_IVW+24(a0)  	dmfc2	t3, 0x0257  	sd	t0, OCTEON_CP2_HSH_IVW+32(a0) -	dmfc2 	t0, 0x0258 +	dmfc2	t0, 0x0258  	sd	t1, OCTEON_CP2_HSH_IVW+40(a0) -	dmfc2 	t1, 0x0259 +	dmfc2	t1, 0x0259  	sd	t2, OCTEON_CP2_HSH_IVW+48(a0)  	dmfc2	t2, 0x025E  	sd	t3, OCTEON_CP2_HSH_IVW+56(a0) @@ -248,7 +265,7 @@  	sd	t0, OCTEON_CP2_GFM_RESULT+8(a0)  	jr	ra -2:      /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */ +2:	/* pass 1 special stuff when !CvmCtl[NOCRYPTO] */  	dmfc2	t3, 0x0040  	dmfc2	t0, 0x0041  	dmfc2	t1, 0x0042 @@ -270,7 +287,7 @@  	sd	t3, OCTEON_CP2_HSH_IVW+8(a0)  	sd	t0, OCTEON_CP2_HSH_IVW+16(a0) -3:      /* pass 1 or CvmCtl[NOCRYPTO] set */ +3:	/* pass 1 or CvmCtl[NOCRYPTO] set */  	jr	ra  	END(octeon_cop2_save) @@ -281,19 +298,19 @@  	.set push  	.set noreorder  	LEAF(octeon_cop2_restore) -        /* First cache line was prefetched before the call */ -        pref    4,  128(a0) +	/* First cache line was prefetched before the call */ +	pref	4,  128(a0)  	dmfc0	t9, $9,7	/* CvmCtl register. */ -        pref    4,  256(a0) +	pref	4,  256(a0)  	ld	t0, OCTEON_CP2_CRC_IV(a0) -        pref    4,  384(a0) +	pref	4,  384(a0)  	ld	t1, OCTEON_CP2_CRC_LENGTH(a0)  	ld	t2, OCTEON_CP2_CRC_POLY(a0)  	/* Restore the COP2 CRC state */  	dmtc2	t0, 0x0201 -	dmtc2 	t1, 0x1202 +	dmtc2	t1, 0x1202  	bbit1	t9, 28, 2f	/* Skip LLM if CvmCtl[NODFA_CP2] is set */  	 dmtc2	t2, 0x4200 @@ -311,19 +328,19 @@  	ld	t0, OCTEON_CP2_3DES_IV(a0)  	ld	t1, OCTEON_CP2_3DES_KEY(a0)  	ld	t2, OCTEON_CP2_3DES_KEY+8(a0) -	dmtc2 	t0, 0x0084 +	dmtc2	t0, 0x0084  	ld	t0, OCTEON_CP2_3DES_KEY+16(a0) -	dmtc2 	t1, 0x0080 +	dmtc2	t1, 0x0080  	ld	t1, OCTEON_CP2_3DES_RESULT(a0) -	dmtc2 	t2, 0x0081 +	dmtc2	t2, 0x0081  	ld	t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */  	dmtc2	t0, 0x0082  	ld	t0, OCTEON_CP2_AES_IV(a0) -	dmtc2 	t1, 0x0098 +	dmtc2	t1, 0x0098  	ld	t1, OCTEON_CP2_AES_IV+8(a0) -	dmtc2 	t2, 0x010A                  /* only really needed for pass 1 */ +	dmtc2	t2, 0x010A		    /* only really needed for pass 1 */  	ld	t2, OCTEON_CP2_AES_KEY(a0) -	dmtc2 	t0, 0x0102 +	dmtc2	t0, 0x0102  	ld	t0, OCTEON_CP2_AES_KEY+8(a0)  	dmtc2	t1, 0x0103  	ld	t1, OCTEON_CP2_AES_KEY+16(a0) @@ -335,14 +352,14 @@  	ld	t1, OCTEON_CP2_AES_RESULT(a0)  	dmtc2	t2, 0x0107  	ld	t2, OCTEON_CP2_AES_RESULT+8(a0) -	mfc0	t3, $15,0 	/* Get the processor ID register */ +	mfc0	t3, $15,0	/* Get the processor ID register */  	dmtc2	t0, 0x0110  	li	t0, 0x000d0000	/* This is the processor ID of Octeon Pass1 */  	dmtc2	t1, 0x0100  	bne	t0, t3, 3f	/* Skip the next stuff for non-pass1 */  	 dmtc2	t2, 0x0101 -        /* this code is specific for pass 1 */ +	/* this code is specific for pass 1 */  	ld	t0, OCTEON_CP2_HSH_DATW(a0)  	ld	t1, OCTEON_CP2_HSH_DATW+8(a0)  	ld	t2, OCTEON_CP2_HSH_DATW+16(a0) @@ -362,10 +379,10 @@  	ld	t0, OCTEON_CP2_HSH_IVW+16(a0)  	dmtc2	t1, 0x0048  	dmtc2	t2, 0x0049 -        b done_restore   /* unconditional branch */ +	b done_restore	 /* unconditional branch */  	 dmtc2	t0, 0x004A -3:      /* this is post-pass1 code */ +3:	/* this is post-pass1 code */  	ld	t2, OCTEON_CP2_HSH_DATW(a0)  	ld	t0, OCTEON_CP2_HSH_DATW+8(a0)  	ld	t1, OCTEON_CP2_HSH_DATW+16(a0) @@ -434,7 +451,7 @@ done_restore:   * sp is assumed to point to a struct pt_regs   *   * NOTE: This is called in SAVE_SOME in stackframe.h. It can only - *       safely modify k0 and k1. + *	 safely modify k0 and k1.   */  	.align	7  	.set push @@ -447,14 +464,14 @@ done_restore:  	/* Save the multiplier state */  	v3mulu	k0, $0, $0  	v3mulu	k1, $0, $0 -	sd	k0, PT_MTP(sp)        /* PT_MTP    has P0 */ +	sd	k0, PT_MTP(sp)	      /* PT_MTP	   has P0 */  	v3mulu	k0, $0, $0  	sd	k1, PT_MTP+8(sp)      /* PT_MTP+8  has P1 */  	ori	k1, $0, 1  	v3mulu	k1, k1, $0  	sd	k0, PT_MTP+16(sp)     /* PT_MTP+16 has P2 */  	v3mulu	k0, $0, $0 -	sd	k1, PT_MPL(sp)        /* PT_MPL    has MPL0 */ +	sd	k1, PT_MPL(sp)	      /* PT_MPL	   has MPL0 */  	v3mulu	k1, $0, $0  	sd	k0, PT_MPL+8(sp)      /* PT_MPL+8  has MPL1 */  	jr	ra @@ -476,19 +493,19 @@ done_restore:  	.set noreorder  	LEAF(octeon_mult_restore)  	dmfc0	k1, $9,7		/* CvmCtl register. */ -	ld	v0, PT_MPL(sp)        	/* MPL0 */ -	ld	v1, PT_MPL+8(sp)      	/* MPL1 */ -	ld	k0, PT_MPL+16(sp)     	/* MPL2 */ +	ld	v0, PT_MPL(sp)		/* MPL0 */ +	ld	v1, PT_MPL+8(sp)	/* MPL1 */ +	ld	k0, PT_MPL+16(sp)	/* MPL2 */  	bbit1	k1, 27, 1f		/* Skip CvmCtl[NOMUL] */  	/* Normally falls through, so no time wasted here */  	nop  	/* Restore the multiplier state */ -	ld	k1, PT_MTP+16(sp)     	/* P2 */ +	ld	k1, PT_MTP+16(sp)	/* P2 */  	MTM0	v0			/* MPL0 */  	ld	v0, PT_MTP+8(sp)	/* P1 */  	MTM1	v1			/* MPL1 */ -	ld	v1, PT_MTP(sp)   	/* P0 */ +	ld	v1, PT_MTP(sp)		/* P0 */  	MTM2	k0			/* MPL2 */  	MTP2	k1			/* P2 */  	MTP1	v0			/* P1 */  | 
