Add support for the PXN bit in level 1 translation table descriptors and
authorkettenis <kettenis@openbsd.org>
Sat, 27 Aug 2016 14:22:35 +0000 (14:22 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 27 Aug 2016 14:22:35 +0000 (14:22 +0000)
enable it on CPUs that support it.  When enabled, this prevents the kernel
from executing userland code.

ok jsg@, tom@

sys/arch/arm/arm/pmap7.c
sys/arch/arm/include/pte.h

index 0889e54..4997cea 100644 (file)
@@ -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 $   */
 
 /*
@@ -302,6 +302,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
  */
@@ -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)
index 059e281..4dc2638 100644 (file)
@@ -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 */