|
@@ -185,19 +185,29 @@ static inline int pte_special(pte_t pte)
|
|
|
return pte_flags(pte) & _PAGE_SPECIAL;
|
|
|
}
|
|
|
|
|
|
+/* Entries that were set to PROT_NONE are inverted */
|
|
|
+
|
|
|
+static inline u64 protnone_mask(u64 val);
|
|
|
+
|
|
|
static inline unsigned long pte_pfn(pte_t pte)
|
|
|
{
|
|
|
- return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
|
|
|
+ unsigned long pfn = pte_val(pte);
|
|
|
+ pfn ^= protnone_mask(pfn);
|
|
|
+ return (pfn & PTE_PFN_MASK) >> PAGE_SHIFT;
|
|
|
}
|
|
|
|
|
|
static inline unsigned long pmd_pfn(pmd_t pmd)
|
|
|
{
|
|
|
- return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
|
|
|
+ unsigned long pfn = pmd_val(pmd);
|
|
|
+ pfn ^= protnone_mask(pfn);
|
|
|
+ return (pfn & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
|
|
|
}
|
|
|
|
|
|
static inline unsigned long pud_pfn(pud_t pud)
|
|
|
{
|
|
|
- return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
|
|
|
+ unsigned long pfn = pud_val(pud);
|
|
|
+ pfn ^= protnone_mask(pfn);
|
|
|
+ return (pfn & pud_pfn_mask(pud)) >> PAGE_SHIFT;
|
|
|
}
|
|
|
|
|
|
static inline unsigned long p4d_pfn(p4d_t p4d)
|
|
@@ -545,25 +555,33 @@ static inline pgprotval_t check_pgprot(pgprot_t pgprot)
|
|
|
|
|
|
static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
|
|
|
{
|
|
|
- return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) |
|
|
|
- check_pgprot(pgprot));
|
|
|
+ phys_addr_t pfn = page_nr << PAGE_SHIFT;
|
|
|
+ pfn ^= protnone_mask(pgprot_val(pgprot));
|
|
|
+ pfn &= PTE_PFN_MASK;
|
|
|
+ return __pte(pfn | check_pgprot(pgprot));
|
|
|
}
|
|
|
|
|
|
static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
|
|
|
{
|
|
|
- return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) |
|
|
|
- check_pgprot(pgprot));
|
|
|
+ phys_addr_t pfn = page_nr << PAGE_SHIFT;
|
|
|
+ pfn ^= protnone_mask(pgprot_val(pgprot));
|
|
|
+ pfn &= PHYSICAL_PMD_PAGE_MASK;
|
|
|
+ return __pmd(pfn | check_pgprot(pgprot));
|
|
|
}
|
|
|
|
|
|
static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot)
|
|
|
{
|
|
|
- return __pud(((phys_addr_t)page_nr << PAGE_SHIFT) |
|
|
|
- check_pgprot(pgprot));
|
|
|
+ phys_addr_t pfn = page_nr << PAGE_SHIFT;
|
|
|
+ pfn ^= protnone_mask(pgprot_val(pgprot));
|
|
|
+ pfn &= PHYSICAL_PUD_PAGE_MASK;
|
|
|
+ return __pud(pfn | check_pgprot(pgprot));
|
|
|
}
|
|
|
|
|
|
+static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask);
|
|
|
+
|
|
|
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|
|
{
|
|
|
- pteval_t val = pte_val(pte);
|
|
|
+ pteval_t val = pte_val(pte), oldval = val;
|
|
|
|
|
|
/*
|
|
|
* Chop off the NX bit (if present), and add the NX portion of
|
|
@@ -571,17 +589,17 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|
|
*/
|
|
|
val &= _PAGE_CHG_MASK;
|
|
|
val |= check_pgprot(newprot) & ~_PAGE_CHG_MASK;
|
|
|
-
|
|
|
+ val = flip_protnone_guard(oldval, val, PTE_PFN_MASK);
|
|
|
return __pte(val);
|
|
|
}
|
|
|
|
|
|
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
|
|
{
|
|
|
- pmdval_t val = pmd_val(pmd);
|
|
|
+ pmdval_t val = pmd_val(pmd), oldval = val;
|
|
|
|
|
|
val &= _HPAGE_CHG_MASK;
|
|
|
val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK;
|
|
|
-
|
|
|
+ val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK);
|
|
|
return __pmd(val);
|
|
|
}
|
|
|
|