Commit 740ef64b authored by Philippe Gerum's avatar Philippe Gerum
Browse files

evl/thread: detect recursive faults in out-of-band context



Make sure breakage and/or WARN_ON() in the in-band transition code we
use for fixing up a trap on the oob stage cannot cause
handle_oob_trap() to be called recursively, leading to a stack
overflow eventually.
Signed-off-by: Philippe Gerum's avatarPhilippe Gerum <rpm@xenomai.org>
parent 9e366a52
......@@ -51,6 +51,7 @@
#define T_MOVED 0x00000001 /*< CPU migration request issued from OOB context */
#define T_SYSRST 0x00000002 /*< Thread awaiting syscall restart after signal */
#define T_HICCUP 0x00000004 /*< Just left from ptracing - timings wrecked */
#define T_INFAULT 0x00000008 /*< In fault handling */
/*
* Must follow strictly the declaration order of the state flags
......
......@@ -1635,6 +1635,20 @@ void arch_inband_task_init(struct task_struct *tsk)
evl_init_thread_state(p);
}
static inline void note_trap(struct evl_thread *curr,
unsigned int trapnr, struct pt_regs *regs,
const char *msg)
{
printk(EVL_WARNING
"%s %s [pid=%d, excpt=%#x, %spc=%#lx]\n",
curr->name, msg,
evl_get_inband_pid(curr),
trapnr,
user_mode(regs) ? "" : "kernel_",
instruction_pointer(regs));
}
/* hard irqs off. */
void handle_oob_trap(unsigned int trapnr, struct pt_regs *regs)
{
struct evl_thread *curr;
......@@ -1642,17 +1656,18 @@ void handle_oob_trap(unsigned int trapnr, struct pt_regs *regs)
oob_context_only();
curr = evl_current();
if (curr->local_info & T_INFAULT) {
note_trap(curr, trapnr, regs, "recursive fault");
return;
}
curr->local_info |= T_INFAULT;
trace_evl_thread_fault(trapnr, regs);
#if defined(CONFIG_EVL_DEBUG_CORE) || defined(CONFIG_EVL_DEBUG_USER)
if (xnarch_fault_notify(trapnr))
printk(EVL_WARNING
"%s switching in-band [pid=%d, excpt=%#x, %spc=%#lx]\n",
curr->name,
evl_get_inband_pid(curr),
trapnr,
user_mode(regs) ? "" : "kernel_",
instruction_pointer(regs));
note_trap(curr, trapnr, regs, "switching in-band");
#endif
if (xnarch_fault_pf_p(trapnr))
/*
......@@ -1669,6 +1684,8 @@ void handle_oob_trap(unsigned int trapnr, struct pt_regs *regs)
evl_switch_inband(xnarch_fault_notify(trapnr) ?
SIGDEBUG_MIGRATE_FAULT :
SIGDEBUG_UNDEFINED);
curr->local_info &= ~T_INFAULT;
}
void handle_oob_mayday(struct pt_regs *regs)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment