All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 related	[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 related	[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 related	[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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.