* [RFC] pr_warn_once() issue in x86 MSR extable code @ 2022-06-17 11:08 Stephane Eranian 2022-06-17 14:52 ` Peter Zijlstra 0 siblings, 1 reply; 6+ messages in thread From: Stephane Eranian @ 2022-06-17 11:08 UTC (permalink / raw) To: Peter Zijlstra; +Cc: LKML, Eric Dumazet, jpoimboe, Steven Rostedt Hi, Some changes to the way invalid MSR accesses are reported by the kernel is causing some problems with messages printed on the console. We have seen several cases of ex_handler_msr() printing invalid MSR accesses once but the callstack multiple times causing confusion on the console. The last time the exception MSR code was modified (5.16) by PeterZ was: d52a7344bdfa x86/msr: Remove .fixup usage: if (!safe && wrmsr && pr_warn_once("unchecked MSR access error: ...")) show_stack_regs(regs); Note that this code pattern was also present, though in a different form, before this commit. The problem here is that another earlier commit (5.13): a358f40600b3 once: implement DO_ONCE_LITE for non-fast-path "do once" functionality Modifies all the pr_*_once() calls to always return true claiming that no caller is ever checking the return value of the functions. This is why we are seeing the callstack printed without the associated printk() msg. I believe that having the pr_*_once() functions return true the first time they are called is useful especially when extra information, such as callstack, must be printed to help track the origin of the problem. The exception handling code seems to be the only place where the return value is checked for pr_warn_once(). A minimal change would be to create another version of that function that calls DO_ONCE() instead of DO_ONCE_LITE(), e.g., pr_warn_once_return(). I can post a patch to that effect if we all agree on the approach. Thanks. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC] pr_warn_once() issue in x86 MSR extable code 2022-06-17 11:08 [RFC] pr_warn_once() issue in x86 MSR extable code Stephane Eranian @ 2022-06-17 14:52 ` Peter Zijlstra 2022-06-22 17:51 ` Stephane Eranian 2022-07-21 8:52 ` [tip: x86/core] " tip-bot2 for Peter Zijlstra 0 siblings, 2 replies; 6+ messages in thread From: Peter Zijlstra @ 2022-06-17 14:52 UTC (permalink / raw) To: Stephane Eranian; +Cc: LKML, Eric Dumazet, jpoimboe, Steven Rostedt On Fri, Jun 17, 2022 at 02:08:52PM +0300, Stephane Eranian wrote: > Hi, > > Some changes to the way invalid MSR accesses are reported by the kernel is > causing some problems with messages printed on the console. > > We have seen several cases of ex_handler_msr() printing invalid MSR > accesses once but > the callstack multiple times causing confusion on the console. > > The last time the exception MSR code was modified (5.16) by PeterZ was: > > d52a7344bdfa x86/msr: Remove .fixup usage: > > if (!safe && wrmsr && pr_warn_once("unchecked MSR access error: ...")) > show_stack_regs(regs); > > Note that this code pattern was also present, though in a different > form, before this commit. > > The problem here is that another earlier commit (5.13): > > a358f40600b3 once: implement DO_ONCE_LITE for non-fast-path "do once" > functionality > > Modifies all the pr_*_once() calls to always return true claiming that > no caller is ever > checking the return value of the functions. > > This is why we are seeing the callstack printed without the associated > printk() msg. > > I believe that having the pr_*_once() functions return true the first > time they are called > is useful especially when extra information, such as callstack, must > be printed to help > track the origin of the problem. > > The exception handling code seems to be the only place where the > return value is checked > for pr_warn_once(). A minimal change would be to create another > version of that function > that calls DO_ONCE() instead of DO_ONCE_LITE(), e.g., pr_warn_once_return(). > > I can post a patch to that effect if we all agree on the approach. > > Thanks. How about something like this? diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index dba2197c05c3..331310c29349 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -94,16 +94,18 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, static bool ex_handler_msr(const struct exception_table_entry *fixup, struct pt_regs *regs, bool wrmsr, bool safe, int reg) { - if (!safe && wrmsr && - pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", - (unsigned int)regs->cx, (unsigned int)regs->dx, - (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) + if (__ONCE_LITE_IF(!safe && wrmsr)) { + pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, (unsigned int)regs->dx, + (unsigned int)regs->ax, regs->ip, (void *)regs->ip); show_stack_regs(regs); + } - if (!safe && !wrmsr && - pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", - (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) + if (__ONCE_LITE_IF(!safe && !wrmsr)) { + pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, regs->ip, (void *)regs->ip); show_stack_regs(regs); + } if (!wrmsr) { /* Pretend that the read succeeded and returned 0. */ diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h index 861e606b820f..63c3bbcef694 100644 --- a/include/linux/once_lite.h +++ b/include/linux/once_lite.h @@ -9,15 +9,27 @@ */ #define DO_ONCE_LITE(func, ...) \ DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) -#define DO_ONCE_LITE_IF(condition, func, ...) \ + +#define __ONCE_LITE_IF(condition) \ ({ \ static bool __section(".data.once") __already_done; \ - bool __ret_do_once = !!(condition); \ + bool __ret_cond = !!(condition); \ + bool __ret_once = false; \ \ if (unlikely(__ret_do_once && !__already_done)) { \ __already_done = true; \ - func(__VA_ARGS__); \ + __ret_once = true; \ } \ + unlikely(__ret_once); \ + }) + +#define DO_ONCE_LITE_IF(condition, func, ...) \ + ({ \ + bool __ret_do_once = !!(condition); \ + \ + if (__ONCE_LITE_IF(__ret_do_once)) \ + func(__VA_ARGS__); \ + \ unlikely(__ret_do_once); \ }) ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [RFC] pr_warn_once() issue in x86 MSR extable code 2022-06-17 14:52 ` Peter Zijlstra @ 2022-06-22 17:51 ` Stephane Eranian 2022-07-20 12:48 ` Stephane Eranian 2022-07-21 8:52 ` [tip: x86/core] " tip-bot2 for Peter Zijlstra 1 sibling, 1 reply; 6+ messages in thread From: Stephane Eranian @ 2022-06-22 17:51 UTC (permalink / raw) To: Peter Zijlstra; +Cc: LKML, Eric Dumazet, jpoimboe, Steven Rostedt Hi Peter, Thanks for taking a quick look at this. I am currently OOO and I cannot test this proposed patch. I am okay with your suggestion. Thanks. On Fri, Jun 17, 2022 at 4:52 PM Peter Zijlstra <peterz@infradead.org> wrote: > > On Fri, Jun 17, 2022 at 02:08:52PM +0300, Stephane Eranian wrote: > > Hi, > > > > Some changes to the way invalid MSR accesses are reported by the kernel is > > causing some problems with messages printed on the console. > > > > We have seen several cases of ex_handler_msr() printing invalid MSR > > accesses once but > > the callstack multiple times causing confusion on the console. > > > > The last time the exception MSR code was modified (5.16) by PeterZ was: > > > > d52a7344bdfa x86/msr: Remove .fixup usage: > > > > if (!safe && wrmsr && pr_warn_once("unchecked MSR access error: ...")) > > show_stack_regs(regs); > > > > Note that this code pattern was also present, though in a different > > form, before this commit. > > > > The problem here is that another earlier commit (5.13): > > > > a358f40600b3 once: implement DO_ONCE_LITE for non-fast-path "do once" > > functionality > > > > Modifies all the pr_*_once() calls to always return true claiming that > > no caller is ever > > checking the return value of the functions. > > > > This is why we are seeing the callstack printed without the associated > > printk() msg. > > > > I believe that having the pr_*_once() functions return true the first > > time they are called > > is useful especially when extra information, such as callstack, must > > be printed to help > > track the origin of the problem. > > > > The exception handling code seems to be the only place where the > > return value is checked > > for pr_warn_once(). A minimal change would be to create another > > version of that function > > that calls DO_ONCE() instead of DO_ONCE_LITE(), e.g., pr_warn_once_return(). > > > > I can post a patch to that effect if we all agree on the approach. > > > > Thanks. > > How about something like this? > > diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c > index dba2197c05c3..331310c29349 100644 > --- a/arch/x86/mm/extable.c > +++ b/arch/x86/mm/extable.c > @@ -94,16 +94,18 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, > static bool ex_handler_msr(const struct exception_table_entry *fixup, > struct pt_regs *regs, bool wrmsr, bool safe, int reg) > { > - if (!safe && wrmsr && > - pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", > - (unsigned int)regs->cx, (unsigned int)regs->dx, > - (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) > + if (__ONCE_LITE_IF(!safe && wrmsr)) { > + pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", > + (unsigned int)regs->cx, (unsigned int)regs->dx, > + (unsigned int)regs->ax, regs->ip, (void *)regs->ip); > show_stack_regs(regs); > + } > > - if (!safe && !wrmsr && > - pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", > - (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) > + if (__ONCE_LITE_IF(!safe && !wrmsr)) { > + pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", > + (unsigned int)regs->cx, regs->ip, (void *)regs->ip); > show_stack_regs(regs); > + } > > if (!wrmsr) { > /* Pretend that the read succeeded and returned 0. */ > diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h > index 861e606b820f..63c3bbcef694 100644 > --- a/include/linux/once_lite.h > +++ b/include/linux/once_lite.h > @@ -9,15 +9,27 @@ > */ > #define DO_ONCE_LITE(func, ...) \ > DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) > -#define DO_ONCE_LITE_IF(condition, func, ...) \ > + > +#define __ONCE_LITE_IF(condition) \ > ({ \ > static bool __section(".data.once") __already_done; \ > - bool __ret_do_once = !!(condition); \ > + bool __ret_cond = !!(condition); \ > + bool __ret_once = false; \ > \ > if (unlikely(__ret_do_once && !__already_done)) { \ > __already_done = true; \ > - func(__VA_ARGS__); \ > + __ret_once = true; \ > } \ > + unlikely(__ret_once); \ > + }) > + > +#define DO_ONCE_LITE_IF(condition, func, ...) \ > + ({ \ > + bool __ret_do_once = !!(condition); \ > + \ > + if (__ONCE_LITE_IF(__ret_do_once)) \ > + func(__VA_ARGS__); \ > + \ > unlikely(__ret_do_once); \ > }) > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC] pr_warn_once() issue in x86 MSR extable code 2022-06-22 17:51 ` Stephane Eranian @ 2022-07-20 12:48 ` Stephane Eranian 2022-07-20 13:44 ` [PATCH] x86/extable: Fix ex_handler_msr() print condition Peter Zijlstra 0 siblings, 1 reply; 6+ messages in thread From: Stephane Eranian @ 2022-07-20 12:48 UTC (permalink / raw) To: Peter Zijlstra; +Cc: LKML, Eric Dumazet, jpoimboe, Steven Rostedt On Wed, Jun 22, 2022 at 8:51 PM Stephane Eranian <eranian@google.com> wrote: > > Hi Peter, > > Thanks for taking a quick look at this. > I am currently OOO and I cannot test this proposed patch. > I am okay with your suggestion. > > Thanks. > > On Fri, Jun 17, 2022 at 4:52 PM Peter Zijlstra <peterz@infradead.org> wrote: > > > > On Fri, Jun 17, 2022 at 02:08:52PM +0300, Stephane Eranian wrote: > > > Hi, > > > > > > Some changes to the way invalid MSR accesses are reported by the kernel is > > > causing some problems with messages printed on the console. > > > > > > We have seen several cases of ex_handler_msr() printing invalid MSR > > > accesses once but > > > the callstack multiple times causing confusion on the console. > > > > > > The last time the exception MSR code was modified (5.16) by PeterZ was: > > > > > > d52a7344bdfa x86/msr: Remove .fixup usage: > > > > > > if (!safe && wrmsr && pr_warn_once("unchecked MSR access error: ...")) > > > show_stack_regs(regs); > > > > > > Note that this code pattern was also present, though in a different > > > form, before this commit. > > > > > > The problem here is that another earlier commit (5.13): > > > > > > a358f40600b3 once: implement DO_ONCE_LITE for non-fast-path "do once" > > > functionality > > > > > > Modifies all the pr_*_once() calls to always return true claiming that > > > no caller is ever > > > checking the return value of the functions. > > > > > > This is why we are seeing the callstack printed without the associated > > > printk() msg. > > > > > > I believe that having the pr_*_once() functions return true the first > > > time they are called > > > is useful especially when extra information, such as callstack, must > > > be printed to help > > > track the origin of the problem. > > > > > > The exception handling code seems to be the only place where the > > > return value is checked > > > for pr_warn_once(). A minimal change would be to create another > > > version of that function > > > that calls DO_ONCE() instead of DO_ONCE_LITE(), e.g., pr_warn_once_return(). > > > > > > I can post a patch to that effect if we all agree on the approach. > > > > > > Thanks. > > > > How about something like this? > > > > diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c > > index dba2197c05c3..331310c29349 100644 > > --- a/arch/x86/mm/extable.c > > +++ b/arch/x86/mm/extable.c > > @@ -94,16 +94,18 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, > > static bool ex_handler_msr(const struct exception_table_entry *fixup, > > struct pt_regs *regs, bool wrmsr, bool safe, int reg) > > { > > - if (!safe && wrmsr && > > - pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", > > - (unsigned int)regs->cx, (unsigned int)regs->dx, > > - (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) > > + if (__ONCE_LITE_IF(!safe && wrmsr)) { > > + pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", > > + (unsigned int)regs->cx, (unsigned int)regs->dx, > > + (unsigned int)regs->ax, regs->ip, (void *)regs->ip); > > show_stack_regs(regs); > > + } > > > > - if (!safe && !wrmsr && > > - pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", > > - (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) > > + if (__ONCE_LITE_IF(!safe && !wrmsr)) { > > + pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", > > + (unsigned int)regs->cx, regs->ip, (void *)regs->ip); > > show_stack_regs(regs); > > + } > > > > if (!wrmsr) { > > /* Pretend that the read succeeded and returned 0. */ > > diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h > > index 861e606b820f..63c3bbcef694 100644 > > --- a/include/linux/once_lite.h > > +++ b/include/linux/once_lite.h > > @@ -9,15 +9,27 @@ > > */ > > #define DO_ONCE_LITE(func, ...) \ > > DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) > > -#define DO_ONCE_LITE_IF(condition, func, ...) \ > > + > > +#define __ONCE_LITE_IF(condition) \ > > ({ \ > > static bool __section(".data.once") __already_done; \ > > - bool __ret_do_once = !!(condition); \ > > + bool __ret_cond = !!(condition); \ > > + bool __ret_once = false; \ > > \ > > if (unlikely(__ret_do_once && !__already_done)) { \ You need to replace __ret_do_once with __ret_cond above and then it compiles and works. I have tested with a kernel module that reads and writes to an illegal MSR: unchecked MSR access error: RDMSR from 0x1234567 at rIP: 0xffffffffc00ec138 (rdpmc_intel+0x28/0x21d0 [rdpmc_test]) Call Trace: <TASK> rdpmc_bench_store+0x53/0x80 [rdpmc_test] kobj_attr_store+0xf/0x20 sysfs_kf_write+0x34/0x50 kernfs_fop_write_iter+0xfa/0x180 vfs_write+0x334/0x3d0 ksys_write+0x71/0xe0 __x64_sys_write+0x1b/0x20 do_syscall_64+0x44/0xa0 ? exc_page_fault+0x6e/0x110 entry_SYSCALL_64_after_hwframe+0x63/0xcd Tested-by: Stephane Eranian <eranian@google.com> > > > __already_done = true; \ > > - func(__VA_ARGS__); \ > > + __ret_once = true; \ > > } \ > > + unlikely(__ret_once); \ > > + }) > > + > > +#define DO_ONCE_LITE_IF(condition, func, ...) \ > > + ({ \ > > + bool __ret_do_once = !!(condition); \ > > + \ > > + if (__ONCE_LITE_IF(__ret_do_once)) \ > > + func(__VA_ARGS__); \ > > + \ > > unlikely(__ret_do_once); \ > > }) > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] x86/extable: Fix ex_handler_msr() print condition 2022-07-20 12:48 ` Stephane Eranian @ 2022-07-20 13:44 ` Peter Zijlstra 0 siblings, 0 replies; 6+ messages in thread From: Peter Zijlstra @ 2022-07-20 13:44 UTC (permalink / raw) To: Stephane Eranian Cc: LKML, Eric Dumazet, jpoimboe, Steven Rostedt, tannerlove, maheshb On Wed, Jul 20, 2022 at 03:48:56PM +0300, Stephane Eranian wrote: > Tested-by: Stephane Eranian <eranian@google.com> Thanks, I'll queue the below. --- Subject: x86/extable: Fix ex_handler_msr() print condition From: Peter Zijlstra <peterz@infradead.org> Date: Fri, 17 Jun 2022 16:52:06 +0200 On Fri, Jun 17, 2022 at 02:08:52PM +0300, Stephane Eranian wrote: > Some changes to the way invalid MSR accesses are reported by the > kernel is causing some problems with messages printed on the > console. > > We have seen several cases of ex_handler_msr() printing invalid MSR > accesses once but the callstack multiple times causing confusion on > the console. > The problem here is that another earlier commit (5.13): > > a358f40600b3 ("once: implement DO_ONCE_LITE for non-fast-path "do once" functionality") > > Modifies all the pr_*_once() calls to always return true claiming > that no caller is ever checking the return value of the functions. > > This is why we are seeing the callstack printed without the > associated printk() msg. Extract the ONCE_IF(cond) part into __ONCE_LTE_IF() and use that to implement DO_ONCE_LITE_IF() and fix the extable code. Fixes: a358f40600b3 ("once: implement DO_ONCE_LITE for non-fast-path "do once" functionality") Reported-by: Stephane Eranian <eranian@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Stephane Eranian <eranian@google.com> Link: https://lkml.kernel.org/r/YqyVFsbviKjVGGZ9@worktop.programming.kicks-ass.net --- arch/x86/mm/extable.c | 16 +++++++++------- include/linux/once_lite.h | 20 ++++++++++++++++---- 2 files changed, 25 insertions(+), 11 deletions(-) --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -94,16 +94,18 @@ static bool ex_handler_copy(const struct static bool ex_handler_msr(const struct exception_table_entry *fixup, struct pt_regs *regs, bool wrmsr, bool safe, int reg) { - if (!safe && wrmsr && - pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", - (unsigned int)regs->cx, (unsigned int)regs->dx, - (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) + if (__ONCE_LITE_IF(!safe && wrmsr)) { + pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, (unsigned int)regs->dx, + (unsigned int)regs->ax, regs->ip, (void *)regs->ip); show_stack_regs(regs); + } - if (!safe && !wrmsr && - pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", - (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) + if (__ONCE_LITE_IF(!safe && !wrmsr)) { + pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, regs->ip, (void *)regs->ip); show_stack_regs(regs); + } if (!wrmsr) { /* Pretend that the read succeeded and returned 0. */ --- a/include/linux/once_lite.h +++ b/include/linux/once_lite.h @@ -9,15 +9,27 @@ */ #define DO_ONCE_LITE(func, ...) \ DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) -#define DO_ONCE_LITE_IF(condition, func, ...) \ + +#define __ONCE_LITE_IF(condition) \ ({ \ static bool __section(".data.once") __already_done; \ - bool __ret_do_once = !!(condition); \ + bool __ret_cond = !!(condition); \ + bool __ret_once = false; \ \ - if (unlikely(__ret_do_once && !__already_done)) { \ + if (unlikely(__ret_cond && !__already_done)) { \ __already_done = true; \ - func(__VA_ARGS__); \ + __ret_once = true; \ } \ + unlikely(__ret_once); \ + }) + +#define DO_ONCE_LITE_IF(condition, func, ...) \ + ({ \ + bool __ret_do_once = !!(condition); \ + \ + if (__ONCE_LITE_IF(__ret_do_once)) \ + func(__VA_ARGS__); \ + \ unlikely(__ret_do_once); \ }) ^ permalink raw reply [flat|nested] 6+ messages in thread
* [tip: x86/core] x86/extable: Fix ex_handler_msr() print condition 2022-06-17 14:52 ` Peter Zijlstra 2022-06-22 17:51 ` Stephane Eranian @ 2022-07-21 8:52 ` tip-bot2 for Peter Zijlstra 1 sibling, 0 replies; 6+ messages in thread From: tip-bot2 for Peter Zijlstra @ 2022-07-21 8:52 UTC (permalink / raw) To: linux-tip-commits Cc: Stephane Eranian, Peter Zijlstra (Intel), x86, linux-kernel The following commit has been merged into the x86/core branch of tip: Commit-ID: a1a5482a2c6e38a3ebed32e571625c56a8cc41a6 Gitweb: https://git.kernel.org/tip/a1a5482a2c6e38a3ebed32e571625c56a8cc41a6 Author: Peter Zijlstra <peterz@infradead.org> AuthorDate: Fri, 17 Jun 2022 16:52:06 +02:00 Committer: Peter Zijlstra <peterz@infradead.org> CommitterDate: Thu, 21 Jul 2022 10:39:42 +02:00 x86/extable: Fix ex_handler_msr() print condition On Fri, Jun 17, 2022 at 02:08:52PM +0300, Stephane Eranian wrote: > Some changes to the way invalid MSR accesses are reported by the > kernel is causing some problems with messages printed on the > console. > > We have seen several cases of ex_handler_msr() printing invalid MSR > accesses once but the callstack multiple times causing confusion on > the console. > The problem here is that another earlier commit (5.13): > > a358f40600b3 ("once: implement DO_ONCE_LITE for non-fast-path "do once" functionality") > > Modifies all the pr_*_once() calls to always return true claiming > that no caller is ever checking the return value of the functions. > > This is why we are seeing the callstack printed without the > associated printk() msg. Extract the ONCE_IF(cond) part into __ONCE_LTE_IF() and use that to implement DO_ONCE_LITE_IF() and fix the extable code. Fixes: a358f40600b3 ("once: implement DO_ONCE_LITE for non-fast-path "do once" functionality") Reported-by: Stephane Eranian <eranian@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Stephane Eranian <eranian@google.com> Link: https://lkml.kernel.org/r/YqyVFsbviKjVGGZ9@worktop.programming.kicks-ass.net --- arch/x86/mm/extable.c | 16 +++++++++------- include/linux/once_lite.h | 20 ++++++++++++++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index dba2197..331310c 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -94,16 +94,18 @@ static bool ex_handler_copy(const struct exception_table_entry *fixup, static bool ex_handler_msr(const struct exception_table_entry *fixup, struct pt_regs *regs, bool wrmsr, bool safe, int reg) { - if (!safe && wrmsr && - pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", - (unsigned int)regs->cx, (unsigned int)regs->dx, - (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) + if (__ONCE_LITE_IF(!safe && wrmsr)) { + pr_warn("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, (unsigned int)regs->dx, + (unsigned int)regs->ax, regs->ip, (void *)regs->ip); show_stack_regs(regs); + } - if (!safe && !wrmsr && - pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", - (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) + if (__ONCE_LITE_IF(!safe && !wrmsr)) { + pr_warn("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", + (unsigned int)regs->cx, regs->ip, (void *)regs->ip); show_stack_regs(regs); + } if (!wrmsr) { /* Pretend that the read succeeded and returned 0. */ diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h index 861e606..b7bce49 100644 --- a/include/linux/once_lite.h +++ b/include/linux/once_lite.h @@ -9,15 +9,27 @@ */ #define DO_ONCE_LITE(func, ...) \ DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__) -#define DO_ONCE_LITE_IF(condition, func, ...) \ + +#define __ONCE_LITE_IF(condition) \ ({ \ static bool __section(".data.once") __already_done; \ - bool __ret_do_once = !!(condition); \ + bool __ret_cond = !!(condition); \ + bool __ret_once = false; \ \ - if (unlikely(__ret_do_once && !__already_done)) { \ + if (unlikely(__ret_cond && !__already_done)) { \ __already_done = true; \ - func(__VA_ARGS__); \ + __ret_once = true; \ } \ + unlikely(__ret_once); \ + }) + +#define DO_ONCE_LITE_IF(condition, func, ...) \ + ({ \ + bool __ret_do_once = !!(condition); \ + \ + if (__ONCE_LITE_IF(__ret_do_once)) \ + func(__VA_ARGS__); \ + \ unlikely(__ret_do_once); \ }) ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-07-21 8:52 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-06-17 11:08 [RFC] pr_warn_once() issue in x86 MSR extable code Stephane Eranian 2022-06-17 14:52 ` Peter Zijlstra 2022-06-22 17:51 ` Stephane Eranian 2022-07-20 12:48 ` Stephane Eranian 2022-07-20 13:44 ` [PATCH] x86/extable: Fix ex_handler_msr() print condition Peter Zijlstra 2022-07-21 8:52 ` [tip: x86/core] " tip-bot2 for Peter Zijlstra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).