diff options
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64s.S')
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 38 | 
1 files changed, 27 insertions, 11 deletions
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index a8a5361fb70..200afa5bcfb 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -74,13 +74,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)				\  	mflr	r10 ;						\  	ld	r12,PACAKBASE(r13) ; 				\  	LOAD_HANDLER(r12, system_call_entry_direct) ;		\ -	mtlr	r12 ;						\ +	mtctr	r12 ;						\  	mfspr	r12,SPRN_SRR1 ;					\  	/* Re-use of r13... No spare regs to do this */	\  	li	r13,MSR_RI ;					\  	mtmsrd 	r13,1 ;						\  	GET_PACA(r13) ;	/* get r13 back */			\ -	blr ; +	bctr ;  #else  	/* We can branch directly */  #define SYSCALL_PSERIES_2_DIRECT				\ @@ -1452,20 +1452,36 @@ do_ste_alloc:  _GLOBAL(do_stab_bolted)  	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */  	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */ +	mfspr	r11,SPRN_DAR			/* ea */ +	/* +	 * check for bad kernel/user address +	 * (ea & ~REGION_MASK) >= PGTABLE_RANGE +	 */ +	rldicr. r9,r11,4,(63 - 46 - 4) +	li	r9,0	/* VSID = 0 for bad address */ +	bne-	0f + +	/* +	 * Calculate VSID: +	 * This is the kernel vsid, we take the top for context from +	 * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1 +	 * Here we know that (ea >> 60) == 0xc +	 */ +	lis	r9,(MAX_USER_CONTEXT + 1)@ha +	addi	r9,r9,(MAX_USER_CONTEXT + 1)@l + +	srdi	r10,r11,SID_SHIFT +	rldimi  r10,r9,ESID_BITS,0 /* proto vsid */ +	ASM_VSID_SCRAMBLE(r10, r9, 256M) +	rldic	r9,r10,12,16	/* r9 = vsid << 12 */ + +0:  	/* Hash to the primary group */  	ld	r10,PACASTABVIRT(r13) -	mfspr	r11,SPRN_DAR -	srdi	r11,r11,28 +	srdi	r11,r11,SID_SHIFT  	rldimi	r10,r11,7,52	/* r10 = first ste of the group */ -	/* Calculate VSID */ -	/* This is a kernel address, so protovsid = ESID | 1 << 37 */ -	li	r9,0x1 -	rldimi  r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0 -	ASM_VSID_SCRAMBLE(r11, r9, 256M) -	rldic	r9,r11,12,16	/* r9 = vsid << 12 */ -  	/* Search the primary group for a free entry */  1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/  	andi.	r11,r11,0x80  |