From: Steven Rostedt <rostedt@goodmis.org> Date: 2012-02-03 18:30:45
Thomas,
Can you apply these to v3.2-rt.
Version 4:
In testing, Clark Williams triggered a bug in the paranoid_exit return
path. The %rcx register was being clobbered by a function call and
needed to be restored with: GET_THREAD_INFO(%rcx)
This version has been tested and so far has triggered no bugs.
-- Steve
From: Steven Rostedt <rostedt@goodmis.org> Date: 2012-02-03 18:30:47
On x86_64 we must disable preemption before we enable interrupts
for int3 and debugging, because the current task is using a per CPU
debug stack defined by the IST. If we schedule out, another task
can come in and use the same stack and cause the stack to be corrupted
and crash the kernel on return.
When CONFIG_PREEMPT_RT_FULL is enabled, spin_locks become mutexes, and
one of these is the spin lock used in signal handling.
Some of the debug code (int3) causes do_trap() to send a signal.
This function calls a spin lock that has been converted to a mutex
and has the possibility to sleep. If this happens, the above issues with
the corrupted stack is possible.
Instead of calling the signal right away, for PREEMPT_RT and x86_64,
the signal information is stored on the stacks task_struct and a
new TIF flag is set (TIF_FORCE_SIG_TRAP). On exit of the exception,
in paranoid_exit, if NEED_RESCHED is set, the task stack is switched
back to the kernel stack and interrupts is enabled. In this code
the TIF_FORCE_SIG_TRAP is also checked and a function is called to
do the force_sig() in a context that may schedule.
Note, to get into this path, the NEED_RESCHED flag is also set.
But as this only happens in debug context, an extra schedule should not
be an issue.
Cc: stable-rt@vger.kernel.org
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-rt.git/arch/x86/include/asm/thread_info.h
===================================================================
From: Steven Rostedt <rostedt@goodmis.org> Date: 2012-02-03 18:31:15
Preemption must be disabled before enabling interrupts in do_trap
on x86_64 because the stack in use for int3 and debug is a per CPU
stack set by th IST. But 32bit does not have an IST and the stack
still belongs to the current task and there is no problem in scheduling
out the task.
Keep preemption enabled on X86_32 when enabling interrupts for
do_trap().
The name of the function is changed from preempt_conditional_sti/cli()
to conditional_sti/cli_ist(), to annotate that this function is used
when the stack is on the IST.
Cc: stable-rt@vger.kernel.org
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-rt.git/arch/x86/kernel/traps.c
===================================================================
@@ -412,12 +426,12 @@ dotraplinkage void __kprobes do_debug(streturn;/* It's safe to allow irq's after DR6 has been saved */-preempt_conditional_sti(regs);+conditional_sti_ist(regs);if(regs->flags&X86_VM_MASK){handle_vm86_trap((structkernel_vm86_regs*)regs,error_code,1);-preempt_conditional_cli(regs);+conditional_cli_ist(regs);return;}
Stupid question. Do we really need to send the signal from here?
Why force_sig(rt => T) can't set TIF_NOTIFY_RESUME instead? Then
we can change do_notify_resume() to check TIF_FORCE_SIG_TRAP. And
perhaps we can even avoid the new TIF_FORCE_SIG_TRAP, we could
check task->stored_info_set.
In fact I feel this can be simplified even more, but I am not sure.
Oleg.
From: Steven Rostedt <rostedt@goodmis.org> Date: 2012-02-03 20:10:38
On Fri, 2012-02-03 at 19:40 +0100, Oleg Nesterov wrote:
Stupid question. Do we really need to send the signal from here?
If we can do it correctly elsewhere, I'm fine with that too :-)
Why force_sig(rt => T) can't set TIF_NOTIFY_RESUME instead? Then
we can change do_notify_resume() to check TIF_FORCE_SIG_TRAP. And
perhaps we can even avoid the new TIF_FORCE_SIG_TRAP, we could
check task->stored_info_set.
You know the signal code much better than I do. If that works, I'm all
for that too. I really don't like the entry_64 solution, but it was what
I knew would work.
In fact I feel this can be simplified even more, but I am not sure.
My strengths are in the entry_64.S code, not the signal code, so I fixed
it the best way that I felt. This does not imply my fix is the best. If
we can solve this in a clean way using the existing signal
infrastructure, I'm all for that.
-- Steve
If
we can solve this in a clean way using the existing signal
infrastructure, I'm all for that.
I am not sure, I know almost nothing about rt and about this
low-level stuff. But please look at my attempt below.
So. it is very simple. The patch simply changes force_sig_info() to
check in_atomic(), if it is true we offload the sending to
do_notify_resume(). Of course, I do not know if we can rely on this
check in rt kernels.
Note:
- The patch adds the new code under CONFIG_PREEMPT_RT_FULL,
it should probably check X86_64 or defined(TIF_NOTIFY_RESUME)
as well.
- I think we can later move task->forced_info into restart_block's
union.
- We could modify get_signal_to_deliver() instead of the
arch-dependant do_notify_resume(). In this case we do not
need TIF_NOTIFY_RESUME, TIF_SIGPENDING is enough.
What do you think?
Oleg.
---
arch/x86/kernel/signal.c | 9 +++++++++
include/linux/sched.h | 4 ++++
kernel/signal.c | 31 +++++++++++++++++++++++++++++--
3 files changed, 42 insertions(+), 2 deletions(-)
@@ -1407,6 +1407,10 @@ struct task_struct {sigset_tblocked,real_blocked;sigset_tsaved_sigmask;/* restored if set_restore_sigmask() was used */structsigpendingpending;+#ifdef CONFIG_PREEMPT_RT_FULL+/* TODO: move me into ->restart_block ? */+structsiginfoforced_info;+#endifunsignedlongsas_ss_sp;size_tsas_ss_size;
This is certainly wrong in upstream kernel. It does use force_
this way although it shouldn't imho.
But _probably_ this is fine for rt? We are going to take the mutex,
we shouldn't do this in atomic context. But, once again, I do not
really know what in_atomic() means in rt.
Oleg.
This is certainly wrong in upstream kernel. It does use force_
this way although it shouldn't imho.
It's wrong in upstream even with the #ifdef define here?
But _probably_ this is fine for rt? We are going to take the mutex,
we shouldn't do this in atomic context. But, once again, I do not
really know what in_atomic() means in rt.
in_atomic() is the same in rt as in mainline. It should still work.
-- Steve
From: Steven Rostedt <rostedt@goodmis.org> Date: 2012-02-07 14:17:28
On Sun, 2012-02-05 at 20:23 +0100, Oleg Nesterov wrote:
On 02/03, Steven Rostedt wrote:
quoted
If
we can solve this in a clean way using the existing signal
infrastructure, I'm all for that.
I am not sure, I know almost nothing about rt and about this
low-level stuff. But please look at my attempt below.
So. it is very simple. The patch simply changes force_sig_info() to
check in_atomic(), if it is true we offload the sending to
do_notify_resume(). Of course, I do not know if we can rely on this
check in rt kernels.
Note:
- The patch adds the new code under CONFIG_PREEMPT_RT_FULL,
it should probably check X86_64 or defined(TIF_NOTIFY_RESUME)
as well.
- I think we can later move task->forced_info into restart_block's
union.
- We could modify get_signal_to_deliver() instead of the
arch-dependant do_notify_resume(). In this case we do not
need TIF_NOTIFY_RESUME, TIF_SIGPENDING is enough.
What do you think?
Oleg.
---
arch/x86/kernel/signal.c | 9 +++++++++
include/linux/sched.h | 4 ++++
kernel/signal.c | 31 +++++++++++++++++++++++++++++--
The problem I have with this patch is here. The change to
kernel/signal.c. If anything, all the changes should be encompassed with
a #ifdef CONFIG_X86_64 as well (or defined(CONFIG_PREEMPT_RT_FULL) &&
defined(CONFIG_X86_64)).
Below is an update of my patch that also handles the stack_segment
fault. I used the info.si_signo to pass what sig is to be sent, and
changed the flag from TIF_FORCE_SIG_TRAP to just TIF_FORCE_SIG. Is this
still acceptable.
I'm not attached to this patch over Oleg's. I've tested both, and they
both work. Oleg's is simpler but puts some of the changes into the core
kernel/signal.c file. Mine is a little more complex but keeps the code
more contained in the x86 arch. If adding x86 specific code into the
core signal code is acceptable, I'll take Oleg's patch.
I'd like to hear from others. Which is more appropriate if we ever need
to send this mainline?
Again, I'd take Oleg's patch just as much as I'd take my own. I really
don't care.
Oleg, if I do end up taking your patch, I still need your signed-off-by.
Thanks!
-- Steve
preempt-rt/x86: Delay calling signals in int3
On x86_64 we must disable preemption before we enable interrupts
for int3 and debugging, because the current task is using a per CPU
debug stack defined by the IST. If we schedule out, another task
can come in and use the same stack and cause the stack to be corrupted
and crash the kernel on return.
When CONFIG_PREEMPT_RT_FULL is enabled, spin_locks become mutexes, and
one of these is the spin lock used in signal handling.
Some of the debug code (int3) causes do_trap() to send a signal.
This function calls a spin lock that has been converted to a mutex
and has the possibility to sleep. If this happens, the above issues with
the corrupted stack is possible.
Instead of calling the signal right away, for PREEMPT_RT and x86_64,
the signal information is stored on the stacks task_struct and a
new TIF flag is set (TIF_FORCE_SIG_TRAP). On exit of the exception,
in paranoid_exit, if NEED_RESCHED is set, the task stack is switched
back to the kernel stack and interrupts is enabled. In this code
the TIF_FORCE_SIG_TRAP is also checked and a function is called to
do the force_sig() in a context that may schedule.
Note, to get into this path, the NEED_RESCHED flag is also set.
But as this only happens in debug context, an extra schedule should not
be an issue.
Cc: stable-rt@vger.kernel.org
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-rt.git/arch/x86/include/asm/thread_info.h
===================================================================