signal/syscall/swapcontext fixes
David Woodhouse
dwmw2 at infradead.org
Wed Mar 8 00:09:11 EST 2006
On Tue, 2006-03-07 at 23:32 +1100, Paul Mackerras wrote:
> * The TIF_SAVE_NVGPRS mechanism was only being used by swapcontext, so
> I removed it and put swapcontext back the way it was in 2.6.15, with
> an assembler stub to save the non-volatile GPRs before calling the C
> code. The save_general_regs functions now WARN_ON(!FULL_REGS(regs)).
OK. As observed, I'd mostly obsoleted TIF_SAVE_NVGPRS when I implemented
TIF_RESTORE_SIGMASK.
The 64-bit version (bl .save_nvgprs) is prettier than the 32-bit version
(doing it longhand), and they're still gratuitously different. We should
probably fix that.
> * 32-bit wasn't testing the _TIF_NOERROR bit in the syscall fast exit
> path, so it was only doing anything with it once it saw some other
> bit being set.
OK.
> * 32-bit wasn't doing the call to ptrace_notify in the syscall exit
> path when the _TIF_SINGLESTEP bit was set.
Yeah. That was historical (arch/ppc never did this) but nonetheless
still wrong. Without it, we never stop on the instruction immediately
following the 'sc', when we're supposed to be single-stepping.
On a similar note, we should also do a ptrace stop when we deliver
signals, to ensure that the debugger gets a stop _on_ the first
instruction of the handler. Once upon a time there was a stop in
handle_rt_signal() and handle_signal(), but doing it that way gave a
_double_ stop when we ended up in a signal handler from sigsuspend(),
because the syscall stop you just fixed for ppc32 happened too.
> * _TIF_RESTOREALL was in both _TIF_USER_WORK_MASK and
> _TIF_PERSYSCALL_MASK, which is odd since _TIF_RESTOREALL is only set
> by system calls. I took it out of _TIF_USER_WORK_MASK.
Right.
> * On 64-bit, _TIF_RESTOREALL wasn't causing the non-volatile registers
> to be restored (unless perhaps a signal was delivered or the syscall
> was traced or single-stepped). Thus the non-volatile registers
> weren't restored on exit from a signal handler. We probably got
> away with it mostly because signal handlers written in C wouldn't
> alter the non-volatile registers.
Hm, yes. The idea behind TIF_RESTOREALL was just to prevent r3 and the
flags from getting stomped on -- I didn't look at the nvgprs at that
point, and I'm not sure if the nvgprs were being restored on ppc32
before my changes. They could well have been on ppc64 -- this was
another area in which the two were different.
> * On 32-bit I simplified the code and made it more like 64-bit by
> making the syscall exit path jump to ret_from_except to handle
> preemption and signal delivery.
OK, good. It would actually be nice if we could split a bunch of this
code out into a shared file and use the PPC_LL, PPC_STL, etc. macros.
> * 32-bit was calling do_signal unnecessarily when _TIF_RESTOREALL was
> set - but I think because of that 32-bit was actually restoring the
> non-volatile registers on exit from a signal handler.
OK.
> * I changed the order of enabling interrupts and saving the
> non-volatile registers before calling do_syscall_trace_leave; now we
> enable interrupts first.
OK.
> Any comments before I send this off to Linus to go in 2.6.16?
Looks good.
On a purely cosmetic note I'm not sure about this though -- it was
slightly easier to follow when it was more explicit:
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK)
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
--
dwmw2
More information about the Linuxppc-dev
mailing list