|
@@ -200,6 +200,7 @@ static inline int is_module_addr(void *addr)
|
|
*/
|
|
*/
|
|
|
|
|
|
/* Hardware bits in the page table entry */
|
|
/* Hardware bits in the page table entry */
|
|
|
|
+#define _PAGE_NOEXEC 0x100 /* HW no-execute bit */
|
|
#define _PAGE_PROTECT 0x200 /* HW read-only bit */
|
|
#define _PAGE_PROTECT 0x200 /* HW read-only bit */
|
|
#define _PAGE_INVALID 0x400 /* HW invalid bit */
|
|
#define _PAGE_INVALID 0x400 /* HW invalid bit */
|
|
#define _PAGE_LARGE 0x800 /* Bit to mark a large pte */
|
|
#define _PAGE_LARGE 0x800 /* Bit to mark a large pte */
|
|
@@ -277,6 +278,7 @@ static inline int is_module_addr(void *addr)
|
|
/* Bits in the region table entry */
|
|
/* Bits in the region table entry */
|
|
#define _REGION_ENTRY_ORIGIN ~0xfffUL/* region/segment table origin */
|
|
#define _REGION_ENTRY_ORIGIN ~0xfffUL/* region/segment table origin */
|
|
#define _REGION_ENTRY_PROTECT 0x200 /* region protection bit */
|
|
#define _REGION_ENTRY_PROTECT 0x200 /* region protection bit */
|
|
|
|
+#define _REGION_ENTRY_NOEXEC 0x100 /* region no-execute bit */
|
|
#define _REGION_ENTRY_OFFSET 0xc0 /* region table offset */
|
|
#define _REGION_ENTRY_OFFSET 0xc0 /* region table offset */
|
|
#define _REGION_ENTRY_INVALID 0x20 /* invalid region table entry */
|
|
#define _REGION_ENTRY_INVALID 0x20 /* invalid region table entry */
|
|
#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
|
|
#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
|
|
@@ -316,6 +318,7 @@ static inline int is_module_addr(void *addr)
|
|
#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address */
|
|
#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address */
|
|
#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
|
|
#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
|
|
#define _SEGMENT_ENTRY_PROTECT 0x200 /* page protection bit */
|
|
#define _SEGMENT_ENTRY_PROTECT 0x200 /* page protection bit */
|
|
|
|
+#define _SEGMENT_ENTRY_NOEXEC 0x100 /* region no-execute bit */
|
|
#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */
|
|
#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */
|
|
|
|
|
|
#define _SEGMENT_ENTRY (0)
|
|
#define _SEGMENT_ENTRY (0)
|
|
@@ -385,17 +388,23 @@ static inline int is_module_addr(void *addr)
|
|
* Page protection definitions.
|
|
* Page protection definitions.
|
|
*/
|
|
*/
|
|
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_INVALID | _PAGE_PROTECT)
|
|
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_INVALID | _PAGE_PROTECT)
|
|
-#define PAGE_READ __pgprot(_PAGE_PRESENT | _PAGE_READ | \
|
|
|
|
|
|
+#define PAGE_RO __pgprot(_PAGE_PRESENT | _PAGE_READ | \
|
|
|
|
+ _PAGE_NOEXEC | _PAGE_INVALID | _PAGE_PROTECT)
|
|
|
|
+#define PAGE_RX __pgprot(_PAGE_PRESENT | _PAGE_READ | \
|
|
_PAGE_INVALID | _PAGE_PROTECT)
|
|
_PAGE_INVALID | _PAGE_PROTECT)
|
|
-#define PAGE_WRITE __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
|
|
|
|
+#define PAGE_RW __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
|
|
+ _PAGE_NOEXEC | _PAGE_INVALID | _PAGE_PROTECT)
|
|
|
|
+#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
_PAGE_INVALID | _PAGE_PROTECT)
|
|
_PAGE_INVALID | _PAGE_PROTECT)
|
|
|
|
|
|
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
- _PAGE_YOUNG | _PAGE_DIRTY)
|
|
|
|
|
|
+ _PAGE_YOUNG | _PAGE_DIRTY | _PAGE_NOEXEC)
|
|
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
- _PAGE_YOUNG | _PAGE_DIRTY)
|
|
|
|
|
|
+ _PAGE_YOUNG | _PAGE_DIRTY | _PAGE_NOEXEC)
|
|
#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_YOUNG | \
|
|
#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_YOUNG | \
|
|
- _PAGE_PROTECT)
|
|
|
|
|
|
+ _PAGE_PROTECT | _PAGE_NOEXEC)
|
|
|
|
+#define PAGE_KERNEL_EXEC __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
|
|
|
|
+ _PAGE_YOUNG | _PAGE_DIRTY)
|
|
|
|
|
|
/*
|
|
/*
|
|
* On s390 the page table entry has an invalid bit and a read-only bit.
|
|
* On s390 the page table entry has an invalid bit and a read-only bit.
|
|
@@ -404,43 +413,51 @@ static inline int is_module_addr(void *addr)
|
|
*/
|
|
*/
|
|
/*xwr*/
|
|
/*xwr*/
|
|
#define __P000 PAGE_NONE
|
|
#define __P000 PAGE_NONE
|
|
-#define __P001 PAGE_READ
|
|
|
|
-#define __P010 PAGE_READ
|
|
|
|
-#define __P011 PAGE_READ
|
|
|
|
-#define __P100 PAGE_READ
|
|
|
|
-#define __P101 PAGE_READ
|
|
|
|
-#define __P110 PAGE_READ
|
|
|
|
-#define __P111 PAGE_READ
|
|
|
|
|
|
+#define __P001 PAGE_RO
|
|
|
|
+#define __P010 PAGE_RO
|
|
|
|
+#define __P011 PAGE_RO
|
|
|
|
+#define __P100 PAGE_RX
|
|
|
|
+#define __P101 PAGE_RX
|
|
|
|
+#define __P110 PAGE_RX
|
|
|
|
+#define __P111 PAGE_RX
|
|
|
|
|
|
#define __S000 PAGE_NONE
|
|
#define __S000 PAGE_NONE
|
|
-#define __S001 PAGE_READ
|
|
|
|
-#define __S010 PAGE_WRITE
|
|
|
|
-#define __S011 PAGE_WRITE
|
|
|
|
-#define __S100 PAGE_READ
|
|
|
|
-#define __S101 PAGE_READ
|
|
|
|
-#define __S110 PAGE_WRITE
|
|
|
|
-#define __S111 PAGE_WRITE
|
|
|
|
|
|
+#define __S001 PAGE_RO
|
|
|
|
+#define __S010 PAGE_RW
|
|
|
|
+#define __S011 PAGE_RW
|
|
|
|
+#define __S100 PAGE_RX
|
|
|
|
+#define __S101 PAGE_RX
|
|
|
|
+#define __S110 PAGE_RWX
|
|
|
|
+#define __S111 PAGE_RWX
|
|
|
|
|
|
/*
|
|
/*
|
|
* Segment entry (large page) protection definitions.
|
|
* Segment entry (large page) protection definitions.
|
|
*/
|
|
*/
|
|
#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \
|
|
#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \
|
|
_SEGMENT_ENTRY_PROTECT)
|
|
_SEGMENT_ENTRY_PROTECT)
|
|
-#define SEGMENT_READ __pgprot(_SEGMENT_ENTRY_PROTECT | \
|
|
|
|
|
|
+#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PROTECT | \
|
|
|
|
+ _SEGMENT_ENTRY_READ | \
|
|
|
|
+ _SEGMENT_ENTRY_NOEXEC)
|
|
|
|
+#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PROTECT | \
|
|
_SEGMENT_ENTRY_READ)
|
|
_SEGMENT_ENTRY_READ)
|
|
-#define SEGMENT_WRITE __pgprot(_SEGMENT_ENTRY_READ | \
|
|
|
|
|
|
+#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_READ | \
|
|
|
|
+ _SEGMENT_ENTRY_WRITE | \
|
|
|
|
+ _SEGMENT_ENTRY_NOEXEC)
|
|
|
|
+#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_READ | \
|
|
_SEGMENT_ENTRY_WRITE)
|
|
_SEGMENT_ENTRY_WRITE)
|
|
#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \
|
|
#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \
|
|
_SEGMENT_ENTRY_LARGE | \
|
|
_SEGMENT_ENTRY_LARGE | \
|
|
_SEGMENT_ENTRY_READ | \
|
|
_SEGMENT_ENTRY_READ | \
|
|
_SEGMENT_ENTRY_WRITE | \
|
|
_SEGMENT_ENTRY_WRITE | \
|
|
_SEGMENT_ENTRY_YOUNG | \
|
|
_SEGMENT_ENTRY_YOUNG | \
|
|
- _SEGMENT_ENTRY_DIRTY)
|
|
|
|
|
|
+ _SEGMENT_ENTRY_DIRTY | \
|
|
|
|
+ _SEGMENT_ENTRY_NOEXEC)
|
|
#define SEGMENT_KERNEL_RO __pgprot(_SEGMENT_ENTRY | \
|
|
#define SEGMENT_KERNEL_RO __pgprot(_SEGMENT_ENTRY | \
|
|
_SEGMENT_ENTRY_LARGE | \
|
|
_SEGMENT_ENTRY_LARGE | \
|
|
_SEGMENT_ENTRY_READ | \
|
|
_SEGMENT_ENTRY_READ | \
|
|
_SEGMENT_ENTRY_YOUNG | \
|
|
_SEGMENT_ENTRY_YOUNG | \
|
|
- _SEGMENT_ENTRY_PROTECT)
|
|
|
|
|
|
+ _SEGMENT_ENTRY_PROTECT | \
|
|
|
|
+ _SEGMENT_ENTRY_NOEXEC)
|
|
|
|
|
|
/*
|
|
/*
|
|
* Region3 entry (large page) protection definitions.
|
|
* Region3 entry (large page) protection definitions.
|
|
@@ -451,12 +468,14 @@ static inline int is_module_addr(void *addr)
|
|
_REGION3_ENTRY_READ | \
|
|
_REGION3_ENTRY_READ | \
|
|
_REGION3_ENTRY_WRITE | \
|
|
_REGION3_ENTRY_WRITE | \
|
|
_REGION3_ENTRY_YOUNG | \
|
|
_REGION3_ENTRY_YOUNG | \
|
|
- _REGION3_ENTRY_DIRTY)
|
|
|
|
|
|
+ _REGION3_ENTRY_DIRTY | \
|
|
|
|
+ _REGION_ENTRY_NOEXEC)
|
|
#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
|
|
#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
|
|
_REGION3_ENTRY_LARGE | \
|
|
_REGION3_ENTRY_LARGE | \
|
|
_REGION3_ENTRY_READ | \
|
|
_REGION3_ENTRY_READ | \
|
|
_REGION3_ENTRY_YOUNG | \
|
|
_REGION3_ENTRY_YOUNG | \
|
|
- _REGION_ENTRY_PROTECT)
|
|
|
|
|
|
+ _REGION_ENTRY_PROTECT | \
|
|
|
|
+ _REGION_ENTRY_NOEXEC)
|
|
|
|
|
|
static inline int mm_has_pgste(struct mm_struct *mm)
|
|
static inline int mm_has_pgste(struct mm_struct *mm)
|
|
{
|
|
{
|
|
@@ -801,14 +820,14 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|
pte_val(pte) &= _PAGE_CHG_MASK;
|
|
pte_val(pte) &= _PAGE_CHG_MASK;
|
|
pte_val(pte) |= pgprot_val(newprot);
|
|
pte_val(pte) |= pgprot_val(newprot);
|
|
/*
|
|
/*
|
|
- * newprot for PAGE_NONE, PAGE_READ and PAGE_WRITE has the
|
|
|
|
- * invalid bit set, clear it again for readable, young pages
|
|
|
|
|
|
+ * newprot for PAGE_NONE, PAGE_RO, PAGE_RX, PAGE_RW and PAGE_RWX
|
|
|
|
+ * has the invalid bit set, clear it again for readable, young pages
|
|
*/
|
|
*/
|
|
if ((pte_val(pte) & _PAGE_YOUNG) && (pte_val(pte) & _PAGE_READ))
|
|
if ((pte_val(pte) & _PAGE_YOUNG) && (pte_val(pte) & _PAGE_READ))
|
|
pte_val(pte) &= ~_PAGE_INVALID;
|
|
pte_val(pte) &= ~_PAGE_INVALID;
|
|
/*
|
|
/*
|
|
- * newprot for PAGE_READ and PAGE_WRITE has the page protection
|
|
|
|
- * bit set, clear it again for writable, dirty pages
|
|
|
|
|
|
+ * newprot for PAGE_RO, PAGE_RX, PAGE_RW and PAGE_RWX has the page
|
|
|
|
+ * protection bit set, clear it again for writable, dirty pages
|
|
*/
|
|
*/
|
|
if ((pte_val(pte) & _PAGE_DIRTY) && (pte_val(pte) & _PAGE_WRITE))
|
|
if ((pte_val(pte) & _PAGE_DIRTY) && (pte_val(pte) & _PAGE_WRITE))
|
|
pte_val(pte) &= ~_PAGE_PROTECT;
|
|
pte_val(pte) &= ~_PAGE_PROTECT;
|
|
@@ -1029,6 +1048,8 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned long addr,
|
|
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
|
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
|
pte_t *ptep, pte_t entry)
|
|
pte_t *ptep, pte_t entry)
|
|
{
|
|
{
|
|
|
|
+ if (!MACHINE_HAS_NX)
|
|
|
|
+ pte_val(entry) &= ~_PAGE_NOEXEC;
|
|
if (mm_has_pgste(mm))
|
|
if (mm_has_pgste(mm))
|
|
ptep_set_pte_at(mm, addr, ptep, entry);
|
|
ptep_set_pte_at(mm, addr, ptep, entry);
|
|
else
|
|
else
|
|
@@ -1173,14 +1194,18 @@ static inline pud_t pud_mkdirty(pud_t pud)
|
|
static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
|
|
static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
|
|
{
|
|
{
|
|
/*
|
|
/*
|
|
- * pgprot is PAGE_NONE, PAGE_READ, or PAGE_WRITE (see __Pxxx / __Sxxx)
|
|
|
|
- * Convert to segment table entry format.
|
|
|
|
|
|
+ * pgprot is PAGE_NONE, PAGE_RO, PAGE_RX, PAGE_RW or PAGE_RWX
|
|
|
|
+ * (see __Pxxx / __Sxxx). Convert to segment table entry format.
|
|
*/
|
|
*/
|
|
if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
|
|
if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
|
|
return pgprot_val(SEGMENT_NONE);
|
|
return pgprot_val(SEGMENT_NONE);
|
|
- if (pgprot_val(pgprot) == pgprot_val(PAGE_READ))
|
|
|
|
- return pgprot_val(SEGMENT_READ);
|
|
|
|
- return pgprot_val(SEGMENT_WRITE);
|
|
|
|
|
|
+ if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
|
|
|
|
+ return pgprot_val(SEGMENT_RO);
|
|
|
|
+ if (pgprot_val(pgprot) == pgprot_val(PAGE_RX))
|
|
|
|
+ return pgprot_val(SEGMENT_RX);
|
|
|
|
+ if (pgprot_val(pgprot) == pgprot_val(PAGE_RW))
|
|
|
|
+ return pgprot_val(SEGMENT_RW);
|
|
|
|
+ return pgprot_val(SEGMENT_RWX);
|
|
}
|
|
}
|
|
|
|
|
|
static inline pmd_t pmd_mkyoung(pmd_t pmd)
|
|
static inline pmd_t pmd_mkyoung(pmd_t pmd)
|
|
@@ -1315,6 +1340,8 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma,
|
|
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
|
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
|
pmd_t *pmdp, pmd_t entry)
|
|
pmd_t *pmdp, pmd_t entry)
|
|
{
|
|
{
|
|
|
|
+ if (!MACHINE_HAS_NX)
|
|
|
|
+ pmd_val(entry) &= ~_SEGMENT_ENTRY_NOEXEC;
|
|
*pmdp = entry;
|
|
*pmdp = entry;
|
|
}
|
|
}
|
|
|
|
|