If TLB entries need to be flushed, make sure to do this after any necessary
cache flushes, since on VIPT machines the cache flush may induce a TLB load.
This commit is contained in:
parent
4655ae1230
commit
1040b9e209
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmap.c,v 1.144 1999/05/16 16:48:59 pk Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.145 1999/05/20 10:03:12 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
|
@ -524,7 +524,7 @@ void (*pmap_rmu_p) __P((struct pmap *, vaddr_t, vaddr_t, int, int));
|
|||
* Macros which implement SRMMU TLB flushing/invalidation
|
||||
*/
|
||||
#define tlb_flush_page(va) \
|
||||
sta(((va) & ~0xfff) | ASI_SRMMUFP_L3, ASI_SRMMUFP, 0)
|
||||
sta(((vaddr_t)(va) & ~0xfff) | ASI_SRMMUFP_L3, ASI_SRMMUFP, 0)
|
||||
|
||||
#define tlb_flush_segment(vr, vs) \
|
||||
sta(((vr)<<RGSHIFT) | ((vs)<<SGSHIFT) | ASI_SRMMUFP_L2, ASI_SRMMUFP,0)
|
||||
|
@ -628,6 +628,7 @@ setpgt4m(ptep, pte)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the page table entry for va to pte. Only affects software MMU page-
|
||||
* tables (the in-core pagetables read by the MMU). Ignores TLB, and
|
||||
|
@ -1714,11 +1715,17 @@ mmu_pagein(pm, va, prot)
|
|||
#ifdef DEBUG
|
||||
if (pm == pmap_kernel())
|
||||
printf("mmu_pagein: kernel wants map at va 0x%x, vr %d, vs %d\n", va, vr, vs);
|
||||
#endif
|
||||
#if 0
|
||||
#if defined(SUN4_MMU3L)
|
||||
printf("mmu_pagein: pm=%p, va 0x%x, vr %d, vs %d, rp=%p, segmap=%p\n", pm, va, vr, vs, rp, rp->rg_segmap);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* return 0 if we have no PMEGs to load */
|
||||
if (rp->rg_segmap == NULL)
|
||||
return (0);
|
||||
|
||||
#if defined(SUN4_MMU3L)
|
||||
if (HASSUN4_MMU3L && rp->rg_smeg == reginval) {
|
||||
smeg_t smeg;
|
||||
|
@ -2472,8 +2479,13 @@ pv_syncflags4m(pv0)
|
|||
flags |= MR4M(tpte);
|
||||
|
||||
if (pm->pm_ctx && (tpte & SRMMU_PG_M)) {
|
||||
cache_flush_page(va); /* XXX: do we need this?*/
|
||||
tlb_flush_page(va); /* paranoid? */
|
||||
/* Only do this for write-back caches? */
|
||||
cache_flush_page(va);
|
||||
/*
|
||||
* VIPT caches might use the TLB when
|
||||
* flushing, so we flush the TLB again.
|
||||
*/
|
||||
tlb_flush_page(va);
|
||||
}
|
||||
|
||||
/* Clear mod/ref bits from PTE and write it back */
|
||||
|
@ -2641,6 +2653,10 @@ pv_flushcache(pv)
|
|||
if (pm->pm_ctx) {
|
||||
setcontext(pm->pm_ctxnum);
|
||||
cache_flush_page(pv->pv_va);
|
||||
#if defined(SUN4M)
|
||||
if (CPU_ISSUN4M)
|
||||
tlb_flush_page(pv->pv_va);
|
||||
#endif
|
||||
}
|
||||
pv = pv->pv_next;
|
||||
if (pv == NULL)
|
||||
|
@ -4229,7 +4245,7 @@ pmap_rmk4m(pm, va, endva, vr, vs)
|
|||
}
|
||||
/* if we're done with a region, leave it wired */
|
||||
}
|
||||
#endif /* sun4m */
|
||||
#endif /* SUN4M */
|
||||
/*
|
||||
* Just like pmap_rmk_magic, but we have a different threshold.
|
||||
* Note that this may well deserve further tuning work.
|
||||
|
@ -4459,9 +4475,6 @@ pmap_rmu4m(pm, va, endva, vr, vs)
|
|||
for (; va < endva; va += NBPG) {
|
||||
int tpte;
|
||||
|
||||
if (pm->pm_ctx)
|
||||
tlb_flush_page(va);
|
||||
|
||||
tpte = pte0[VA_SUN4M_VPG(va)];
|
||||
|
||||
if ((tpte & SRMMU_TETYPE) != SRMMU_TEPTE) {
|
||||
|
@ -4492,6 +4505,9 @@ pmap_rmu4m(pm, va, endva, vr, vs)
|
|||
panic("pmap_rmu: too many PTEs in segment; "
|
||||
"va 0x%lx; endva 0x%lx", va, endva);
|
||||
#endif
|
||||
if (pm->pm_ctx)
|
||||
tlb_flush_page(va);
|
||||
|
||||
setpgt4m(&pte0[VA_SUN4M_VPG(va)], SRMMU_TEINVALID);
|
||||
}
|
||||
|
||||
|
@ -5072,8 +5088,8 @@ pmap_protect4m(pm, sva, eva, prot)
|
|||
vaddr_t sva, eva;
|
||||
vm_prot_t prot;
|
||||
{
|
||||
int va, nva, vr, vs;
|
||||
int s, ctx;
|
||||
vaddr_t va, nva;
|
||||
int s, ctx, vr, vs;
|
||||
struct regmap *rp;
|
||||
struct segmap *sp;
|
||||
|
||||
|
@ -5085,6 +5101,13 @@ pmap_protect4m(pm, sva, eva, prot)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (pmapdebug & PDB_CHANGEPROT)
|
||||
printf("pmap_protect[curpid %d, ctx %d](%lx, %lx, %x)\n",
|
||||
curproc==NULL ? -1 : curproc->p_pid,
|
||||
pm->pm_ctx ? pm->pm_ctxnum : -1, sva, eva, prot);
|
||||
#endif
|
||||
|
||||
write_user_windows();
|
||||
ctx = getcontext4m();
|
||||
s = splpmap();
|
||||
|
@ -5116,7 +5139,9 @@ pmap_protect4m(pm, sva, eva, prot)
|
|||
if (sp->sg_pte == NULL)
|
||||
panic("pmap_protect: no pages");
|
||||
#endif
|
||||
/* pages loaded: take away write bits from MMU PTEs */
|
||||
/*
|
||||
* pages loaded: take away write bits from MMU PTEs
|
||||
*/
|
||||
if (pm->pm_ctx)
|
||||
setcontext4m(pm->pm_ctxnum);
|
||||
|
||||
|
@ -5124,11 +5149,6 @@ pmap_protect4m(pm, sva, eva, prot)
|
|||
for (; va < nva; va += NBPG) {
|
||||
int tpte;
|
||||
|
||||
if (pm->pm_ctx) {
|
||||
/* Flush TLB entry */
|
||||
tlb_flush_page(va);
|
||||
}
|
||||
|
||||
tpte = sp->sg_pte[VA_SUN4M_VPG(va)];
|
||||
/*
|
||||
* Flush cache so that any existing cache
|
||||
|
@ -5140,6 +5160,8 @@ pmap_protect4m(pm, sva, eva, prot)
|
|||
pmap_stats.ps_npg_prot_actual++;
|
||||
if (pm->pm_ctx) {
|
||||
cache_flush_page(va);
|
||||
/* Flush TLB entry */
|
||||
tlb_flush_page(va);
|
||||
}
|
||||
setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)],
|
||||
tpte & ~PPROT_WRITE);
|
||||
|
@ -5188,14 +5210,7 @@ pmap_changeprot4m(pm, va, prot, wired)
|
|||
rp = &pm->pm_regmap[VA_VREG(va)];
|
||||
sp = &rp->rg_segmap[VA_VSEG(va)];
|
||||
|
||||
ctx = getcontext4m();
|
||||
if (pm->pm_ctx) {
|
||||
/* Flush TLB entry */
|
||||
setcontext4m(pm->pm_ctxnum);
|
||||
tlb_flush_page(va);
|
||||
}
|
||||
pte = sp->sg_pte[VA_SUN4M_VPG(va)];
|
||||
|
||||
if ((pte & SRMMU_PROT_MASK) == newprot) {
|
||||
/* only wiring changed, and we ignore wiring */
|
||||
pmap_stats.ps_useless_changeprots++;
|
||||
|
@ -5208,18 +5223,24 @@ pmap_changeprot4m(pm, va, prot, wired)
|
|||
* Flush cache if page has been referenced to
|
||||
* avoid stale protection bits in the cache tags.
|
||||
*/
|
||||
|
||||
ctx = getcontext4m();
|
||||
setcontext4m(pm->pm_ctxnum);
|
||||
if ((pte & (SRMMU_PG_C|SRMMU_PGTYPE)) ==
|
||||
(SRMMU_PG_C|PG_SUN4M_OBMEM))
|
||||
cache_flush_page(va);
|
||||
|
||||
tlb_flush_page(va);
|
||||
setcontext4m(ctx);
|
||||
}
|
||||
|
||||
setpgt4m(&sp->sg_pte[VA_SUN4M_VPG(va)],
|
||||
(pte & ~SRMMU_PROT_MASK) | newprot);
|
||||
|
||||
out:
|
||||
setcontext4m(ctx);
|
||||
splx(s);
|
||||
}
|
||||
#endif /* 4m */
|
||||
#endif /* SUN4M */
|
||||
|
||||
/*
|
||||
* Insert (MI) physical page pa at virtual address va in the given pmap.
|
||||
|
@ -5473,6 +5494,7 @@ printf("pmap_enter: segment filled during sleep\n"); /* can this happen? */
|
|||
rp->rg_nsegmap = 0;
|
||||
for (i = NSEGRG; --i >= 0;)
|
||||
sp++->sg_pmeg = seginval;
|
||||
|
||||
#if defined(SUN4_MMU3L)
|
||||
/*
|
||||
* XXX - preallocate the region MMU cookies.
|
||||
|
@ -5640,8 +5662,11 @@ pmap_enter4m(pm, va, pa, prot, wired, access_type)
|
|||
|
||||
#ifdef DEBUG
|
||||
if (pmapdebug & PDB_ENTER)
|
||||
printf("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n",
|
||||
pm, va, pa, prot, wired);
|
||||
printf("pmap_enter[curpid %d, ctx %d]"
|
||||
"(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n",
|
||||
curproc==NULL ? -1 : curproc->p_pid,
|
||||
pm->pm_ctx==NULL ? -1 : pm->pm_ctxnum,
|
||||
pm, va, pa, prot, wired);
|
||||
#endif
|
||||
|
||||
/* Initialise pteproto with cache bit */
|
||||
|
@ -5928,7 +5953,7 @@ printf("%s[%d]: pmap_enu: changing existing va 0x%x: pte 0x%x=>0x%x\n",
|
|||
|
||||
splx(s);
|
||||
}
|
||||
#endif /* sun4m */
|
||||
#endif /* SUN4M */
|
||||
|
||||
/*
|
||||
* Change the wiring attribute for a map/virtual-address pair.
|
||||
|
@ -6045,7 +6070,7 @@ pmap_extract4m(pm, va)
|
|||
if ((rm = pm->pm_regmap) == NULL) {
|
||||
#ifdef DEBUG
|
||||
if (pmapdebug & PDB_FOLLOW)
|
||||
printf("pmap_extract: no regmap entry");
|
||||
printf("pmap_extract: no regmap entry\n");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
@ -6054,7 +6079,7 @@ pmap_extract4m(pm, va)
|
|||
if ((sm = rm->rg_segmap) == NULL) {
|
||||
#ifdef DEBUG
|
||||
if (pmapdebug & PDB_FOLLOW)
|
||||
panic("pmap_extract: no segmap");
|
||||
printf("pmap_extract: no segmap\n");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
@ -6063,7 +6088,7 @@ pmap_extract4m(pm, va)
|
|||
if (sm->sg_pte == NULL) {
|
||||
#ifdef DEBUG
|
||||
if (pmapdebug & PDB_FOLLOW)
|
||||
panic("pmap_extract: no ptes");
|
||||
printf("pmap_extract: no ptes\n");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
@ -6410,7 +6435,7 @@ pmap_copy_page4_4c(src, dst)
|
|||
setpte4(sva, spte);
|
||||
setpte4(dva, dpte);
|
||||
qcopy(sva, dva, NBPG); /* loads cache, so we must ... */
|
||||
cache_flush_page((int)sva);
|
||||
cache_flush_page((vaddr_t)sva);
|
||||
setpte4(sva, 0);
|
||||
setpte4(dva, 0);
|
||||
}
|
||||
|
@ -6423,6 +6448,7 @@ pmap_copy_page4_4c(src, dst)
|
|||
* We avoid stomping on the cache.
|
||||
* XXX might be faster to use destination's context and allow cache to fill?
|
||||
*/
|
||||
int xxxdebug = 0;
|
||||
void
|
||||
pmap_zero_page4m(pa)
|
||||
paddr_t pa;
|
||||
|
@ -6439,18 +6465,15 @@ pmap_zero_page4m(pa)
|
|||
if (CACHEINFO.c_vactype != VAC_NONE)
|
||||
pv_flushcache(pvhead(pa));
|
||||
}
|
||||
pte = (SRMMU_TEPTE | PPROT_S | PPROT_WRITE |
|
||||
(atop(pa) << SRMMU_PPNSHIFT));
|
||||
pte = SRMMU_TEPTE | PPROT_N_RWX | (atop(pa) << SRMMU_PPNSHIFT);
|
||||
if (cpuinfo.flags & CPUFLG_CACHE_MANDATORY)
|
||||
pte |= SRMMU_PG_C;
|
||||
else
|
||||
pte &= ~SRMMU_PG_C;
|
||||
|
||||
va = vpage[0];
|
||||
setpgt4m(vpage_pte[0], pte);
|
||||
qzero(va, NBPG);
|
||||
/* Remove temporary mapping */
|
||||
tlb_flush_page((int)va);
|
||||
tlb_flush_page(va);
|
||||
setpgt4m(vpage_pte[0], SRMMU_TEINVALID);
|
||||
}
|
||||
|
||||
|
@ -6474,7 +6497,8 @@ pmap_copy_page4m(src, dst)
|
|||
if (CACHEINFO.c_vactype == VAC_WRITEBACK)
|
||||
pv_flushcache(pvhead(src));
|
||||
}
|
||||
spte = SRMMU_TEPTE | SRMMU_PG_C | PPROT_S |
|
||||
|
||||
spte = SRMMU_TEPTE | SRMMU_PG_C | PPROT_N_RX |
|
||||
(atop(src) << SRMMU_PPNSHIFT);
|
||||
|
||||
if (managed(dst)) {
|
||||
|
@ -6482,22 +6506,20 @@ pmap_copy_page4m(src, dst)
|
|||
if (CACHEINFO.c_vactype != VAC_NONE)
|
||||
pv_flushcache(pvhead(dst));
|
||||
}
|
||||
dpte = (SRMMU_TEPTE | PPROT_S | PPROT_WRITE |
|
||||
(atop(dst) << SRMMU_PPNSHIFT));
|
||||
|
||||
dpte = SRMMU_TEPTE | PPROT_N_RWX | (atop(dst) << SRMMU_PPNSHIFT);
|
||||
if (cpuinfo.flags & CPUFLG_CACHE_MANDATORY)
|
||||
dpte |= SRMMU_PG_C;
|
||||
else
|
||||
dpte &= ~SRMMU_PG_C;
|
||||
|
||||
sva = vpage[0];
|
||||
dva = vpage[1];
|
||||
setpgt4m(vpage_pte[0], spte);
|
||||
setpgt4m(vpage_pte[1], dpte);
|
||||
qcopy(sva, dva, NBPG); /* loads cache, so we must ... */
|
||||
cache_flush_page((int)sva);
|
||||
tlb_flush_page((int)sva);
|
||||
cache_flush_page((vaddr_t)sva);
|
||||
tlb_flush_page(sva);
|
||||
setpgt4m(vpage_pte[0], SRMMU_TEINVALID);
|
||||
tlb_flush_page((int)dva);
|
||||
tlb_flush_page(dva);
|
||||
setpgt4m(vpage_pte[1], SRMMU_TEINVALID);
|
||||
}
|
||||
#endif /* SUN4M */
|
||||
|
|
Loading…
Reference in New Issue