summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2002-03-17 01:51:32 +0000
committerjake <jake@FreeBSD.org>2002-03-17 01:51:32 +0000
commitab433ce9315248a8f326229470d63dddee8ff950 (patch)
tree98af833252b8e2ffd1f2092cbf3a608d97b5d0d1 /sys/sparc64
parentcdf21113df657b3ab5c2ca4491c050d6e5262b39 (diff)
downloadFreeBSD-src-ab433ce9315248a8f326229470d63dddee8ff950.zip
FreeBSD-src-ab433ce9315248a8f326229470d63dddee8ff950.tar.gz
Fix a problem where kernel text could become unmapped when clearing out all
the user mappings from the tlb due to the context numbers rolling over. The store to the internal mmu register must be followed by a membar #Sync before much else happens to "avoid data corruption", so we use special inlines which both disable interrupts and ensure that the compiler will not insert extra instructions between the two. Also, load the tte tag and check if the context is nucleus context, rather than relying on the priviledged bit which doesn't actually serve any purpose in our design, and check the lock bit too for sanity.
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/sparc64/pmap.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index 14b4b0c..fcc0405 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -479,21 +479,22 @@ void
pmap_context_rollover(void)
{
u_long data;
+ u_long tag;
int i;
mtx_assert(&sched_lock, MA_OWNED);
CTR0(KTR_PMAP, "pmap_context_rollover");
for (i = 0; i < 64; i++) {
data = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_DATA_ACCESS_REG);
- if ((data & TD_V) != 0 && (data & TD_P) == 0) {
- stxa(TLB_DAR_SLOT(i), ASI_DTLB_DATA_ACCESS_REG, 0);
- membar(Sync);
- }
+ tag = ldxa(TLB_DAR_SLOT(i), ASI_DTLB_TAG_READ_REG);
+ if ((data & TD_V) != 0 && (data & TD_L) == 0 &&
+ TLB_TAR_CTX(tag) != TLB_CTX_KERNEL)
+ stxa_sync(TLB_DAR_SLOT(i), ASI_DTLB_DATA_ACCESS_REG, 0);
data = ldxa(TLB_DAR_SLOT(i), ASI_ITLB_DATA_ACCESS_REG);
- if ((data & TD_V) != 0 && (data & TD_P) == 0) {
- stxa(TLB_DAR_SLOT(i), ASI_ITLB_DATA_ACCESS_REG, 0);
- membar(Sync);
- }
+ tag = ldxa(TLB_DAR_SLOT(i), ASI_ITLB_TAG_READ_REG);
+ if ((data & TD_V) != 0 && (data & TD_L) == 0 &&
+ TLB_TAR_CTX(tag) != TLB_CTX_KERNEL)
+ stxa_sync(TLB_DAR_SLOT(i), ASI_ITLB_DATA_ACCESS_REG, 0);
}
PCPU_SET(tlb_ctx, PCPU_GET(tlb_ctx_min));
}
OpenPOWER on IntegriCloud