summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2016-08-27 14:22:36 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2016-08-27 14:22:36 +0000
commit4d04abefd34b749258076f5b38200af9b37215a2 (patch)
treed2352a354448369aaf8c9a69138f6695a75f7249 /sys
parent20d23896dc245f50f5dab2b4695f7c291e674e92 (diff)
Add support for the PXN bit in level 1 translation table descriptors and
enable it on CPUs that support it. When enabled, this prevents the kernel from executing userland code. ok jsg@, tom@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/arm/arm/pmap7.c16
-rw-r--r--sys/arch/arm/include/pte.h6
2 files changed, 17 insertions, 5 deletions
diff --git a/sys/arch/arm/arm/pmap7.c b/sys/arch/arm/arm/pmap7.c
index 0889e549205..4997cea003b 100644
--- a/sys/arch/arm/arm/pmap7.c
+++ b/sys/arch/arm/arm/pmap7.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap7.c,v 1.49 2016/08/26 16:02:33 kettenis Exp $ */
+/* $OpenBSD: pmap7.c,v 1.50 2016/08/27 14:22:35 kettenis Exp $ */
/* $NetBSD: pmap.c,v 1.147 2004/01/18 13:03:50 scw Exp $ */
/*
@@ -303,6 +303,11 @@ struct l1_ttable {
#define L1_IDX(va) (((vaddr_t)(va)) >> L1_S_SHIFT)
/*
+ * Set if the PXN bit is supported.
+ */
+pd_entry_t l1_c_pxn;
+
+/*
* A list of all L1 tables
*/
TAILQ_HEAD(, l1_ttable) l1_list;
@@ -1267,7 +1272,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
pd_entry_t *pl1pd, l1pd;
pl1pd = &pm->pm_l1->l1_kva[L1_IDX(va)];
- l1pd = L1_C_PROTO | l2b->l2b_phys;
+ l1pd = L1_C_PROTO | l2b->l2b_phys | l1_c_pxn;
if (*pl1pd != l1pd) {
*pl1pd = l1pd;
PTE_SYNC(pl1pd);
@@ -2861,7 +2866,7 @@ void (*pmap_zero_page_func)(struct vm_page *);
void
pmap_pte_init_armv7(void)
{
- uint32_t id_mmfr3;
+ uint32_t id_mmfr0, id_mmfr3;
/*
* XXX We want to use proper TEX settings eventually.
@@ -2910,6 +2915,11 @@ pmap_pte_init_armv7(void)
pmap_copy_page_func = pmap_copy_page_generic;
pmap_zero_page_func = pmap_zero_page_generic;
+ /* Check if the PXN bit is supported. */
+ __asm volatile("mrc p15, 0, %0, c0, c1, 4" : "=r"(id_mmfr0));
+ if ((id_mmfr0 & ID_MMFR0_VMSA_MASK) >= VMSA_V7_PXN)
+ l1_c_pxn = L1_C_V7_PXN;
+
/* Check for coherent walk. */
__asm volatile("mrc p15, 0, %0, c0, c1, 7" : "=r"(id_mmfr3));
if ((id_mmfr3 & 0x00f00000) == 0x00100000)
diff --git a/sys/arch/arm/include/pte.h b/sys/arch/arm/include/pte.h
index 059e2812576..4dc2638fa2b 100644
--- a/sys/arch/arm/include/pte.h
+++ b/sys/arch/arm/include/pte.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pte.h,v 1.7 2016/08/18 09:28:22 kettenis Exp $ */
+/* $OpenBSD: pte.h,v 1.8 2016/08/27 14:22:35 kettenis Exp $ */
/* $NetBSD: pte.h,v 1.6 2003/04/18 11:08:28 scw Exp $ */
/*
@@ -159,6 +159,7 @@ typedef uint32_t pt_entry_t; /* L2 table entry */
#define L1_S_V7_AF 0x00000400 /* Access Flag */
#define L1_S_V7_IMP 0x00000200 /* implementation defined */
#define L1_S_V7_XN 0x00000010 /* eXecute Never */
+#define L1_S_V7_PXN 0x00000001 /* Privileged eXecute Never */
/* L1 Coarse Descriptor */
#define L1_C_IMP0 0x00000004 /* implementation defined */
@@ -170,8 +171,9 @@ typedef uint32_t pt_entry_t; /* L2 table entry */
#define L1_C_XSCALE_P 0x00000200 /* ECC enable for this section */
-#define L1_C_V7_NS 0x00000008 /* Non-secure */
#define L1_C_V7_IMP 0x00000200 /* implementation defined */
+#define L1_C_V7_NS 0x00000008 /* Non-secure */
+#define L1_C_V7_PXN 0x00000004 /* Privileged eXecute Never */
/* L1 Fine Descriptor */
#define L1_F_IMP0 0x00000004 /* implementation defined */