Skip to content

Commit c58ce2b

Browse files
Tiejun Chenozbenh
authored andcommitted
ppc64: fix missing to check all bits of _TIF_USER_WORK_MASK in preempt
In entry_64.S version of ret_from_except_lite, you'll notice that in the !preempt case, after we've checked MSR_PR we test for any TIF flag in _TIF_USER_WORK_MASK to decide whether to go to do_work or not. However, in the preempt case, we do a convoluted trick to test SIGPENDING only if PR was set and always test NEED_RESCHED ... but we forget to test any other bit of _TIF_USER_WORK_MASK !!! So that means that with preempt, we completely fail to test for things like single step, syscall tracing, etc... This should be fixed as the following path: - Test PR. If not set, go to resume_kernel, else continue. - If go resume_kernel, to do that original do_work. - If else, then always test for _TIF_USER_WORK_MASK to decide to do that original user_work, else restore directly. Signed-off-by: Tiejun Chen <tiejun.chen@windriver.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
1 parent 82b2521 commit c58ce2b

File tree

1 file changed

+40
-57
lines changed

1 file changed

+40
-57
lines changed

arch/powerpc/kernel/entry_64.S

Lines changed: 40 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -558,27 +558,54 @@ _GLOBAL(ret_from_except_lite)
558558
mtmsrd r10,1 /* Update machine state */
559559
#endif /* CONFIG_PPC_BOOK3E */
560560

561-
#ifdef CONFIG_PREEMPT
562561
clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */
563-
li r0,_TIF_NEED_RESCHED /* bits to check */
564562
ld r3,_MSR(r1)
565563
ld r4,TI_FLAGS(r9)
566-
/* Move MSR_PR bit in r3 to _TIF_SIGPENDING position in r0 */
567-
rlwimi r0,r3,32+TIF_SIGPENDING-MSR_PR_LG,_TIF_SIGPENDING
568-
and. r0,r4,r0 /* check NEED_RESCHED and maybe SIGPENDING */
569-
bne do_work
570-
571-
#else /* !CONFIG_PREEMPT */
572-
ld r3,_MSR(r1) /* Returning to user mode? */
573564
andi. r3,r3,MSR_PR
574-
beq restore /* if not, just restore regs and return */
565+
beq resume_kernel
575566

576567
/* Check current_thread_info()->flags */
568+
andi. r0,r4,_TIF_USER_WORK_MASK
569+
beq restore
570+
571+
andi. r0,r4,_TIF_NEED_RESCHED
572+
beq 1f
573+
bl .restore_interrupts
574+
bl .schedule
575+
b .ret_from_except_lite
576+
577+
1: bl .save_nvgprs
578+
bl .restore_interrupts
579+
addi r3,r1,STACK_FRAME_OVERHEAD
580+
bl .do_notify_resume
581+
b .ret_from_except
582+
583+
resume_kernel:
584+
#ifdef CONFIG_PREEMPT
585+
/* Check if we need to preempt */
586+
andi. r0,r4,_TIF_NEED_RESCHED
587+
beq+ restore
588+
/* Check that preempt_count() == 0 and interrupts are enabled */
589+
lwz r8,TI_PREEMPT(r9)
590+
cmpwi cr1,r8,0
591+
ld r0,SOFTE(r1)
592+
cmpdi r0,0
593+
crandc eq,cr1*4+eq,eq
594+
bne restore
595+
596+
/*
597+
* Here we are preempting the current task. We want to make
598+
* sure we are soft-disabled first
599+
*/
600+
SOFT_DISABLE_INTS(r3,r4)
601+
1: bl .preempt_schedule_irq
602+
603+
/* Re-test flags and eventually loop */
577604
clrrdi r9,r1,THREAD_SHIFT
578605
ld r4,TI_FLAGS(r9)
579-
andi. r0,r4,_TIF_USER_WORK_MASK
580-
bne do_work
581-
#endif /* !CONFIG_PREEMPT */
606+
andi. r0,r4,_TIF_NEED_RESCHED
607+
bne 1b
608+
#endif /* CONFIG_PREEMPT */
582609

583610
.globl fast_exc_return_irq
584611
fast_exc_return_irq:
@@ -759,50 +786,6 @@ restore_check_irq_replay:
759786
#endif /* CONFIG_PPC_BOOK3E */
760787
1: b .ret_from_except /* What else to do here ? */
761788

762-
763-
764-
3:
765-
do_work:
766-
#ifdef CONFIG_PREEMPT
767-
andi. r0,r3,MSR_PR /* Returning to user mode? */
768-
bne user_work
769-
/* Check that preempt_count() == 0 and interrupts are enabled */
770-
lwz r8,TI_PREEMPT(r9)
771-
cmpwi cr1,r8,0
772-
ld r0,SOFTE(r1)
773-
cmpdi r0,0
774-
crandc eq,cr1*4+eq,eq
775-
bne restore
776-
777-
/*
778-
* Here we are preempting the current task. We want to make
779-
* sure we are soft-disabled first
780-
*/
781-
SOFT_DISABLE_INTS(r3,r4)
782-
1: bl .preempt_schedule_irq
783-
784-
/* Re-test flags and eventually loop */
785-
clrrdi r9,r1,THREAD_SHIFT
786-
ld r4,TI_FLAGS(r9)
787-
andi. r0,r4,_TIF_NEED_RESCHED
788-
bne 1b
789-
b restore
790-
791-
user_work:
792-
#endif /* CONFIG_PREEMPT */
793-
794-
andi. r0,r4,_TIF_NEED_RESCHED
795-
beq 1f
796-
bl .restore_interrupts
797-
bl .schedule
798-
b .ret_from_except_lite
799-
800-
1: bl .save_nvgprs
801-
bl .restore_interrupts
802-
addi r3,r1,STACK_FRAME_OVERHEAD
803-
bl .do_notify_resume
804-
b .ret_from_except
805-
806789
unrecov_restore:
807790
addi r3,r1,STACK_FRAME_OVERHEAD
808791
bl .unrecoverable_exception

0 commit comments

Comments
 (0)