diff options
Diffstat (limited to 'arch/powerpc/kernel/entry_64.S')
| -rw-r--r-- | arch/powerpc/kernel/entry_64.S | 97 | 
1 files changed, 40 insertions, 57 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index ed1718feb9d..5971c85df13 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -558,27 +558,54 @@ _GLOBAL(ret_from_except_lite)  	mtmsrd	r10,1		  /* Update machine state */  #endif /* CONFIG_PPC_BOOK3E */ -#ifdef CONFIG_PREEMPT  	clrrdi	r9,r1,THREAD_SHIFT	/* current_thread_info() */ -	li	r0,_TIF_NEED_RESCHED	/* bits to check */  	ld	r3,_MSR(r1)  	ld	r4,TI_FLAGS(r9) -	/* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */ -	rlwimi	r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING -	and.	r0,r4,r0	/* check NEED_RESCHED and maybe SIGPENDING */ -	bne	do_work - -#else /* !CONFIG_PREEMPT */ -	ld	r3,_MSR(r1)	/* Returning to user mode? */  	andi.	r3,r3,MSR_PR -	beq	restore		/* if not, just restore regs and return */ +	beq	resume_kernel  	/* Check current_thread_info()->flags */ +	andi.	r0,r4,_TIF_USER_WORK_MASK +	beq	restore + +	andi.	r0,r4,_TIF_NEED_RESCHED +	beq	1f +	bl	.restore_interrupts +	bl	.schedule +	b	.ret_from_except_lite + +1:	bl	.save_nvgprs +	bl	.restore_interrupts +	addi	r3,r1,STACK_FRAME_OVERHEAD +	bl	.do_notify_resume +	b	.ret_from_except + +resume_kernel: +#ifdef CONFIG_PREEMPT +	/* Check if we need to preempt */ +	andi.	r0,r4,_TIF_NEED_RESCHED +	beq+	restore +	/* Check that preempt_count() == 0 and interrupts are enabled */ +	lwz	r8,TI_PREEMPT(r9) +	cmpwi	cr1,r8,0 +	ld	r0,SOFTE(r1) +	cmpdi	r0,0 +	crandc	eq,cr1*4+eq,eq +	bne	restore + +	/* +	 * Here we are preempting the current task. We want to make +	 * sure we are soft-disabled first +	 */ +	SOFT_DISABLE_INTS(r3,r4) +1:	bl	.preempt_schedule_irq + +	/* Re-test flags and eventually loop */  	clrrdi	r9,r1,THREAD_SHIFT  	ld	r4,TI_FLAGS(r9) -	andi.	r0,r4,_TIF_USER_WORK_MASK -	bne	do_work -#endif /* !CONFIG_PREEMPT */ +	andi.	r0,r4,_TIF_NEED_RESCHED +	bne	1b +#endif /* CONFIG_PREEMPT */  	.globl	fast_exc_return_irq  fast_exc_return_irq: @@ -759,50 +786,6 @@ restore_check_irq_replay:  #endif /* CONFIG_PPC_BOOK3E */  1:	b	.ret_from_except /* What else to do here ? */ - - -3: -do_work: -#ifdef CONFIG_PREEMPT -	andi.	r0,r3,MSR_PR	/* Returning to user mode? */ -	bne	user_work -	/* Check that preempt_count() == 0 and interrupts are enabled */ -	lwz	r8,TI_PREEMPT(r9) -	cmpwi	cr1,r8,0 -	ld	r0,SOFTE(r1) -	cmpdi	r0,0 -	crandc	eq,cr1*4+eq,eq -	bne	restore - -	/* -	 * Here we are preempting the current task. We want to make -	 * sure we are soft-disabled first -	 */ -	SOFT_DISABLE_INTS(r3,r4) -1:	bl	.preempt_schedule_irq - -	/* Re-test flags and eventually loop */ -	clrrdi	r9,r1,THREAD_SHIFT -	ld	r4,TI_FLAGS(r9) -	andi.	r0,r4,_TIF_NEED_RESCHED -	bne	1b -	b	restore - -user_work: -#endif /* CONFIG_PREEMPT */ - -	andi.	r0,r4,_TIF_NEED_RESCHED -	beq	1f -	bl	.restore_interrupts -	bl	.schedule -	b	.ret_from_except_lite - -1:	bl	.save_nvgprs -	bl	.restore_interrupts -	addi	r3,r1,STACK_FRAME_OVERHEAD -	bl	.do_notify_resume -	b	.ret_from_except -  unrecov_restore:  	addi	r3,r1,STACK_FRAME_OVERHEAD  	bl	.unrecoverable_exception  |