Message ID | 20220815105808.17385-2-chenzhongjin@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | x86/unwind/orc: Add 'unwind_debug' cmdline option | expand |
I accidentally attached this with my patch. Please ignore this one. Thanks, Chen On 2022/8/15 18:58, Chen Zhongjin wrote: > From: Josh Poimboeuf <jpoimboe@redhat.com> > > 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. > > Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> > Reviewed-by: Miroslav Benes <mbenes@suse.cz> > --- > .../admin-guide/kernel-parameters.txt | 6 +++ > arch/x86/kernel/unwind_orc.c | 46 +++++++++++++++++++ > 2 files changed, 52 insertions(+) > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > index cc3ea8febc62..85d48f6052fd 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -6317,6 +6317,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, > diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c > index 38185aedf7d1..c539ca39e9f4 100644 > --- a/arch/x86/kernel/unwind_orc.c > +++ b/arch/x86/kernel/unwind_orc.c > @@ -13,8 +13,13 @@ > > #define orc_warn_current(args...) \ > ({ \ > + static bool dumped_before; > if (state->task == current && !state->error) \ > orc_warn(args); \ > + if (unwind_debug && !dumped_before) \ > + unwind_dump(state); \ > + dumped_before = true; \ > + } \ > }) > > extern int __start_orc_unwind_ip[]; > @@ -23,8 +28,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;
Hi Chen, I love your patch! Perhaps something to improve: [auto build test WARNING on tip/x86/core] [also build test WARNING on soc/for-next clk/clk-next linus/master v6.0-rc1 next-20220815] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Chen-Zhongjin/x86-unwind-orc-Add-unwind_debug-cmdline-option/20220815-190328 base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git a1a5482a2c6e38a3ebed32e571625c56a8cc41a6 config: x86_64-randconfig-a003-20220815 (https://download.01.org/0day-ci/archive/20220816/202208160326.pFZMVgFP-lkp@intel.com/config) compiler: gcc-11 (Debian 11.3.0-5) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/3295e738f5b51f1f1f223bf52a8ecee2ab93fbca git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Chen-Zhongjin/x86-unwind-orc-Add-unwind_debug-cmdline-option/20220815-190328 git checkout 3295e738f5b51f1f1f223bf52a8ecee2ab93fbca # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash arch/x86/kernel/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): arch/x86/kernel/unwind_orc.c:17:9: error: expected identifier or '(' before 'if' 17 | if (state->task == current && !state->error) \ | ^~ In file included from include/asm-generic/bug.h:7, from arch/x86/include/asm/bug.h:87, from include/linux/bug.h:5, from include/linux/jump_label.h:257, from include/linux/static_key.h:1, from arch/x86/include/asm/nospec-branch.h:6, from arch/x86/include/asm/paravirt_types.h:40, from arch/x86/include/asm/ptrace.h:97, from arch/x86/include/asm/math_emu.h:5, from arch/x86/include/asm/processor.h:13, from arch/x86/include/asm/timex.h:5, from include/linux/timex.h:67, from include/linux/time32.h:13, from include/linux/time.h:60, from include/linux/stat.h:19, from include/linux/module.h:13, from arch/x86/kernel/unwind_orc.c:3: include/linux/once_lite.h:34:10: error: expected identifier or '(' before ')' token 34 | }) | ^ include/linux/once_lite.h:11:9: note: in expansion of macro 'DO_ONCE_LITE_IF' 11 | DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) | ^~~~~~~~~~~~~~~ include/linux/printk.h:605:9: note: in expansion of macro 'DO_ONCE_LITE' 605 | DO_ONCE_LITE(printk_deferred, fmt, ##__VA_ARGS__) | ^~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:12:9: note: in expansion of macro 'printk_deferred_once' 12 | printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__) | ^~~~~~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:18:17: note: in expansion of macro 'orc_warn' 18 | orc_warn(args); \ | ^~~~~~~~ arch/x86/kernel/unwind_orc.c:19:17: error: expected identifier or '(' before 'if' 19 | if (unwind_debug && !dumped_before) \ | ^~ >> arch/x86/kernel/unwind_orc.c:21:17: warning: data definition has no type or storage class 21 | dumped_before = true; \ | ^~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:21:17: error: type defaults to 'int' in declaration of 'dumped_before' [-Werror=implicit-int] arch/x86/kernel/unwind_orc.c:22:9: error: expected identifier or '(' before '}' token 22 | } \ | ^ arch/x86/kernel/unwind_orc.c:23:1: error: expected identifier or '(' before '}' token 23 | }) | ^ arch/x86/kernel/unwind_orc.c:23:2: error: expected identifier or '(' before ')' token 23 | }) | ^ arch/x86/kernel/unwind_orc.c: In function 'orc_find': arch/x86/kernel/unwind_orc.c:219:35: error: '__start_orc_unwind_ip' undeclared (first use in this function); did you mean '__start_orc_unwind'? 219 | return __orc_find(__start_orc_unwind_ip + start, | ^~~~~~~~~~~~~~~~~~~~~ | __start_orc_unwind arch/x86/kernel/unwind_orc.c:219:35: note: each undeclared identifier is reported only once for each function it appears in arch/x86/kernel/unwind_orc.c: At top level: arch/x86/kernel/unwind_orc.c:239:32: error: '__start_orc_unwind_ip' undeclared here (not in a function); did you mean '__start_orc_unwind'? 239 | static int *cur_orc_ip_table = __start_orc_unwind_ip; | ^~~~~~~~~~~~~~~~~~~~~ | __start_orc_unwind arch/x86/kernel/unwind_orc.c: In function 'unwind_next_frame': arch/x86/kernel/unwind_orc.c:534:18: error: expected ')' before 'break' 534 | } | ^ | ) 535 | break; | ~~~~~ >> arch/x86/kernel/unwind_orc.c:16:21: warning: unused variable 'dumped_before' [-Wunused-variable] 16 | static bool dumped_before; | ^~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:531:25: note: in expansion of macro 'orc_warn_current' 531 | orc_warn_current("missing R10 value at %pB\n", | ^~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:767:1: error: expected declaration or statement at end of input 767 | EXPORT_SYMBOL_GPL(__unwind_start); | ^~~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:767:1: error: expected declaration or statement at end of input arch/x86/kernel/unwind_orc.c:767:1: error: expected declaration or statement at end of input arch/x86/kernel/unwind_orc.c:533:25: error: label 'err' used but not defined 533 | goto err; | ^~~~ arch/x86/kernel/unwind_orc.c:506:17: error: label 'the_end' used but not defined 506 | goto the_end; | ^~~~ >> arch/x86/kernel/unwind_orc.c:468:14: warning: variable 'indirect' set but not used [-Wunused-but-set-variable] 468 | bool indirect = false; | ^~~~~~~~ >> arch/x86/kernel/unwind_orc.c:466:25: warning: unused variable 'prev_type' [-Wunused-variable] 466 | enum stack_type prev_type = state->stack_info.type; | ^~~~~~~~~ >> arch/x86/kernel/unwind_orc.c:465:59: warning: unused variable 'prev_sp' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~~~~~ >> arch/x86/kernel/unwind_orc.c:465:38: warning: unused variable 'orig_ip' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~~~~~ >> arch/x86/kernel/unwind_orc.c:465:33: warning: unused variable 'tmp' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~ >> arch/x86/kernel/unwind_orc.c:465:23: warning: unused variable 'ip_p' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~~ arch/x86/kernel/unwind_orc.c:768: error: control reaches end of non-void function [-Werror=return-type] At top level: >> arch/x86/kernel/unwind_orc.c:16:21: warning: 'dumped_before' defined but not used [-Wunused-variable] 16 | static bool dumped_before; | ^~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:531:25: note: in expansion of macro 'orc_warn_current' 531 | orc_warn_current("missing R10 value at %pB\n", | ^~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:421:13: warning: 'deref_stack_iret_regs' defined but not used [-Wunused-function] 421 | static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr, | ^~~~~~~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:405:13: warning: 'deref_stack_regs' defined but not used [-Wunused-function] 405 | static bool deref_stack_regs(struct unwind_state *state, unsigned long addr, | ^~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:395:13: warning: 'deref_stack_reg' defined but not used [-Wunused-function] 395 | static bool deref_stack_reg(struct unwind_state *state, unsigned long addr, | ^~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:42:13: warning: 'unwind_dump' defined but not used [-Wunused-function] 42 | static void unwind_dump(struct unwind_state *state) | ^~~~~~~~~~~ cc1: some warnings being treated as errors vim +21 arch/x86/kernel/unwind_orc.c 10 11 #define orc_warn(fmt, ...) \ 12 printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__) 13 14 #define orc_warn_current(args...) \ 15 ({ \ > 16 static bool dumped_before; 17 if (state->task == current && !state->error) \ 18 orc_warn(args); \ 19 if (unwind_debug && !dumped_before) \ 20 unwind_dump(state); \ > 21 dumped_before = true; \ 22 } \ 23 }) 24
Hi Chen, I love your patch! Yet something to improve: [auto build test ERROR on tip/x86/core] [also build test ERROR on soc/for-next clk/clk-next linus/master v6.0-rc1 next-20220815] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Chen-Zhongjin/x86-unwind-orc-Add-unwind_debug-cmdline-option/20220815-190328 base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git a1a5482a2c6e38a3ebed32e571625c56a8cc41a6 config: x86_64-randconfig-a003-20220815 (https://download.01.org/0day-ci/archive/20220816/202208160719.jJFohEBB-lkp@intel.com/config) compiler: gcc-11 (Debian 11.3.0-5) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/3295e738f5b51f1f1f223bf52a8ecee2ab93fbca git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Chen-Zhongjin/x86-unwind-orc-Add-unwind_debug-cmdline-option/20220815-190328 git checkout 3295e738f5b51f1f1f223bf52a8ecee2ab93fbca # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> arch/x86/kernel/unwind_orc.c:17:9: error: expected identifier or '(' before 'if' 17 | if (state->task == current && !state->error) \ | ^~ In file included from include/asm-generic/bug.h:7, from arch/x86/include/asm/bug.h:87, from include/linux/bug.h:5, from include/linux/jump_label.h:257, from include/linux/static_key.h:1, from arch/x86/include/asm/nospec-branch.h:6, from arch/x86/include/asm/paravirt_types.h:40, from arch/x86/include/asm/ptrace.h:97, from arch/x86/include/asm/math_emu.h:5, from arch/x86/include/asm/processor.h:13, from arch/x86/include/asm/timex.h:5, from include/linux/timex.h:67, from include/linux/time32.h:13, from include/linux/time.h:60, from include/linux/stat.h:19, from include/linux/module.h:13, from arch/x86/kernel/unwind_orc.c:3: >> include/linux/once_lite.h:34:10: error: expected identifier or '(' before ')' token 34 | }) | ^ include/linux/once_lite.h:11:9: note: in expansion of macro 'DO_ONCE_LITE_IF' 11 | DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) | ^~~~~~~~~~~~~~~ include/linux/printk.h:605:9: note: in expansion of macro 'DO_ONCE_LITE' 605 | DO_ONCE_LITE(printk_deferred, fmt, ##__VA_ARGS__) | ^~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:12:9: note: in expansion of macro 'printk_deferred_once' 12 | printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__) | ^~~~~~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:18:17: note: in expansion of macro 'orc_warn' 18 | orc_warn(args); \ | ^~~~~~~~ arch/x86/kernel/unwind_orc.c:19:17: error: expected identifier or '(' before 'if' 19 | if (unwind_debug && !dumped_before) \ | ^~ arch/x86/kernel/unwind_orc.c:21:17: warning: data definition has no type or storage class 21 | dumped_before = true; \ | ^~~~~~~~~~~~~ >> arch/x86/kernel/unwind_orc.c:21:17: error: type defaults to 'int' in declaration of 'dumped_before' [-Werror=implicit-int] >> arch/x86/kernel/unwind_orc.c:22:9: error: expected identifier or '(' before '}' token 22 | } \ | ^ arch/x86/kernel/unwind_orc.c:23:1: error: expected identifier or '(' before '}' token 23 | }) | ^ >> arch/x86/kernel/unwind_orc.c:23:2: error: expected identifier or '(' before ')' token 23 | }) | ^ arch/x86/kernel/unwind_orc.c: In function 'orc_find': >> arch/x86/kernel/unwind_orc.c:219:35: error: '__start_orc_unwind_ip' undeclared (first use in this function); did you mean '__start_orc_unwind'? 219 | return __orc_find(__start_orc_unwind_ip + start, | ^~~~~~~~~~~~~~~~~~~~~ | __start_orc_unwind arch/x86/kernel/unwind_orc.c:219:35: note: each undeclared identifier is reported only once for each function it appears in arch/x86/kernel/unwind_orc.c: At top level: >> arch/x86/kernel/unwind_orc.c:239:32: error: '__start_orc_unwind_ip' undeclared here (not in a function); did you mean '__start_orc_unwind'? 239 | static int *cur_orc_ip_table = __start_orc_unwind_ip; | ^~~~~~~~~~~~~~~~~~~~~ | __start_orc_unwind arch/x86/kernel/unwind_orc.c: In function 'unwind_next_frame': >> arch/x86/kernel/unwind_orc.c:534:18: error: expected ')' before 'break' 534 | } | ^ | ) 535 | break; | ~~~~~ arch/x86/kernel/unwind_orc.c:16:21: warning: unused variable 'dumped_before' [-Wunused-variable] 16 | static bool dumped_before; | ^~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:531:25: note: in expansion of macro 'orc_warn_current' 531 | orc_warn_current("missing R10 value at %pB\n", | ^~~~~~~~~~~~~~~~ >> arch/x86/kernel/unwind_orc.c:767:1: error: expected declaration or statement at end of input 767 | EXPORT_SYMBOL_GPL(__unwind_start); | ^~~~~~~~~~~~~~~~~ >> arch/x86/kernel/unwind_orc.c:767:1: error: expected declaration or statement at end of input >> arch/x86/kernel/unwind_orc.c:767:1: error: expected declaration or statement at end of input >> arch/x86/kernel/unwind_orc.c:533:25: error: label 'err' used but not defined 533 | goto err; | ^~~~ >> arch/x86/kernel/unwind_orc.c:506:17: error: label 'the_end' used but not defined 506 | goto the_end; | ^~~~ arch/x86/kernel/unwind_orc.c:468:14: warning: variable 'indirect' set but not used [-Wunused-but-set-variable] 468 | bool indirect = false; | ^~~~~~~~ arch/x86/kernel/unwind_orc.c:466:25: warning: unused variable 'prev_type' [-Wunused-variable] 466 | enum stack_type prev_type = state->stack_info.type; | ^~~~~~~~~ arch/x86/kernel/unwind_orc.c:465:59: warning: unused variable 'prev_sp' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~~~~~ arch/x86/kernel/unwind_orc.c:465:38: warning: unused variable 'orig_ip' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~~~~~ arch/x86/kernel/unwind_orc.c:465:33: warning: unused variable 'tmp' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~ arch/x86/kernel/unwind_orc.c:465:23: warning: unused variable 'ip_p' [-Wunused-variable] 465 | unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; | ^~~~ arch/x86/kernel/unwind_orc.c:768: error: control reaches end of non-void function [-Werror=return-type] At top level: arch/x86/kernel/unwind_orc.c:16:21: warning: 'dumped_before' defined but not used [-Wunused-variable] 16 | static bool dumped_before; | ^~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:531:25: note: in expansion of macro 'orc_warn_current' 531 | orc_warn_current("missing R10 value at %pB\n", | ^~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:421:13: warning: 'deref_stack_iret_regs' defined but not used [-Wunused-function] 421 | static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr, | ^~~~~~~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:405:13: warning: 'deref_stack_regs' defined but not used [-Wunused-function] 405 | static bool deref_stack_regs(struct unwind_state *state, unsigned long addr, | ^~~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:395:13: warning: 'deref_stack_reg' defined but not used [-Wunused-function] 395 | static bool deref_stack_reg(struct unwind_state *state, unsigned long addr, | ^~~~~~~~~~~~~~~ arch/x86/kernel/unwind_orc.c:42:13: warning: 'unwind_dump' defined but not used [-Wunused-function] 42 | static void unwind_dump(struct unwind_state *state) | ^~~~~~~~~~~ cc1: some warnings being treated as errors vim +17 arch/x86/kernel/unwind_orc.c ee9f8fce996408 Josh Poimboeuf 2017-07-24 10 ee9f8fce996408 Josh Poimboeuf 2017-07-24 11 #define orc_warn(fmt, ...) \ b08418b5483125 Josh Poimboeuf 2020-04-25 12 printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__) b08418b5483125 Josh Poimboeuf 2020-04-25 13 b08418b5483125 Josh Poimboeuf 2020-04-25 14 #define orc_warn_current(args...) \ b08418b5483125 Josh Poimboeuf 2020-04-25 15 ({ \ 3295e738f5b51f Josh Poimboeuf 2022-08-15 @16 static bool dumped_before; b59cc97674c947 Josh Poimboeuf 2021-02-05 @17 if (state->task == current && !state->error) \ b08418b5483125 Josh Poimboeuf 2020-04-25 @18 orc_warn(args); \ 3295e738f5b51f Josh Poimboeuf 2022-08-15 @19 if (unwind_debug && !dumped_before) \ 3295e738f5b51f Josh Poimboeuf 2022-08-15 20 unwind_dump(state); \ 3295e738f5b51f Josh Poimboeuf 2022-08-15 @21 dumped_before = true; \ 3295e738f5b51f Josh Poimboeuf 2022-08-15 @22 } \ b08418b5483125 Josh Poimboeuf 2020-04-25 @23 }) ee9f8fce996408 Josh Poimboeuf 2017-07-24 24
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index cc3ea8febc62..85d48f6052fd 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6317,6 +6317,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, diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 38185aedf7d1..c539ca39e9f4 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -13,8 +13,13 @@ #define orc_warn_current(args...) \ ({ \ + static bool dumped_before; if (state->task == current && !state->error) \ orc_warn(args); \ + if (unwind_debug && !dumped_before) \ + unwind_dump(state); \ + dumped_before = true; \ + } \ }) extern int __start_orc_unwind_ip[]; @@ -23,8 +28,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;