|
@@ -871,6 +871,18 @@ static inline int subpage_protection(struct mm_struct *mm, unsigned long ea)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+void hash_failure_debug(unsigned long ea, unsigned long access,
|
|
|
+ unsigned long vsid, unsigned long trap,
|
|
|
+ int ssize, int psize, unsigned long pte)
|
|
|
+{
|
|
|
+ if (!printk_ratelimit())
|
|
|
+ return;
|
|
|
+ pr_info("mm: Hashing failure ! EA=0x%lx access=0x%lx current=%s\n",
|
|
|
+ ea, access, current->comm);
|
|
|
+ pr_info(" trap=0x%lx vsid=0x%lx ssize=%d psize=%d pte=0x%lx\n",
|
|
|
+ trap, vsid, ssize, psize, pte);
|
|
|
+}
|
|
|
+
|
|
|
/* Result code is:
|
|
|
* 0 - handled
|
|
|
* 1 - normal page fault
|
|
@@ -1036,6 +1048,12 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
|
|
|
local, ssize, spp);
|
|
|
}
|
|
|
|
|
|
+ /* Dump some info in case of hash insertion failure, they should
|
|
|
+ * never happen so it is really useful to know if/when they do
|
|
|
+ */
|
|
|
+ if (rc == -1)
|
|
|
+ hash_failure_debug(ea, access, vsid, trap, ssize, psize,
|
|
|
+ pte_val(*ptep));
|
|
|
#ifndef CONFIG_PPC_64K_PAGES
|
|
|
DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep));
|
|
|
#else
|
|
@@ -1054,8 +1072,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
|
|
|
void *pgdir;
|
|
|
pte_t *ptep;
|
|
|
unsigned long flags;
|
|
|
- int local = 0;
|
|
|
- int ssize;
|
|
|
+ int rc, ssize, local = 0;
|
|
|
|
|
|
BUG_ON(REGION_ID(ea) != USER_REGION_ID);
|
|
|
|
|
@@ -1101,11 +1118,18 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
|
|
|
/* Hash it in */
|
|
|
#ifdef CONFIG_PPC_HAS_HASH_64K
|
|
|
if (mm->context.user_psize == MMU_PAGE_64K)
|
|
|
- __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize);
|
|
|
+ rc = __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize);
|
|
|
else
|
|
|
#endif /* CONFIG_PPC_HAS_HASH_64K */
|
|
|
- __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
|
|
|
- subpage_protection(pgdir, ea));
|
|
|
+ rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
|
|
|
+ subpage_protection(pgdir, ea));
|
|
|
+
|
|
|
+ /* Dump some info in case of hash insertion failure, they should
|
|
|
+ * never happen so it is really useful to know if/when they do
|
|
|
+ */
|
|
|
+ if (rc == -1)
|
|
|
+ hash_failure_debug(ea, access, vsid, trap, ssize,
|
|
|
+ mm->context.user_psize, pte_val(*ptep));
|
|
|
|
|
|
local_irq_restore(flags);
|
|
|
}
|