Skip to content

Commit

Permalink
ARC: show_regs: lockdep: avoid page allocator...
Browse files Browse the repository at this point in the history
[ Upstream commit ab6c036 ]

and use smaller/on-stack buffer instead

The motivation for this change was lockdep splat like below.

| potentially unexpected fatal signal 11.
| BUG: sleeping function called from invalid context at ../mm/page_alloc.c:4317
| in_atomic(): 1, irqs_disabled(): 0, pid: 57, name: segv
| no locks held by segv/57.
| Preemption disabled at:
| [<8182f17e>] get_signal+0x4a6/0x7c4
| CPU: 0 PID: 57 Comm: segv Not tainted 4.17.0+ #23
|
| Stack Trace:
|  arc_unwind_core.constprop.1+0xd0/0xf4
|  __might_sleep+0x1f6/0x234
|  __get_free_pages+0x174/0xca0
|  show_regs+0x22/0x330
|  get_signal+0x4ac/0x7c4     # print_fatal_signals() -> preempt_disable()
|  do_signal+0x30/0x224
|  resume_user_mode_begin+0x90/0xd8

So signal handling core calls show_regs() with preemption disabled but
an ensuing GFP_KERNEL page allocator call is flagged by lockdep.

We could have switched to GFP_NOWAIT, but turns out that is not enough
anways and eliding page allocator call leads to less code and
instruction traces to sift thru when debugging pesky crashes.

FWIW, this patch doesn't cure the lockdep splat (which next patch does).

Reviewed-by: William Kucharski <william.kucharski@oracle.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
vineetgarc authored and gregkh committed Mar 5, 2019
1 parent 4e34dd3 commit 4749ffd
Showing 1 changed file with 12 additions and 14 deletions.
26 changes: 12 additions & 14 deletions arch/arc/kernel/troubleshoot.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <asm/arcregs.h>
#include <asm/irqflags.h>

#define ARC_PATH_MAX 256

/*
* Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
* -Prints 3 regs per line and a CR.
Expand Down Expand Up @@ -58,11 +60,12 @@ static void show_callee_regs(struct callee_regs *cregs)
print_reg_file(&(cregs->r13), 13);
}

static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
static void print_task_path_n_nm(struct task_struct *tsk)
{
char *path_nm = NULL;
struct mm_struct *mm;
struct file *exe_file;
char buf[ARC_PATH_MAX];

mm = get_task_mm(tsk);
if (!mm)
Expand All @@ -72,18 +75,17 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
mmput(mm);

if (exe_file) {
path_nm = file_path(exe_file, buf, 255);
path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
fput(exe_file);
}

done:
pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
}

static void show_faulting_vma(unsigned long address, char *buf)
static void show_faulting_vma(unsigned long address)
{
struct vm_area_struct *vma;
char *nm = buf;
struct mm_struct *active_mm = current->active_mm;

/* can't use print_vma_addr() yet as it doesn't check for
Expand All @@ -96,8 +98,11 @@ static void show_faulting_vma(unsigned long address, char *buf)
* if the container VMA is not found
*/
if (vma && (vma->vm_start <= address)) {
char buf[ARC_PATH_MAX];
char *nm = "?";

if (vma->vm_file) {
nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1);
nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
if (IS_ERR(nm))
nm = "?";
}
Expand Down Expand Up @@ -173,13 +178,8 @@ void show_regs(struct pt_regs *regs)
{
struct task_struct *tsk = current;
struct callee_regs *cregs;
char *buf;

buf = (char *)__get_free_page(GFP_KERNEL);
if (!buf)
return;

print_task_path_n_nm(tsk, buf);
print_task_path_n_nm(tsk);
show_regs_print_info(KERN_INFO);

show_ecr_verbose(regs);
Expand All @@ -189,7 +189,7 @@ void show_regs(struct pt_regs *regs)
(void *)regs->blink, (void *)regs->ret);

if (user_mode(regs))
show_faulting_vma(regs->ret, buf); /* faulting code, not data */
show_faulting_vma(regs->ret); /* faulting code, not data */

pr_info("[STAT32]: 0x%08lx", regs->status32);

Expand Down Expand Up @@ -221,8 +221,6 @@ void show_regs(struct pt_regs *regs)
cregs = (struct callee_regs *)current->thread.callee_reg;
if (cregs)
show_callee_regs(cregs);

free_page((unsigned long)buf);
}

void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
Expand Down

0 comments on commit 4749ffd

Please sign in to comment.