microblaze: fix handling of multiple pending signals
We need to keep building sigframes until no pending signals remain. Wrap do_notify_resume() calls into loops; do _not_ allow syscall restart logics to trigger after the first iteration. Incidentally, comments about pending signals that should (somehow) be in r18 are pure BS. Doesn't work that way and cannot work that way, sorry... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
14203e19cb
commit
e9f9252667
|
@ -124,6 +124,7 @@ ret_from_intr:
|
|||
lwi r11, r1, PT_MODE
|
||||
bneid r11, no_intr_resched
|
||||
|
||||
3:
|
||||
lwi r6, r31, TS_THREAD_INFO /* get thread info */
|
||||
lwi r19, r6, TI_FLAGS /* get flags in thread info */
|
||||
/* do an extra work if any bits are set */
|
||||
|
@ -132,11 +133,13 @@ ret_from_intr:
|
|||
beqi r11, 1f
|
||||
bralid r15, schedule
|
||||
nop
|
||||
bri 3b
|
||||
1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||
beqid r11, no_intr_resched
|
||||
addk r5, r1, r0
|
||||
bralid r15, do_notify_resume
|
||||
addk r6, r0, r0
|
||||
bri 3b
|
||||
|
||||
no_intr_resched:
|
||||
/* Disable interrupts, we are now committed to the state restore */
|
||||
|
@ -486,18 +489,24 @@ ENTRY(ret_from_kernel_thread)
|
|||
work_pending:
|
||||
lwi r11, r1, PT_MODE
|
||||
bneid r11, 2f
|
||||
3:
|
||||
enable_irq
|
||||
|
||||
andi r11, r19, _TIF_NEED_RESCHED
|
||||
beqi r11, 1f
|
||||
bralid r15, schedule
|
||||
nop
|
||||
bri 4f
|
||||
1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||
beqi r11, no_work_pending
|
||||
addk r5, r30, r0
|
||||
bralid r15, do_notify_resume
|
||||
addik r6, r0, 1
|
||||
bri no_work_pending
|
||||
addk r30, r0, r0 /* no restarts from now on */
|
||||
4:
|
||||
disable_irq
|
||||
lwi r6, r31, TS_THREAD_INFO /* get thread info */
|
||||
lwi r19, r6, TI_FLAGS /* get flags in thread info */
|
||||
bri 3b
|
||||
|
||||
ENTRY(ret_to_user)
|
||||
disable_irq
|
||||
|
|
|
@ -402,26 +402,27 @@ C_ENTRY(ret_from_trap):
|
|||
* trigger rescheduling. */
|
||||
/* get thread info from current task */
|
||||
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_NEED_RESCHED;
|
||||
lwi r19, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r19, _TIF_NEED_RESCHED;
|
||||
beqi r11, 5f;
|
||||
|
||||
bralid r15, schedule; /* Call scheduler */
|
||||
nop; /* delay slot */
|
||||
bri 1b
|
||||
|
||||
/* Maybe handle a signal */
|
||||
5: /* get thread info from current task*/
|
||||
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqi r11, 1f; /* Signals to handle, handle them */
|
||||
5:
|
||||
andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqi r11, 4f; /* Signals to handle, handle them */
|
||||
|
||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
add r6, r30, r0; /* Arg 2: int in_syscall */
|
||||
add r30, r0, r0 /* no more restarts */
|
||||
bri 1b
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: set_bip; /* Ints masked for state restore */
|
||||
4: set_bip; /* Ints masked for state restore */
|
||||
swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
||||
VM_OFF;
|
||||
tophys(r1,r1);
|
||||
|
@ -573,20 +574,20 @@ C_ENTRY(ret_from_exc):
|
|||
|
||||
/* We're returning to user mode, so check for various conditions that
|
||||
trigger rescheduling. */
|
||||
1:
|
||||
lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_NEED_RESCHED;
|
||||
lwi r19, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r19, _TIF_NEED_RESCHED;
|
||||
beqi r11, 5f;
|
||||
|
||||
/* Call the scheduler before returning from a syscall/trap. */
|
||||
bralid r15, schedule; /* Call scheduler */
|
||||
nop; /* delay slot */
|
||||
bri 1b
|
||||
|
||||
/* Maybe handle a signal */
|
||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqi r11, 1f; /* Signals to handle, handle them */
|
||||
5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqi r11, 4f; /* Signals to handle, handle them */
|
||||
|
||||
/*
|
||||
* Handle a signal return; Pending signals should be in r18.
|
||||
|
@ -602,9 +603,10 @@ C_ENTRY(ret_from_exc):
|
|||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||
bri 1b
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: set_bip; /* Ints masked for state restore */
|
||||
4: set_bip; /* Ints masked for state restore */
|
||||
swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
||||
VM_OFF;
|
||||
tophys(r1,r1);
|
||||
|
@ -684,22 +686,23 @@ ret_from_irq:
|
|||
lwi r11, r1, PT_MODE;
|
||||
bnei r11, 2f;
|
||||
|
||||
1:
|
||||
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
|
||||
lwi r11, r11, TI_FLAGS; /* MS: get flags from thread info */
|
||||
andi r11, r11, _TIF_NEED_RESCHED;
|
||||
lwi r19, r11, TI_FLAGS; /* MS: get flags from thread info */
|
||||
andi r11, r19, _TIF_NEED_RESCHED;
|
||||
beqi r11, 5f
|
||||
bralid r15, schedule;
|
||||
nop; /* delay slot */
|
||||
bri 1b
|
||||
|
||||
/* Maybe handle a signal */
|
||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqid r11, no_intr_resched
|
||||
/* Handle a signal return; Pending signals should be in r18. */
|
||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||
bri 1b
|
||||
|
||||
/* Finally, return to user state. */
|
||||
no_intr_resched:
|
||||
|
@ -817,28 +820,29 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
|
|||
lwi r11, r1, PT_MODE;
|
||||
bnei r11, 2f;
|
||||
/* MS: Return to user space - gdb */
|
||||
1:
|
||||
/* Get current task ptr into r11 */
|
||||
lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_NEED_RESCHED;
|
||||
lwi r19, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r19, _TIF_NEED_RESCHED;
|
||||
beqi r11, 5f;
|
||||
|
||||
/* Call the scheduler before returning from a syscall/trap. */
|
||||
bralid r15, schedule; /* Call scheduler */
|
||||
nop; /* delay slot */
|
||||
bri 1b
|
||||
|
||||
/* Maybe handle a signal */
|
||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqi r11, 1f; /* Signals to handle, handle them */
|
||||
5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||
beqi r11, 4f; /* Signals to handle, handle them */
|
||||
|
||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||
bri 1b
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
||||
4: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
||||
VM_OFF;
|
||||
tophys(r1,r1);
|
||||
/* MS: Restore all regs */
|
||||
|
|
Loading…
Reference in New Issue