|
@@ -253,6 +253,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
|
|
|
{
|
|
|
unsigned index = pgd_index(address);
|
|
|
pgd_t *pgd_k;
|
|
|
+ p4d_t *p4d, *p4d_k;
|
|
|
pud_t *pud, *pud_k;
|
|
|
pmd_t *pmd, *pmd_k;
|
|
|
|
|
@@ -265,10 +266,15 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
|
|
|
/*
|
|
|
* set_pgd(pgd, *pgd_k); here would be useless on PAE
|
|
|
* and redundant with the set_pmd() on non-PAE. As would
|
|
|
- * set_pud.
|
|
|
+ * set_p4d/set_pud.
|
|
|
*/
|
|
|
- pud = pud_offset(pgd, address);
|
|
|
- pud_k = pud_offset(pgd_k, address);
|
|
|
+ p4d = p4d_offset(pgd, address);
|
|
|
+ p4d_k = p4d_offset(pgd_k, address);
|
|
|
+ if (!p4d_present(*p4d_k))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ pud = pud_offset(p4d, address);
|
|
|
+ pud_k = pud_offset(p4d_k, address);
|
|
|
if (!pud_present(*pud_k))
|
|
|
return NULL;
|
|
|
|
|
@@ -384,6 +390,8 @@ static void dump_pagetable(unsigned long address)
|
|
|
{
|
|
|
pgd_t *base = __va(read_cr3());
|
|
|
pgd_t *pgd = &base[pgd_index(address)];
|
|
|
+ p4d_t *p4d;
|
|
|
+ pud_t *pud;
|
|
|
pmd_t *pmd;
|
|
|
pte_t *pte;
|
|
|
|
|
@@ -392,7 +400,9 @@ static void dump_pagetable(unsigned long address)
|
|
|
if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd))
|
|
|
goto out;
|
|
|
#endif
|
|
|
- pmd = pmd_offset(pud_offset(pgd, address), address);
|
|
|
+ p4d = p4d_offset(pgd, address);
|
|
|
+ pud = pud_offset(p4d, address);
|
|
|
+ pmd = pmd_offset(pud, address);
|
|
|
printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd));
|
|
|
|
|
|
/*
|
|
@@ -526,6 +536,7 @@ static void dump_pagetable(unsigned long address)
|
|
|
{
|
|
|
pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
|
|
|
pgd_t *pgd = base + pgd_index(address);
|
|
|
+ p4d_t *p4d;
|
|
|
pud_t *pud;
|
|
|
pmd_t *pmd;
|
|
|
pte_t *pte;
|
|
@@ -538,7 +549,15 @@ static void dump_pagetable(unsigned long address)
|
|
|
if (!pgd_present(*pgd))
|
|
|
goto out;
|
|
|
|
|
|
- pud = pud_offset(pgd, address);
|
|
|
+ p4d = p4d_offset(pgd, address);
|
|
|
+ if (bad_address(p4d))
|
|
|
+ goto bad;
|
|
|
+
|
|
|
+ printk("P4D %lx ", p4d_val(*p4d));
|
|
|
+ if (!p4d_present(*p4d) || p4d_large(*p4d))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ pud = pud_offset(p4d, address);
|
|
|
if (bad_address(pud))
|
|
|
goto bad;
|
|
|
|
|
@@ -1082,6 +1101,7 @@ static noinline int
|
|
|
spurious_fault(unsigned long error_code, unsigned long address)
|
|
|
{
|
|
|
pgd_t *pgd;
|
|
|
+ p4d_t *p4d;
|
|
|
pud_t *pud;
|
|
|
pmd_t *pmd;
|
|
|
pte_t *pte;
|
|
@@ -1104,7 +1124,14 @@ spurious_fault(unsigned long error_code, unsigned long address)
|
|
|
if (!pgd_present(*pgd))
|
|
|
return 0;
|
|
|
|
|
|
- pud = pud_offset(pgd, address);
|
|
|
+ p4d = p4d_offset(pgd, address);
|
|
|
+ if (!p4d_present(*p4d))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (p4d_large(*p4d))
|
|
|
+ return spurious_fault_check(error_code, (pte_t *) p4d);
|
|
|
+
|
|
|
+ pud = pud_offset(p4d, address);
|
|
|
if (!pud_present(*pud))
|
|
|
return 0;
|
|
|
|