|
|
|
@@ -28,7 +28,7 @@
|
|
|
|
|
#define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
|
|
|
|
|
#define PTE_DIRTY (_AT(pteval_t, 1) << 55)
|
|
|
|
|
#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)
|
|
|
|
|
/* bit 57 for PMD_SECT_SPLITTING */
|
|
|
|
|
#define PTE_WRITE (_AT(pteval_t, 1) << 57)
|
|
|
|
|
#define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -67,15 +67,15 @@ extern pgprot_t pgprot_default;
|
|
|
|
|
|
|
|
|
|
#define _MOD_PROT(p, b) __pgprot_modify(p, 0, b)
|
|
|
|
|
|
|
|
|
|
#define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
|
|
|
|
|
#define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
|
|
|
|
|
#define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
|
|
|
|
|
#define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
|
|
|
|
|
#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
|
|
|
|
|
#define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
|
|
|
|
|
#define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
|
|
|
|
|
#define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
|
|
|
|
|
#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
|
|
|
|
|
#define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
|
|
|
|
|
#define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
|
|
|
|
|
#define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
|
|
|
|
|
#define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY | PTE_WRITE)
|
|
|
|
|
|
|
|
|
|
#define PAGE_HYP _MOD_PROT(pgprot_default, PTE_HYP)
|
|
|
|
|
#define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
|
|
|
|
@@ -83,13 +83,13 @@ extern pgprot_t pgprot_default;
|
|
|
|
|
#define PAGE_S2 __pgprot_modify(pgprot_default, PTE_S2_MEMATTR_MASK, PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)
|
|
|
|
|
#define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | PTE_UXN)
|
|
|
|
|
|
|
|
|
|
#define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
|
|
|
|
|
#define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
|
|
|
|
|
#define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
|
|
|
|
|
#define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
|
|
|
|
|
#define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
|
|
|
|
|
#define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
|
|
|
|
|
#define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
|
|
|
|
|
#define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
|
|
|
|
|
#define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
|
|
|
|
|
#define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
|
|
|
|
|
|
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
|
|
|
|
|
@@ -140,22 +140,53 @@ extern struct page *empty_zero_page;
|
|
|
|
|
#define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY)
|
|
|
|
|
#define pte_young(pte) (pte_val(pte) & PTE_AF)
|
|
|
|
|
#define pte_special(pte) (pte_val(pte) & PTE_SPECIAL)
|
|
|
|
|
#define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY))
|
|
|
|
|
#define pte_write(pte) (pte_val(pte) & PTE_WRITE)
|
|
|
|
|
#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN))
|
|
|
|
|
|
|
|
|
|
#define pte_valid_user(pte) \
|
|
|
|
|
((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
|
|
|
|
|
|
|
|
|
|
#define PTE_BIT_FUNC(fn,op) \
|
|
|
|
|
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
|
|
|
|
|
static inline pte_t pte_wrprotect(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) &= ~PTE_WRITE;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PTE_BIT_FUNC(wrprotect, |= PTE_RDONLY);
|
|
|
|
|
PTE_BIT_FUNC(mkwrite, &= ~PTE_RDONLY);
|
|
|
|
|
PTE_BIT_FUNC(mkclean, &= ~PTE_DIRTY);
|
|
|
|
|
PTE_BIT_FUNC(mkdirty, |= PTE_DIRTY);
|
|
|
|
|
PTE_BIT_FUNC(mkold, &= ~PTE_AF);
|
|
|
|
|
PTE_BIT_FUNC(mkyoung, |= PTE_AF);
|
|
|
|
|
PTE_BIT_FUNC(mkspecial, |= PTE_SPECIAL);
|
|
|
|
|
static inline pte_t pte_mkwrite(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) |= PTE_WRITE;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline pte_t pte_mkclean(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) &= ~PTE_DIRTY;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline pte_t pte_mkdirty(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) |= PTE_DIRTY;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline pte_t pte_mkold(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) &= ~PTE_AF;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline pte_t pte_mkyoung(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) |= PTE_AF;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline pte_t pte_mkspecial(pte_t pte)
|
|
|
|
|
{
|
|
|
|
|
pte_val(pte) |= PTE_SPECIAL;
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void set_pte(pte_t *ptep, pte_t pte)
|
|
|
|
|
{
|
|
|
|
@@ -170,8 +201,10 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
|
|
|
|
if (pte_valid_user(pte)) {
|
|
|
|
|
if (pte_exec(pte))
|
|
|
|
|
__sync_icache_dcache(pte, addr);
|
|
|
|
|
if (!pte_dirty(pte))
|
|
|
|
|
pte = pte_wrprotect(pte);
|
|
|
|
|
if (pte_dirty(pte) && pte_write(pte))
|
|
|
|
|
pte_val(pte) &= ~PTE_RDONLY;
|
|
|
|
|
else
|
|
|
|
|
pte_val(pte) |= PTE_RDONLY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set_pte(ptep, pte);
|
|
|
|
@@ -345,7 +378,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
|
|
|
|
|
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|
|
|
|
{
|
|
|
|
|
const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
|
|
|
|
|
PTE_PROT_NONE | PTE_VALID;
|
|
|
|
|
PTE_PROT_NONE | PTE_VALID | PTE_WRITE;
|
|
|
|
|
pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
|
|
|
|
|
return pte;
|
|
|
|
|
}
|
|
|
|
|