|
@@ -80,18 +80,33 @@ static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr)
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
- * Dump out the page tables associated with 'addr' in mm 'mm'.
|
|
|
+ * Dump out the page tables associated with 'addr' in the currently active mm.
|
|
|
*/
|
|
|
-void show_pte(struct mm_struct *mm, unsigned long addr)
|
|
|
+void show_pte(unsigned long addr)
|
|
|
{
|
|
|
+ struct mm_struct *mm;
|
|
|
pgd_t *pgd;
|
|
|
|
|
|
- if (!mm)
|
|
|
+ if (addr < TASK_SIZE) {
|
|
|
+ /* TTBR0 */
|
|
|
+ mm = current->active_mm;
|
|
|
+ if (mm == &init_mm) {
|
|
|
+ pr_alert("[%016lx] user address but active_mm is swapper\n",
|
|
|
+ addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else if (addr >= VA_START) {
|
|
|
+ /* TTBR1 */
|
|
|
mm = &init_mm;
|
|
|
+ } else {
|
|
|
+ pr_alert("[%016lx] address between user and kernel address ranges\n",
|
|
|
+ addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
pr_alert("pgd = %p\n", mm->pgd);
|
|
|
pgd = pgd_offset(mm, addr);
|
|
|
- pr_alert("[%08lx] *pgd=%016llx", addr, pgd_val(*pgd));
|
|
|
+ pr_alert("[%016lx] *pgd=%016llx", addr, pgd_val(*pgd));
|
|
|
|
|
|
do {
|
|
|
pud_t *pud;
|
|
@@ -196,8 +211,8 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs,
|
|
|
/*
|
|
|
* The kernel tried to access some page that wasn't present.
|
|
|
*/
|
|
|
-static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
|
|
|
- unsigned int esr, struct pt_regs *regs)
|
|
|
+static void __do_kernel_fault(unsigned long addr, unsigned int esr,
|
|
|
+ struct pt_regs *regs)
|
|
|
{
|
|
|
const char *msg;
|
|
|
|
|
@@ -227,7 +242,7 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
|
|
|
pr_alert("Unable to handle kernel %s at virtual address %08lx\n", msg,
|
|
|
addr);
|
|
|
|
|
|
- show_pte(mm, addr);
|
|
|
+ show_pte(addr);
|
|
|
die("Oops", regs, esr);
|
|
|
bust_spinlocks(0);
|
|
|
do_exit(SIGKILL);
|
|
@@ -249,7 +264,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
|
|
|
pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
|
|
|
tsk->comm, task_pid_nr(tsk), inf->name, sig,
|
|
|
addr, esr);
|
|
|
- show_pte(tsk->mm, addr);
|
|
|
+ show_pte(addr);
|
|
|
__show_regs(regs);
|
|
|
}
|
|
|
|
|
@@ -265,7 +280,6 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
|
|
|
static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
|
|
|
{
|
|
|
struct task_struct *tsk = current;
|
|
|
- struct mm_struct *mm = tsk->active_mm;
|
|
|
const struct fault_info *inf;
|
|
|
|
|
|
/*
|
|
@@ -276,7 +290,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
|
|
|
inf = esr_to_fault_info(esr);
|
|
|
__do_user_fault(tsk, addr, esr, inf->sig, inf->code, regs);
|
|
|
} else
|
|
|
- __do_kernel_fault(mm, addr, esr, regs);
|
|
|
+ __do_kernel_fault(addr, esr, regs);
|
|
|
}
|
|
|
|
|
|
#define VM_FAULT_BADMAP 0x010000
|
|
@@ -475,7 +489,7 @@ retry:
|
|
|
return 0;
|
|
|
|
|
|
no_context:
|
|
|
- __do_kernel_fault(mm, addr, esr, regs);
|
|
|
+ __do_kernel_fault(addr, esr, regs);
|
|
|
return 0;
|
|
|
}
|
|
|
|