Implement X-only mappings on sun4u by not letting the dtlb miss handler
authormiod <miod@openbsd.org>
Wed, 11 Jan 2023 19:57:17 +0000 (19:57 +0000)
committermiod <miod@openbsd.org>
Wed, 11 Jan 2023 19:57:17 +0000 (19:57 +0000)
allow ttes with the "exec only" bit; joint work with deraadt@, unfortunately
no effect on sun4v due to the lack of software bits in ttes to fit an
"exec only" bit.

ok deraadt@ kettenis@

sys/arch/sparc64/sparc64/genassym.cf
sys/arch/sparc64/sparc64/locore.s
sys/arch/sparc64/sparc64/pmap.c

index 1e38922..48fd26b 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: genassym.cf,v 1.39 2022/10/21 18:55:42 miod Exp $
+#      $OpenBSD: genassym.cf,v 1.40 2023/01/11 19:57:17 miod Exp $
 #      $NetBSD: genassym.cf,v 1.23 2001/08/08 00:09:30 eeh Exp $
 
 #
@@ -269,6 +269,7 @@ export      SUN4U_TLB_ACCESS
 export SUN4U_TLB_MODIFY
 export SUN4U_TLB_REAL_W
 export SUN4U_TLB_EXEC
+export SUN4U_TLB_EXEC_ONLY
 export SUN4U_TLB_W
 
 export SUN4V_TLB_ACCESS
index be95325..891eeb2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: locore.s,v 1.197 2023/01/06 19:10:18 miod Exp $       */
+/*     $OpenBSD: locore.s,v 1.198 2023/01/11 19:57:17 miod Exp $       */
 /*     $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $    */
 
 /*
@@ -1714,11 +1714,15 @@ data_miss:
 1:
        ldxa    [%g6] ASI_PHYS_CACHED, %g4
        brgez,pn %g4, data_nfo                          ! Entry invalid?  Punt
-        or     %g4, SUN4U_TLB_ACCESS, %g7              ! Update the access bit
+        nop
+
+       btst    SUN4U_TLB_EXEC_ONLY, %g4                ! no read/write allowed?
+       bne,pn  %xcc, data_nfo                          ! bail
+        nop
        
        btst    SUN4U_TLB_ACCESS, %g4                   ! Need to update access git?
        bne,pt  %xcc, 1f
-        nop
+        or     %g4, SUN4U_TLB_ACCESS, %g7              ! Update the access bit
        casxa   [%g6] ASI_PHYS_CACHED, %g4, %g7         !  and write it out
        cmp     %g4, %g7
        bne,pn  %xcc, 1b
index 2903f1a..5715ab8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.107 2023/01/10 17:38:10 miod Exp $ */
+/*     $OpenBSD: pmap.c,v 1.108 2023/01/11 19:57:18 miod Exp $ */
 /*     $NetBSD: pmap.c,v 1.107 2001/08/31 16:47:41 eeh Exp $   */
 /*
  * 
@@ -780,7 +780,6 @@ remap_data:
                OF_exit();
        }
 
-
        /*
         * Now the kernel text segment is in its final location we can try to
         * find out how much memory really is free.  
@@ -1691,6 +1690,8 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
                        tte.data |= SUN4U_TLB_REAL_W|SUN4U_TLB_W;
                if (prot & PROT_EXEC)
                        tte.data |= SUN4U_TLB_EXEC;
+               if (prot == PROT_EXEC)
+                       tte.data |= SUN4U_TLB_EXEC_ONLY;
                tte.data |= SUN4U_TLB_TSB_LOCK; /* wired */
        }
        KDASSERT((tte.data & TLB_NFO) == 0);
@@ -1823,6 +1824,8 @@ pmap_enter(struct pmap *pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
                        tte.data |= SUN4U_TLB_REAL_W;
                if (prot & PROT_EXEC)
                        tte.data |= SUN4U_TLB_EXEC;
+               if (prot == PROT_EXEC)
+                       tte.data |= SUN4U_TLB_EXEC_ONLY;
                if (wired)
                        tte.data |= SUN4U_TLB_TSB_LOCK;
        }
@@ -1947,8 +1950,7 @@ pmap_protect(struct pmap *pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
        KDASSERT(pm != pmap_kernel() || eva < INTSTACK || sva > EINTSTACK);
        KDASSERT(pm != pmap_kernel() || eva < kdata || sva > ekdata);
 
-       if ((prot & (PROT_WRITE | PROT_EXEC)) ==
-           (PROT_WRITE | PROT_EXEC))
+       if ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC))
                return;
 
        if (prot == PROT_NONE) {
@@ -1991,7 +1993,7 @@ pmap_protect(struct pmap *pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
                                if ((prot & PROT_WRITE) == 0)
                                        data &= ~(SUN4U_TLB_W|SUN4U_TLB_REAL_W);
                                if ((prot & PROT_EXEC) == 0)
-                                       data &= ~(SUN4U_TLB_EXEC);
+                                       data &= ~(SUN4U_TLB_EXEC | SUN4U_TLB_EXEC_ONLY);
                        }
                        KDASSERT((data & TLB_NFO) == 0);
                        if (pseg_set(pm, sva, data, 0)) {
@@ -2470,6 +2472,8 @@ pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
                                clear |= SUN4U_TLB_EXEC;
                        if (PROT_EXEC == prot)
                                set |= SUN4U_TLB_EXEC_ONLY;
+                       else
+                               clear |= SUN4U_TLB_EXEC_ONLY;
                }
 
                pv = pa_to_pvh(pa);