mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
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: Miroslav Benes <mbenes@suse.cz> Link: https://lore.kernel.org/r/6afb9e48a05fd2046bfad47e69b061b43dfd0e0e.1681331449.git.jpoimboe@kernel.org Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
parent
dc1d05536f
commit
89da5a69a8
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user