Commit 89da5a69 authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Josh Poimboeuf

x86/unwind/orc: Add 'unwind_debug' cmdline option

Sometimes the one-line ORC unwinder warnings aren't very helpful.  Add a
new 'unwind_debug' cmdline option which will dump the full stack
contents of the current task when an error condition is encountered.
Reviewed-by: default avatarMiroslav Benes <mbenes@suse.cz>
Link: https://lore.kernel.org/r/6afb9e48a05fd2046bfad47e69b061b43dfd0e0e.1681331449.git.jpoimboe@kernel.orgSigned-off-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
parent dc1d0553
......@@ -6563,6 +6563,12 @@
unknown_nmi_panic
[X86] Cause panic on unknown NMI.
unwind_debug [X86-64]
Enable unwinder debug output. This can be
useful for debugging certain unwinder error
conditions, including corrupt stacks and
bad/missing unwinder metadata.
usbcore.authorized_default=
[USB] Default USB device authorization:
(default -1 = authorized except for wireless USB,
......
......@@ -13,8 +13,14 @@
#define orc_warn_current(args...) \
({ \
if (state->task == current && !state->error) \
static bool dumped_before; \
if (state->task == current && !state->error) { \
orc_warn(args); \
if (unwind_debug && !dumped_before) { \
dumped_before = true; \
unwind_dump(state); \
} \
} \
})
extern int __start_orc_unwind_ip[];
......@@ -23,8 +29,49 @@ extern struct orc_entry __start_orc_unwind[];
extern struct orc_entry __stop_orc_unwind[];
static bool orc_init __ro_after_init;
static bool unwind_debug __ro_after_init;
static unsigned int lookup_num_blocks __ro_after_init;
static int __init unwind_debug_cmdline(char *str)
{
unwind_debug = true;
return 0;
}
early_param("unwind_debug", unwind_debug_cmdline);
static void unwind_dump(struct unwind_state *state)
{
static bool dumped_before;
unsigned long word, *sp;
struct stack_info stack_info = {0};
unsigned long visit_mask = 0;
if (dumped_before)
return;
dumped_before = true;
printk_deferred("unwind stack type:%d next_sp:%p mask:0x%lx graph_idx:%d\n",
state->stack_info.type, state->stack_info.next_sp,
state->stack_mask, state->graph_idx);
for (sp = __builtin_frame_address(0); sp;
sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
if (get_stack_info(sp, state->task, &stack_info, &visit_mask))
break;
for (; sp < stack_info.end; sp++) {
word = READ_ONCE_NOCHECK(*sp);
printk_deferred("%0*lx: %0*lx (%pB)\n", BITS_PER_LONG/4,
(unsigned long)sp, BITS_PER_LONG/4,
word, (void *)word);
}
}
}
static inline unsigned long orc_ip(const int *ip)
{
return (unsigned long)ip + *ip;
......
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