From 8c38b3156c90d1e1803d9f3404cfb66d963b0cfc Mon Sep 17 00:00:00 2001 From: miod Date: Wed, 11 Jan 2023 19:57:17 +0000 Subject: [PATCH] Implement X-only mappings on sun4u by not letting the dtlb miss handler 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 | 3 ++- sys/arch/sparc64/sparc64/locore.s | 10 +++++++--- sys/arch/sparc64/sparc64/pmap.c | 14 +++++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/sys/arch/sparc64/sparc64/genassym.cf b/sys/arch/sparc64/sparc64/genassym.cf index 1e389227cf4..48fd26b907f 100644 --- a/sys/arch/sparc64/sparc64/genassym.cf +++ b/sys/arch/sparc64/sparc64/genassym.cf @@ -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 diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index be95325d5e7..891eeb2aef6 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -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 diff --git a/sys/arch/sparc64/sparc64/pmap.c b/sys/arch/sparc64/sparc64/pmap.c index 2903f1a59ee..5715ab81644 100644 --- a/sys/arch/sparc64/sparc64/pmap.c +++ b/sys/arch/sparc64/sparc64/pmap.c @@ -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); -- 2.20.1