Skip to content

Commit 67ce16e

Browse files
kristina-martsenkowildea01
authored andcommitted
arm64: mm: print out correct page table entries
When we take a fault that can't be handled, we print out the page table entries associated with the faulting address. In some cases we currently print out the wrong entries. For a faulting TTBR1 address, we sometimes print out TTBR0 table entries instead, and for a faulting TTBR0 address we sometimes print out TTBR1 table entries. Fix this by choosing the tables based on the faulting address. Acked-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com> [will: zero-extend addrs to 64-bit, don't walk swapper w/ TTBR0 addr] Signed-off-by: Will Deacon <will.deacon@arm.com>
1 parent e71a4e1 commit 67ce16e

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

arch/arm64/include/asm/system_misc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
4040
int sig, int code, const char *name);
4141

4242
struct mm_struct;
43-
extern void show_pte(struct mm_struct *mm, unsigned long addr);
43+
extern void show_pte(unsigned long addr);
4444
extern void __show_regs(struct pt_regs *);
4545

4646
extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);

arch/arm64/mm/fault.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,33 @@ static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr)
8080
#endif
8181

8282
/*
83-
* Dump out the page tables associated with 'addr' in mm 'mm'.
83+
* Dump out the page tables associated with 'addr' in the currently active mm.
8484
*/
85-
void show_pte(struct mm_struct *mm, unsigned long addr)
85+
void show_pte(unsigned long addr)
8686
{
87+
struct mm_struct *mm;
8788
pgd_t *pgd;
8889

89-
if (!mm)
90+
if (addr < TASK_SIZE) {
91+
/* TTBR0 */
92+
mm = current->active_mm;
93+
if (mm == &init_mm) {
94+
pr_alert("[%016lx] user address but active_mm is swapper\n",
95+
addr);
96+
return;
97+
}
98+
} else if (addr >= VA_START) {
99+
/* TTBR1 */
90100
mm = &init_mm;
101+
} else {
102+
pr_alert("[%016lx] address between user and kernel address ranges\n",
103+
addr);
104+
return;
105+
}
91106

92107
pr_alert("pgd = %p\n", mm->pgd);
93108
pgd = pgd_offset(mm, addr);
94-
pr_alert("[%08lx] *pgd=%016llx", addr, pgd_val(*pgd));
109+
pr_alert("[%016lx] *pgd=%016llx", addr, pgd_val(*pgd));
95110

96111
do {
97112
pud_t *pud;
@@ -196,8 +211,8 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs,
196211
/*
197212
* The kernel tried to access some page that wasn't present.
198213
*/
199-
static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
200-
unsigned int esr, struct pt_regs *regs)
214+
static void __do_kernel_fault(unsigned long addr, unsigned int esr,
215+
struct pt_regs *regs)
201216
{
202217
const char *msg;
203218

@@ -227,7 +242,7 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
227242
pr_alert("Unable to handle kernel %s at virtual address %08lx\n", msg,
228243
addr);
229244

230-
show_pte(mm, addr);
245+
show_pte(addr);
231246
die("Oops", regs, esr);
232247
bust_spinlocks(0);
233248
do_exit(SIGKILL);
@@ -249,7 +264,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
249264
pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
250265
tsk->comm, task_pid_nr(tsk), inf->name, sig,
251266
addr, esr);
252-
show_pte(tsk->mm, addr);
267+
show_pte(addr);
253268
__show_regs(regs);
254269
}
255270

@@ -265,7 +280,6 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
265280
static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
266281
{
267282
struct task_struct *tsk = current;
268-
struct mm_struct *mm = tsk->active_mm;
269283
const struct fault_info *inf;
270284

271285
/*
@@ -276,7 +290,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
276290
inf = esr_to_fault_info(esr);
277291
__do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs);
278292
} else
279-
__do_kernel_fault(mm, addr, esr, regs);
293+
__do_kernel_fault(addr, esr, regs);
280294
}
281295

282296
#define VM_FAULT_BADMAP 0x010000
@@ -475,7 +489,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
475489
return 0;
476490

477491
no_context:
478-
__do_kernel_fault(mm, addr, esr, regs);
492+
__do_kernel_fault(addr, esr, regs);
479493
return 0;
480494
}
481495

0 commit comments

Comments
 (0)