* [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr
@ 2020-08-14 17:53 Joe Perches
2020-08-14 18:38 ` Steven Rostedt
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Joe Perches @ 2020-08-14 17:53 UTC (permalink / raw)
To: LKML
Cc: Petr Mladek, Steven Rostedt, Sergey Senozhatsky, Andy Shevchenko,
Rasmus Villemoes
There is a print_vma_addr function used several places
that requires KERN_CONT use.
Add a %pv mechanism to avoid the need for KERN_CONT.
An example conversion is arch/x86/kernel/signal.c
from:
if (show_unhandled_signals && printk_ratelimit()) {
printk("%s"
"%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx",
task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
me->comm, me->pid, where, frame,
regs->ip, regs->sp, regs->orig_ax);
print_vma_addr(KERN_CONT " in ", regs->ip);
pr_cont("\n");
to:
printk("%s"
"%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx in %pv\n",
task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
me->comm, me->pid, where, frame,
regs->ip, regs->sp, regs->orig_ax, (void *)regs->ip);
---
lib/vsprintf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index c155769559ab..654402c43f8d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -995,6 +995,12 @@ static const struct printf_spec default_dec_spec = {
.precision = -1,
};
+static const struct printf_spec default_hex_spec = {
+ .base = 16,
+ .precision = -1,
+ .flags = SMALL,
+};
+
static const struct printf_spec default_dec02_spec = {
.base = 10,
.field_width = 2,
@@ -2089,6 +2095,50 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
return widen_string(buf, buf - buf_start, end, spec);
}
+static noinline_for_stack
+char *vma_addr(char *buf, char *end, void *ip,
+ struct printf_spec spec, const char *fmt)
+{
+#ifdef CONFIG_MMU
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+
+ /*
+ * we might be running from an atomic context so we cannot sleep
+ */
+ if (!mmap_read_trylock(mm))
+ return buf;
+
+ vma = find_vma(mm, (unsigned long)ip);
+ if (vma && vma->vm_file) {
+ char *p;
+ struct file *f = vma->vm_file;
+ char *page = (char *)__get_free_page(GFP_NOWAIT);
+
+ if (page) {
+ p = file_path(f, page, PAGE_SIZE);
+ if (IS_ERR(p))
+ p = "?";
+ buf = string(buf, end, kbasename(p), default_str_spec);
+ buf = string_nocheck(buf, end, "[", default_str_spec);
+ buf = pointer_string(buf, end,
+ (void *)vma->vm_start,
+ default_hex_spec);
+ buf = string_nocheck(buf, end, "+", default_str_spec);
+ buf = pointer_string(buf, end,
+ (void *)(vma->vm_end - vma->vm_start),
+ default_hex_spec);
+ buf = string_nocheck(buf, end, "]", default_str_spec);
+ free_page((unsigned long)page);
+ }
+ }
+ mmap_read_unlock(mm);
+#else
+ buf = string_nocheck(buf, end, "CONFIG_MMU=n", default_str_spec);
+#endif
+ return buf;
+}
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
@@ -2254,6 +2304,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return uuid_string(buf, end, ptr, spec, fmt);
case 'V':
return va_format(buf, end, ptr, spec, fmt);
+ case 'v':
+ return vma_addr(buf, end, ptr, spec, fmt);
case 'K':
return restricted_pointer(buf, end, ptr, spec);
case 'N':
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr 2020-08-14 17:53 [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr Joe Perches @ 2020-08-14 18:38 ` Steven Rostedt 2020-08-14 19:24 ` Joe Perches 2020-08-15 3:52 ` Sergey Senozhatsky 2020-08-17 11:44 ` Andy Shevchenko 2 siblings, 1 reply; 7+ messages in thread From: Steven Rostedt @ 2020-08-14 18:38 UTC (permalink / raw) To: Joe Perches Cc: LKML, Petr Mladek, Sergey Senozhatsky, Andy Shevchenko, Rasmus Villemoes On Fri, 14 Aug 2020 10:53:03 -0700 Joe Perches <joe@perches.com> wrote: > There is a print_vma_addr function used several places > that requires KERN_CONT use. > > Add a %pv mechanism to avoid the need for KERN_CONT. > > An example conversion is arch/x86/kernel/signal.c > > from: > if (show_unhandled_signals && printk_ratelimit()) { > printk("%s" > "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", > task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, > me->comm, me->pid, where, frame, > regs->ip, regs->sp, regs->orig_ax); > print_vma_addr(KERN_CONT " in ", regs->ip); > pr_cont("\n"); > to: > printk("%s" > "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx in %pv\n", > task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, > me->comm, me->pid, where, frame, > regs->ip, regs->sp, regs->orig_ax, (void *)regs->ip); > --- > lib/vsprintf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 52 insertions(+) > > diff --git a/lib/vsprintf.c b/lib/vsprintf.c > index c155769559ab..654402c43f8d 100644 > --- a/lib/vsprintf.c > +++ b/lib/vsprintf.c > @@ -995,6 +995,12 @@ static const struct printf_spec default_dec_spec = { > .precision = -1, > }; > > +static const struct printf_spec default_hex_spec = { > + .base = 16, > + .precision = -1, > + .flags = SMALL, > +}; > + > static const struct printf_spec default_dec02_spec = { > .base = 10, > .field_width = 2, > @@ -2089,6 +2095,50 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode, > return widen_string(buf, buf - buf_start, end, spec); > } > > +static noinline_for_stack > +char *vma_addr(char *buf, char *end, void *ip, > + struct printf_spec spec, const char *fmt) > +{ > +#ifdef CONFIG_MMU > + struct mm_struct *mm = current->mm; > + struct vm_area_struct *vma; > + > + /* > + * we might be running from an atomic context so we cannot sleep > + */ > + if (!mmap_read_trylock(mm)) > + return buf; > + > + vma = find_vma(mm, (unsigned long)ip); > + if (vma && vma->vm_file) { > + char *p; > + struct file *f = vma->vm_file; > + char *page = (char *)__get_free_page(GFP_NOWAIT); > + > + if (page) { > + p = file_path(f, page, PAGE_SIZE); > + if (IS_ERR(p)) > + p = "?"; > + buf = string(buf, end, kbasename(p), default_str_spec); > + buf = string_nocheck(buf, end, "[", default_str_spec); > + buf = pointer_string(buf, end, > + (void *)vma->vm_start, > + default_hex_spec); > + buf = string_nocheck(buf, end, "+", default_str_spec); > + buf = pointer_string(buf, end, > + (void *)(vma->vm_end - vma->vm_start), > + default_hex_spec); > + buf = string_nocheck(buf, end, "]", default_str_spec); > + free_page((unsigned long)page); > + } > + } > + mmap_read_unlock(mm); > +#else > + buf = string_nocheck(buf, end, "CONFIG_MMU=n", default_str_spec); > +#endif I'm fine with all his, but I feel more comfortable if this patch created a single copy of the code. Perhaps add: diff --git a/mm/memory.c b/mm/memory.c index 87ec87cdc1ff..795a4db4d83d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4771,32 +4771,7 @@ EXPORT_SYMBOL_GPL(access_process_vm); */ void print_vma_addr(char *prefix, unsigned long ip) { - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - - /* - * we might be running from an atomic context so we cannot sleep - */ - if (!mmap_read_trylock(mm)) - return; - - vma = find_vma(mm, ip); - if (vma && vma->vm_file) { - struct file *f = vma->vm_file; - char *buf = (char *)__get_free_page(GFP_NOWAIT); - if (buf) { - char *p; - - p = file_path(f, buf, PAGE_SIZE); - if (IS_ERR(p)) - p = "?"; - printk("%s%s[%lx+%lx]", prefix, kbasename(p), - vma->vm_start, - vma->vm_end - vma->vm_start); - free_page((unsigned long)buf); - } - } - mmap_read_unlock(mm); + printk("%s%pv", prefix, ip); } #if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP) And of course this would need for documentation. -- Steve > + return buf; > +} > + > /* > * Show a '%p' thing. A kernel extension is that the '%p' is followed > * by an extra set of alphanumeric characters that are extended format > @@ -2254,6 +2304,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, > return uuid_string(buf, end, ptr, spec, fmt); > case 'V': > return va_format(buf, end, ptr, spec, fmt); > + case 'v': > + return vma_addr(buf, end, ptr, spec, fmt); > case 'K': > return restricted_pointer(buf, end, ptr, spec); > case 'N': > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr 2020-08-14 18:38 ` Steven Rostedt @ 2020-08-14 19:24 ` Joe Perches 0 siblings, 0 replies; 7+ messages in thread From: Joe Perches @ 2020-08-14 19:24 UTC (permalink / raw) To: Steven Rostedt Cc: LKML, Petr Mladek, Sergey Senozhatsky, Andy Shevchenko, Rasmus Villemoes On Fri, 2020-08-14 at 14:38 -0400, Steven Rostedt wrote: > On Fri, 14 Aug 2020 10:53:03 -0700 > Joe Perches <joe@perches.com> wrote: > I'm fine with all his, but I feel more comfortable if this patch > created a single copy of the code. Perhaps add: [] > diff --git a/mm/memory.c b/mm/memory.c [] > @@ -4771,32 +4771,7 @@ EXPORT_SYMBOL_GPL(access_process_vm); > */ > void print_vma_addr(char *prefix, unsigned long ip) > { > - struct mm_struct *mm = current->mm; > - struct vm_area_struct *vma; > - > - /* > - * we might be running from an atomic context so we cannot sleep > - */ > - if (!mmap_read_trylock(mm)) > - return; > - > - vma = find_vma(mm, ip); > - if (vma && vma->vm_file) { > - struct file *f = vma->vm_file; > - char *buf = (char *)__get_free_page(GFP_NOWAIT); > - if (buf) { > - char *p; > - > - p = file_path(f, buf, PAGE_SIZE); > - if (IS_ERR(p)) > - p = "?"; > - printk("%s%s[%lx+%lx]", prefix, kbasename(p), > - vma->vm_start, > - vma->vm_end - vma->vm_start); > - free_page((unsigned long)buf); > - } > - } > - mmap_read_unlock(mm); > + printk("%s%pv", prefix, ip); > } I'd just convert all of them and remove this function instead. Something like (uncompiled/untested): --- arch/arc/kernel/troubleshoot.c | 2 +- arch/arm64/kernel/traps.c | 16 +++++++------ arch/csky/kernel/traps.c | 11 ++++----- arch/mips/mm/fault.c | 14 +++++------ arch/parisc/mm/fault.c | 15 +++++------- arch/powerpc/kernel/traps.c | 8 ++----- arch/riscv/kernel/traps.c | 11 ++++----- arch/s390/mm/fault.c | 7 +++--- arch/sparc/mm/fault_32.c | 8 ++----- arch/sparc/mm/fault_64.c | 8 ++----- arch/um/kernel/trap.c | 13 ++++------- arch/x86/kernel/signal.c | 6 ++--- arch/x86/kernel/traps.c | 6 ++--- arch/x86/mm/fault.c | 53 +++++++++++++++++++----------------------- include/linux/mm.h | 7 ------ mm/memory.c | 33 -------------------------- 16 files changed, 74 insertions(+), 144 deletions(-) diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 28e8bf04b253..26ecd59f0057 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -86,7 +86,7 @@ static void show_faulting_vma(unsigned long address) struct vm_area_struct *vma; struct mm_struct *active_mm = current->active_mm; - /* can't use print_vma_addr() yet as it doesn't check for + /* can't use %pv yet as it doesn't check for * non-inclusive vma */ mmap_read_lock(active_mm); diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 13ebd5ca2070..294ed81f67d8 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -224,13 +224,15 @@ static void arm64_show_signal(int signo, const char *str) !__ratelimit(&rs)) return; - pr_info("%s[%d]: unhandled exception: ", tsk->comm, task_pid_nr(tsk)); - if (esr) - pr_cont("%s, ESR 0x%08x, ", esr_get_class_string(esr), esr); - - pr_cont("%s", str); - print_vma_addr(KERN_CONT " in ", regs->pc); - pr_cont("\n"); + if (esr) { + pr_info("%s[%d]: unhandled exception: %s, ESR 0x%08x, %s in %pv\n", + tsk->comm, task_pid_nr(tsk), + esr_get_class_string(esr), esr, + str, (void *)regs->pc); + } else { + pr_info("%s[%d]: unhandled exception: %s in %pv\n", + tsk->comm, task_pid_nr(tsk), str, (void *)regs->pc); + } __show_regs(regs); } diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c index 959a917c989d..bdf1577237df 100644 --- a/arch/csky/kernel/traps.c +++ b/arch/csky/kernel/traps.c @@ -118,12 +118,11 @@ void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr) { struct task_struct *tsk = current; - if (show_unhandled_signals && unhandled_signal(tsk, signo) - && printk_ratelimit()) { - pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx", - tsk->comm, task_pid_nr(tsk), signo, code, addr); - print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); - pr_cont("\n"); + if (show_unhandled_signals && unhandled_signal(tsk, signo) && + printk_ratelimit()) { + pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx in %pv\n", + tsk->comm, task_pid_nr(tsk), signo, code, addr, + (void *)instruction_pointer(regs)); show_regs(regs); } diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 7c871b14e74a..cd87d11d57dc 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -204,14 +204,12 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, tsk->comm, write ? "write access to" : "read access from", field, address); - pr_info("epc = %0*lx in", field, - (unsigned long) regs->cp0_epc); - print_vma_addr(KERN_CONT " ", regs->cp0_epc); - pr_cont("\n"); - pr_info("ra = %0*lx in", field, - (unsigned long) regs->regs[31]); - print_vma_addr(KERN_CONT " ", regs->regs[31]); - pr_cont("\n"); + pr_info("epc = %0*lx in %pv\n", + field, (unsigned long)regs->cp0_epc, + (void *)(unsigned long)regs->cp0_epc); + pr_info("ra = %0*lx in %pv\n", + field, (unsigned long)regs->regs[31], + (void *)(unsigned long)regs->regs[31]); } current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f; force_sig_fault(SIGSEGV, si_code, (void __user *)address); diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 4bfe2da9fbe3..3d519fb80541 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -242,17 +242,14 @@ show_signal_msg(struct pt_regs *regs, unsigned long code, if (!printk_ratelimit()) return; - pr_warn("\n"); - pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx", - tsk->comm, code, address); - print_vma_addr(KERN_CONT " in ", regs->iaoq[0]); - - pr_cont("\ntrap #%lu: %s%c", code, trap_name(code), - vma ? ',':'\n'); + pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx in %pv\n", + tsk->comm, code, address, (void *)regs->iaoq[0]); if (vma) - pr_cont(" vm_start = 0x%08lx, vm_end = 0x%08lx\n", - vma->vm_start, vma->vm_end); + pr_warn("trap #%lu: %s, vm_start = 0x%08lx, vm_end = 0x%08lx\n", + code, trap_name(code), vma->vm_start, vma->vm_end); + else + pr_warn("trap #%lu: %s\n", code, trap_name(code)); show_regs(regs); } diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index d1ebe152f210..a21bad3c059b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -321,13 +321,9 @@ static void show_signal_msg(int signr, struct pt_regs *regs, int code, if (!__ratelimit(&rs)) return; - pr_info("%s[%d]: %s (%d) at %lx nip %lx lr %lx code %x", + pr_info("%s[%d]: %s (%d) at %lx nip %lx lr %lx code %x in %pv\n", current->comm, current->pid, signame(signr), signr, - addr, regs->nip, regs->link, code); - - print_vma_addr(KERN_CONT " in ", regs->nip); - - pr_cont("\n"); + addr, regs->nip, regs->link, code, (void *)regs->nip); show_user_instructions(regs); } diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index ad14f4466d92..c08d80b18e33 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -60,12 +60,11 @@ void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr) { struct task_struct *tsk = current; - if (show_unhandled_signals && unhandled_signal(tsk, signo) - && printk_ratelimit()) { - pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x" REG_FMT, - tsk->comm, task_pid_nr(tsk), signo, code, addr); - print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); - pr_cont("\n"); + if (show_unhandled_signals && unhandled_signal(tsk, signo) && + printk_ratelimit()) { + pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x" REG_FMT " in %pv\n", + tsk->comm, task_pid_nr(tsk), signo, code, addr, + (void *)instruction_pointer(regs)); show_regs(regs); } diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 4c8c063bce5b..4726a440dfdd 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -217,10 +217,9 @@ void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault) return; if (!printk_ratelimit()) return; - printk(KERN_ALERT "User process fault: interruption code %04x ilc:%d ", - regs->int_code & 0xffff, regs->int_code >> 17); - print_vma_addr(KERN_CONT "in ", regs->psw.addr); - printk(KERN_CONT "\n"); + pr_alert("User process fault: interruption code %04x ilc:%d in %pv\n", + regs->int_code & 0xffff, regs->int_code >> 17, + (void *)regs->psw.addr); if (is_mm_fault) dump_fault_info(regs); show_regs(regs); diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index 8071bfd72349..c527d77a84d6 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -112,15 +112,11 @@ show_signal_msg(struct pt_regs *regs, int sig, int code, if (!printk_ratelimit()) return; - printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x", + printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x in %pv\n", task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, tsk->comm, task_pid_nr(tsk), address, (void *)regs->pc, (void *)regs->u_regs[UREG_I7], - (void *)regs->u_regs[UREG_FP], code); - - print_vma_addr(KERN_CONT " in ", regs->pc); - - printk(KERN_CONT "\n"); + (void *)regs->u_regs[UREG_FP], code, (void *)regs->pc); } static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs, diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 0a6bcc85fba7..bbe39cb9560b 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -143,15 +143,11 @@ show_signal_msg(struct pt_regs *regs, int sig, int code, if (!printk_ratelimit()) return; - printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x", + printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x in %pv\n", task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, tsk->comm, task_pid_nr(tsk), address, (void *)regs->tpc, (void *)regs->u_regs[UREG_I7], - (void *)regs->u_regs[UREG_FP], code); - - print_vma_addr(KERN_CONT " in ", regs->tpc); - - printk(KERN_CONT "\n"); + (void *)regs->u_regs[UREG_FP], code, (void *)regs->tpc); } static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index ad12f78bda7e..f7854e9bc06a 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -140,14 +140,11 @@ static void show_segv_info(struct uml_pt_regs *regs) if (!printk_ratelimit()) return; - printk("%s%s[%d]: segfault at %lx ip %px sp %px error %x", - task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, - tsk->comm, task_pid_nr(tsk), FAULT_ADDRESS(*fi), - (void *)UPT_IP(regs), (void *)UPT_SP(regs), - fi->error_code); - - print_vma_addr(KERN_CONT " in ", UPT_IP(regs)); - printk(KERN_CONT "\n"); + printk("%s%s[%d]: segfault at %lx ip %px sp %px error %x in %pv\n", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), FAULT_ADDRESS(*fi), + (void *)UPT_IP(regs), (void *)UPT_SP(regs), + fi->error_code, (void *)UPT_IP(regs)); } static void bad_segv(struct faultinfo fi, unsigned long ip) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index d5fa494c2304..ae7b280f4971 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -845,12 +845,10 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where) if (show_unhandled_signals && printk_ratelimit()) { printk("%s" - "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", + "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx in %pv\n", task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, me->comm, me->pid, where, frame, - regs->ip, regs->sp, regs->orig_ax); - print_vma_addr(KERN_CONT " in ", regs->ip); - pr_cont("\n"); + regs->ip, regs->sp, regs->orig_ax, (void *)regs->ip); } force_sig(SIGSEGV); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 1f66d2d1e998..426324f93929 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -139,11 +139,9 @@ static void show_signal(struct task_struct *tsk, int signr, { if (show_unhandled_signals && unhandled_signal(tsk, signr) && printk_ratelimit()) { - pr_info("%s[%d] %s%s ip:%lx sp:%lx error:%lx", + pr_info("%s[%d] %s%s ip:%lx sp:%lx error:%lx in %pv\n", tsk->comm, task_pid_nr(tsk), type, desc, - regs->ip, regs->sp, error_code); - print_vma_addr(KERN_CONT " in ", regs->ip); - pr_cont("\n"); + regs->ip, regs->sp, error_code, (void *)regs->ip); } } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 35f1498e9832..01e9b0f12092 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -246,20 +246,22 @@ static void dump_pagetable(unsigned long address) pud_t *pud; pmd_t *pmd; pte_t *pte; + char buffer[128] = '\0'; + char *p = buffer; + char *end = buffer + sizeof(buffer) - 1; #ifdef CONFIG_X86_PAE - pr_info("*pdpt = %016Lx ", pgd_val(*pgd)); + p += scnprintf(p, end - p, "%s*pdpt = %016llx", + p == buffer ? "" : " ", pgd_val(*pgd)); if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd)) goto out; -#define pr_pde pr_cont -#else -#define pr_pde pr_info #endif p4d = p4d_offset(pgd, address); pud = pud_offset(p4d, address); pmd = pmd_offset(pud, address); - pr_pde("*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd)); -#undef pr_pde + p += scnprintf(p, end - p, "%s*pde = %0*llx", + p == buffer ? "" : " ", + sizeof(*pmd) * 2, (u64)pmd_val(*pmd)); /* * We must not directly access the pte in the highpte @@ -271,20 +273,12 @@ static void dump_pagetable(unsigned long address) goto out; pte = pte_offset_kernel(pmd, address); - pr_cont("*pte = %0*Lx ", sizeof(*pte) * 2, (u64)pte_val(*pte)); + p += snprintf(p, end - p, "%s*pte = %0*llx", + p == buffer ? "" : " ", + sizeof(*pte) * 2, (u64)pte_val(*pte)); out: - pr_cont("\n"); + pr_info("%s\n", buffer); } - -#else /* CONFIG_X86_64: */ - -#ifdef CONFIG_CPU_SUP_AMD -static const char errata93_warning[] = -KERN_ERR -"******* Your BIOS seems to not contain a fix for K8 errata #93\n" -"******* Working around it, but it may cause SEGVs or burn power.\n" -"******* Please consider a BIOS update.\n" -"******* Disabling USB legacy in the BIOS may also help.\n"; #endif /* @@ -388,7 +382,11 @@ static int is_errata93(struct pt_regs *regs, unsigned long address) address |= 0xffffffffUL << 32; if ((address >= (u64)_stext && address <= (u64)_etext) || (address >= MODULES_VADDR && address <= MODULES_END)) { - printk_once(errata93_warning); + pr_err_once( +"******* Your BIOS seems to not contain a fix for K8 errata #93\n" +"******* Working around it, but it may cause SEGVs or burn power.\n" +"******* Please consider a BIOS update.\n" +"******* Disabling USB legacy in the BIOS may also help.\n"); regs->ip = address; return 1; } @@ -545,8 +543,8 @@ pgtable_bad(struct pt_regs *regs, unsigned long error_code, tsk = current; sig = SIGKILL; - printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", - tsk->comm, address); + pr_alert("%s: Corrupted page table at address %lx\n", + tsk->comm, address); dump_pagetable(address); if (__die("Bad pagetable", regs, error_code)) @@ -688,7 +686,7 @@ no_context(struct pt_regs *regs, unsigned long error_code, show_fault_oops(regs, error_code, address); if (task_stack_end_corrupted(tsk)) - printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); + pr_emerg("Thread overran stack, or stack corrupted\n"); sig = SIGKILL; if (__die("Oops", regs, error_code)) @@ -716,13 +714,10 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code, if (!printk_ratelimit()) return; - printk("%s%s[%d]: segfault at %lx ip %px sp %px error %lx", - loglvl, tsk->comm, task_pid_nr(tsk), address, - (void *)regs->ip, (void *)regs->sp, error_code); - - print_vma_addr(KERN_CONT " in ", regs->ip); - - printk(KERN_CONT "\n"); + printk("%s%s[%d]: segfault at %lx ip %px sp %px error %lx in %pv\n", + loglvl, tsk->comm, task_pid_nr(tsk), address, + (void *)regs->ip, (void *)regs->sp, error_code, + (void *)regs->ip); show_opcodes(regs, loglvl); } diff --git a/include/linux/mm.h b/include/linux/mm.h index 8ab941cf73f4..b04cd8a59c8b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2951,13 +2951,6 @@ extern int randomize_va_space; #endif const char * arch_vma_name(struct vm_area_struct *vma); -#ifdef CONFIG_MMU -void print_vma_addr(char *prefix, unsigned long rip); -#else -static inline void print_vma_addr(char *prefix, unsigned long rip) -{ -} -#endif void *sparse_buffer_alloc(unsigned long size); struct page * __populate_section_memmap(unsigned long pfn, diff --git a/mm/memory.c b/mm/memory.c index 747594f5225d..3df7a4a2b79c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4836,39 +4836,6 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, } EXPORT_SYMBOL_GPL(access_process_vm); -/* - * Print the name of a VMA. - */ -void print_vma_addr(char *prefix, unsigned long ip) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - - /* - * we might be running from an atomic context so we cannot sleep - */ - if (!mmap_read_trylock(mm)) - return; - - vma = find_vma(mm, ip); - if (vma && vma->vm_file) { - struct file *f = vma->vm_file; - char *buf = (char *)__get_free_page(GFP_NOWAIT); - if (buf) { - char *p; - - p = file_path(f, buf, PAGE_SIZE); - if (IS_ERR(p)) - p = "?"; - printk("%s%s[%lx+%lx]", prefix, kbasename(p), - vma->vm_start, - vma->vm_end - vma->vm_start); - free_page((unsigned long)buf); - } - } - mmap_read_unlock(mm); -} - #if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP) void __might_fault(const char *file, int line) { ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr 2020-08-14 17:53 [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr Joe Perches 2020-08-14 18:38 ` Steven Rostedt @ 2020-08-15 3:52 ` Sergey Senozhatsky 2020-08-15 4:18 ` Joe Perches 2020-08-17 11:44 ` Andy Shevchenko 2 siblings, 1 reply; 7+ messages in thread From: Sergey Senozhatsky @ 2020-08-15 3:52 UTC (permalink / raw) To: Joe Perches Cc: LKML, Petr Mladek, Steven Rostedt, Sergey Senozhatsky, Andy Shevchenko, Rasmus Villemoes, John Ogness Cc-ing John On (20/08/14 10:53), Joe Perches wrote: [..] In general, the idea looks nice. > +static noinline_for_stack > +char *vma_addr(char *buf, char *end, void *ip, > + struct printf_spec spec, const char *fmt) > +{ > +#ifdef CONFIG_MMU > + struct mm_struct *mm = current->mm; > + struct vm_area_struct *vma; > + > + /* > + * we might be running from an atomic context so we cannot sleep > + */ > + if (!mmap_read_trylock(mm)) > + return buf; > + > + vma = find_vma(mm, (unsigned long)ip); > + if (vma && vma->vm_file) { > + char *p; > + struct file *f = vma->vm_file; > + char *page = (char *)__get_free_page(GFP_NOWAIT); Hmm, this is huge. For the time being this is going to introduce lock inversion chains: PRINTK -> printk_locks -> MM -> mm_locks vs MM -> mm_locks -> PRINTK -> printk_locks Another thing to mention is PRINTK -> printk_locks -> MM (WANR_ON/etc) -> PRINTK we are in printk_safe, currently, but that's going to change. We might not be ready to take this as of now, but things can change once we drop printk_locks. > + if (page) { > + p = file_path(f, page, PAGE_SIZE); > + if (IS_ERR(p)) > + p = "?"; > + buf = string(buf, end, kbasename(p), default_str_spec); > + buf = string_nocheck(buf, end, "[", default_str_spec); > + buf = pointer_string(buf, end, > + (void *)vma->vm_start, > + default_hex_spec); > + buf = string_nocheck(buf, end, "+", default_str_spec); > + buf = pointer_string(buf, end, > + (void *)(vma->vm_end - vma->vm_start), > + default_hex_spec); > + buf = string_nocheck(buf, end, "]", default_str_spec); > + free_page((unsigned long)page); > + } > + } > + mmap_read_unlock(mm); > +#else > + buf = string_nocheck(buf, end, "CONFIG_MMU=n", default_str_spec); Hmm, we don't usually do that CONFIG_FOO=n thing, I think we just need to skip %pv and print nothing. Otherwise on !CONFIG_MMU systems the logbuf may contain a number of CONFIG_MMU=n messages, which are hardly useful. > +#endif > + return buf; > +} > + > /* > * Show a '%p' thing. A kernel extension is that the '%p' is followed > * by an extra set of alphanumeric characters that are extended format > @@ -2254,6 +2304,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, > return uuid_string(buf, end, ptr, spec, fmt); > case 'V': > return va_format(buf, end, ptr, spec, fmt); + #ifdef CONFIG_MMU > + case 'v': > + return vma_addr(buf, end, ptr, spec, fmt); + #endif > case 'K': > return restricted_pointer(buf, end, ptr, spec); > case 'N': -ss ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr 2020-08-15 3:52 ` Sergey Senozhatsky @ 2020-08-15 4:18 ` Joe Perches 0 siblings, 0 replies; 7+ messages in thread From: Joe Perches @ 2020-08-15 4:18 UTC (permalink / raw) To: Sergey Senozhatsky Cc: LKML, Petr Mladek, Steven Rostedt, Andy Shevchenko, Rasmus Villemoes, John Ogness On Sat, 2020-08-15 at 12:52 +0900, Sergey Senozhatsky wrote: > Cc-ing John > > On (20/08/14 10:53), Joe Perches wrote: > [..] > > In general, the idea looks nice. > > > +static noinline_for_stack > > +char *vma_addr(char *buf, char *end, void *ip, > > + struct printf_spec spec, const char *fmt) > > +{ > > +#ifdef CONFIG_MMU > > + struct mm_struct *mm = current->mm; > > + struct vm_area_struct *vma; > > + > > + /* > > + * we might be running from an atomic context so we cannot sleep > > + */ > > + if (!mmap_read_trylock(mm)) > > + return buf; > > + > > + vma = find_vma(mm, (unsigned long)ip); > > + if (vma && vma->vm_file) { > > + char *p; > > + struct file *f = vma->vm_file; > > + char *page = (char *)__get_free_page(GFP_NOWAIT); > > Hmm, this is huge. For the time being this is going to introduce lock > inversion chains: > > PRINTK -> printk_locks -> MM -> mm_locks > > vs > MM -> mm_locks -> PRINTK -> printk_locks > > Another thing to mention is > > PRINTK -> printk_locks -> MM (WANR_ON/etc) -> PRINTK > > we are in printk_safe, currently, but that's going to change. > > We might not be ready to take this as of now, but things can change > once we drop printk_locks. > > > + if (page) { > > + p = file_path(f, page, PAGE_SIZE); > > + if (IS_ERR(p)) > > + p = "?"; > > + buf = string(buf, end, kbasename(p), default_str_spec); > > + buf = string_nocheck(buf, end, "[", default_str_spec); > > + buf = pointer_string(buf, end, > > + (void *)vma->vm_start, > > + default_hex_spec); > > + buf = string_nocheck(buf, end, "+", default_str_spec); > > + buf = pointer_string(buf, end, > > + (void *)(vma->vm_end - vma->vm_start), > > + default_hex_spec); > > + buf = string_nocheck(buf, end, "]", default_str_spec); > > + free_page((unsigned long)page); > > + } > > + } > > + mmap_read_unlock(mm); > > +#else > > + buf = string_nocheck(buf, end, "CONFIG_MMU=n", default_str_spec); > > Hmm, we don't usually do that CONFIG_FOO=n thing, I think we just need > to skip %pv and print nothing. I don't. Right now, include/linux/mm.h has #ifdef CONFIG_MMU void print_vma_addr(char *prefix, unsigned long rip); #else static inline void print_vma_addr(char *prefix, unsigned long rip) { } #endif and the 'v' can't be #ifdef'd in vsprintf/pointer() otherwise %pv would fallthrough to return ptr_to_id(buf, end, ptr, spec); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr 2020-08-14 17:53 [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr Joe Perches 2020-08-14 18:38 ` Steven Rostedt 2020-08-15 3:52 ` Sergey Senozhatsky @ 2020-08-17 11:44 ` Andy Shevchenko 2020-08-17 14:39 ` Joe Perches 2 siblings, 1 reply; 7+ messages in thread From: Andy Shevchenko @ 2020-08-17 11:44 UTC (permalink / raw) To: Joe Perches Cc: LKML, Petr Mladek, Steven Rostedt, Sergey Senozhatsky, Rasmus Villemoes On Fri, Aug 14, 2020 at 10:53:03AM -0700, Joe Perches wrote: > There is a print_vma_addr function used several places > that requires KERN_CONT use. > > Add a %pv mechanism to avoid the need for KERN_CONT. I like the idea, but I would accent the selling point to make code (in the user call sites) nicer. > An example conversion is arch/x86/kernel/signal.c > > from: > if (show_unhandled_signals && printk_ratelimit()) { > printk("%s" > "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", > task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, > me->comm, me->pid, where, frame, > regs->ip, regs->sp, regs->orig_ax); > print_vma_addr(KERN_CONT " in ", regs->ip); > pr_cont("\n"); > to: > printk("%s" > "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx in %pv\n", > task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, > me->comm, me->pid, where, frame, > regs->ip, regs->sp, regs->orig_ax, (void *)regs->ip); ... > +#else > + buf = string_nocheck(buf, end, "CONFIG_MMU=n", default_str_spec); > +#endif Can we avoid this spammy message? Really it's quite long and fills valuable space in kernel buffer. I would rather print the hashed pointer as it's done for the rest of %pXXX. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr 2020-08-17 11:44 ` Andy Shevchenko @ 2020-08-17 14:39 ` Joe Perches 0 siblings, 0 replies; 7+ messages in thread From: Joe Perches @ 2020-08-17 14:39 UTC (permalink / raw) To: Andy Shevchenko Cc: LKML, Petr Mladek, Steven Rostedt, Sergey Senozhatsky, Rasmus Villemoes On Mon, 2020-08-17 at 14:44 +0300, Andy Shevchenko wrote: > On Fri, Aug 14, 2020 at 10:53:03AM -0700, Joe Perches wrote: > > There is a print_vma_addr function used several places > > that requires KERN_CONT use. > > > > Add a %pv mechanism to avoid the need for KERN_CONT. > > I like the idea, but I would accent the selling point to make code > (in the user call sites) nicer. [] > > +#else > > + buf = string_nocheck(buf, end, "CONFIG_MMU=n", default_str_spec); > > +#endif > > Can we avoid this spammy message? Really it's quite long and fills valuable > space in kernel buffer. I would rather print the hashed pointer as it's done > for the rest of %pXXX. Don't see why not. I believe it'd just use buf = ptr_to_id(buf, end, ip, spec); instead ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-08-17 14:39 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-08-14 17:53 [RFC PATCH] vsprintf: Add %pv extension replacement for print_vma_addr Joe Perches 2020-08-14 18:38 ` Steven Rostedt 2020-08-14 19:24 ` Joe Perches 2020-08-15 3:52 ` Sergey Senozhatsky 2020-08-15 4:18 ` Joe Perches 2020-08-17 11:44 ` Andy Shevchenko 2020-08-17 14:39 ` Joe Perches
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®