-/* $OpenBSD: locore.s,v 1.191 2022/01/02 23:34:15 jsg Exp $ */
+/* $OpenBSD: locore.s,v 1.192 2022/09/08 17:44:48 miod Exp $ */
/* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */
/*
#define HORRID_III_HACK
-#undef NO_VCACHE /* Map w/D$ disabled */
-#undef DCACHE_BUG /* Flush D$ around ASI_PHYS accesses */
-#undef NO_TSB /* Don't use TSB */
-
.register %g2,
.register %g3,
.previous
-/*
- * This macro will clear out a cache line before an explicit
- * access to that location. It's mostly used to make certain
- * loads bypassing the D$ do not get stale D$ data.
- *
- * It uses a register with the address to clear and a temporary
- * which is destroyed.
- */
- .macro DLFLUSH a,t
-#ifdef DCACHE_BUG
- andn \a, 0x1f, \t
- stxa %g0, [ \t ] ASI_DCACHE_TAG
- membar #Sync
-#endif /* DCACHE_BUG */
- .endm
-/* The following can be used if the pointer is 16-byte aligned */
- .macro DLFLUSH2 t
-#ifdef DCACHE_BUG
- stxa %g0, [ \t ] ASI_DCACHE_TAG
- membar #Sync
-#endif /* DCACHE_BUG */
- .endm
-
/*
* A handy macro for maintaining instrumentation counters.
* Note that this clobbers %o0, %o1 and %o2. Normal usage is
and %g5, PDMASK, %g5
sll %g5, 3, %g5
add %g6, %g4, %g4
- DLFLUSH %g4,%g6
ldxa [%g4] ASI_PHYS_CACHED, %g4
- DLFLUSH2 %g6
srlx %g3, PTSHIFT, %g6 ! Convert to ptab offset
and %g6, PTMASK, %g6
add %g5, %g4, %g5
and %g7, STMASK, %g7
sll %g7, 3, %g7
add %g7, %g1, %g1
- DLFLUSH %g1,%g7
ldxa [%g1] ASI_PHYS_CACHED, %g1 ! Load pointer to directory
- DLFLUSH2 %g7
srlx %g6, PDSHIFT, %g7 ! Do page directory
and %g7, PDMASK, %g7
sll %g7, 3, %g7
brz,pn %g1, 0f
add %g7, %g1, %g1
- DLFLUSH %g1,%g7
ldxa [%g1] ASI_PHYS_CACHED, %g1
- DLFLUSH2 %g7
srlx %g6, PTSHIFT, %g7 ! Convert to ptab offset
and %g7, PTMASK, %g7
brz %g1, 0f
sll %g7, 3, %g7
add %g1, %g7, %g7
- DLFLUSH %g7,%g1
ldxa [%g7] ASI_PHYS_CACHED, %g7 ! This one is not
- DLFLUSH2 %g1
brgez %g7, 0f
srlx %g7, PGSHIFT, %g7 ! Isolate PA part
sll %g6, 32-PGSHIFT, %g6 ! And offset
mov %g7, %g1
CHKPT %g5,%g7,0x13
add %g6, PCB_NSAVED, %g7
- DLFLUSH %g7,%g5
lduba [%g6 + PCB_NSAVED] %asi, %g7 ! Start incrementing pcb_nsaved
- DLFLUSH2 %g5
#ifdef DEBUG
wrpr %g0, 5, %tl
sub %o3, 0x1d, %o3
brz,a %o3, 0f
mov %g0, %o5
- DLFLUSH %o0,%o5 ! flush cache line
! }
0:
btst 1, %o4
membar #Sync
brz %o5, 1f ! if (cache flush addr != 0)
nop
- DLFLUSH2 %o5 ! flush cache line again
1:
wr %g0, ASI_PRIMARY_NOFAULT, %asi ! Restore default ASI
stx %g0, [%o2 + PCB_ONFAULT]
#endif /* DDB */
/*
- * pmap_zero_page(pa)
+ * pmap_zero_phys(pa)
*
* Zero one page physically addressed
*
END(pmap_zero_phys)
/*
- * pmap_copy_page(src, dst)
+ * pmap_copy_phys(src, dst)
*
* Copy one page physically addressed
*
* We also need to blast the D$ and flush like
- * pmap_zero_page.
+ * pmap_zero_phys.
*/
ENTRY(pmap_copy_phys)
set NBPG, %o3
and %o3, STMASK, %o3 ! Index into pm_segs
sll %o3, 3, %o3
add %o2, %o3, %o2
- DLFLUSH %o2,%o3
ldxa [%o2] ASI_PHYS_CACHED, %o2 ! Load page directory pointer
- DLFLUSH2 %o3
srlx %o1, PDSHIFT, %o3
and %o3, PDMASK, %o3
sll %o3, 3, %o3
brz,pn %o2, 1f ! NULL entry? check somewhere else
add %o2, %o3, %o2
- DLFLUSH %o2,%o3
ldxa [%o2] ASI_PHYS_CACHED, %o2 ! Load page table pointer
- DLFLUSH2 %o3
srlx %o1, PTSHIFT, %o3 ! Convert to ptab offset
and %o3, PTMASK, %o3
sll %o3, 3, %o3
brz,pn %o2, 1f ! NULL entry? check somewhere else
add %o2, %o3, %o2
- DLFLUSH %o2,%o3
ldxa [%o2] ASI_PHYS_CACHED, %o0
- DLFLUSH2 %o3
brgez,pn %o0, 1f ! Entry invalid? Punt
nop
retl
sll %o5, 3, %o5
add %o4, %o5, %o4
2:
- DLFLUSH %o4,%g1
ldxa [%o4] ASI_PHYS_CACHED, %o5 ! Load page directory pointer
- DLFLUSH2 %g1
brnz,a,pt %o5, 0f ! Null pointer?
mov %o5, %o4
mov %o3, %o5
casxa [%o4] ASI_PHYS_CACHED, %g0, %o5
brnz,pn %o5, 2b ! Something changed?
- DLFLUSH %o4, %o5
mov %o3, %o4
clr %o3 ! Mark spare as used
0:
sll %o5, 3, %o5
add %o4, %o5, %o4
2:
- DLFLUSH %o4,%g1
ldxa [%o4] ASI_PHYS_CACHED, %o5 ! Load table directory pointer
- DLFLUSH2 %g1
brnz,a,pt %o5, 0f ! Null pointer?
mov %o5, %o4
mov %o3, %o5
casxa [%o4] ASI_PHYS_CACHED, %g0, %o5
brnz,pn %o5, 2b ! Something changed?
- DLFLUSH %o4, %o4
mov %o3, %o4
clr %o3 ! Mark spare as used
0:
sll %o5, 3, %o5
add %o5, %o4, %o4
stxa %o2, [%o4] ASI_PHYS_CACHED ! Easier than shift+or
- DLFLUSH %o4, %o4
mov 2, %o0 ! spare unused?
retl
movrz %o3, %g0, %o0 ! No. return 0
-/* $OpenBSD: pmap.c,v 1.104 2022/01/02 23:39:48 jsg Exp $ */
+/* $OpenBSD: pmap.c,v 1.105 2022/09/08 17:44:48 miod Exp $ */
/* $NetBSD: pmap.c,v 1.107 2001/08/31 16:47:41 eeh Exp $ */
-#undef NO_VCACHE /* Don't forget the locked TLB in dostart */
/*
*
* Copyright (C) 1996-1999 Eduardo Horvath.
paddr_t cpu0paddr;/* XXXXXXXXXXXXXXXX */
-extern int64_t asmptechk(int64_t *pseg[], int addr); /* DEBUG XXXXX */
-
/* These routines are in assembly to allow access thru physical mappings */
extern int64_t pseg_get(struct pmap*, vaddr_t addr);
extern int pseg_set(struct pmap*, vaddr_t addr, int64_t tte, paddr_t spare);
-/* XXX - temporary workaround for pmap_{copy,zero}_page api change */
-void pmap_zero_phys(paddr_t pa);
-void pmap_copy_phys(paddr_t src, paddr_t dst);
+extern void pmap_zero_phys(paddr_t pa);
+extern void pmap_copy_phys(paddr_t src, paddr_t dst);
/*
* Diatribe on ref/mod counting:
* and collect/clear all the ref/mod information and copy it into the pv_entry.
*/
-#ifdef NO_VCACHE
-#define FORCE_ALIAS 1
-#else
-#define FORCE_ALIAS 0
-#endif
-
#define PV_ALIAS 0x1LL
#define PV_REF 0x2LL
#define PV_MOD 0x4LL
-#define PV_NVC 0x8LL
-#define PV_NC 0x10LL
-#define PV_WE 0x20LL /* Debug -- track if this page was ever writable */
#define PV_MASK (0x03fLL)
#define PV_VAMASK (~(NBPG - 1))
#define PV_MATCH(pv,va) (!((((pv)->pv_va) ^ (va)) & PV_VAMASK))
#define PV_SETVA(pv,va) ((pv)->pv_va = (((va) & PV_VAMASK) | (((pv)->pv_va) & PV_MASK)))
-pv_entry_t pv_table; /* array of entries, one per page */
static struct pool pv_pool;
static struct pool pmap_pool;
void pmap_release(struct pmap *);
pv_entry_t pa_to_pvh(paddr_t);
-u_int64_t first_phys_addr;
-
pv_entry_t
pa_to_pvh(paddr_t pa)
{
struct pmap kernel_pmap_;
-extern int physmem;
/*
* Virtual and physical addresses of the start and end of kernel text
* and data segments.
vaddr_t ekdata;
paddr_t ekdatap;
-static int npgs;
static struct mem_region memlist[8]; /* Pick a random size here */
vaddr_t vmmap; /* one reserved MI vpage for /dev/mem */
* page bits. That is: these are the bits between 8K pages and
* larger page sizes that cause aliasing.
*/
-struct page_size_map page_size_map[] = {
+const struct page_size_map page_size_map[] = {
{ (4*1024*1024-1) & ~(8*1024-1), PGSZ_4M },
{ (512*1024-1) & ~(8*1024-1), PGSZ_512K },
{ (64*1024-1) & ~(8*1024-1), PGSZ_64K },
{ (8*1024-1) & ~(8*1024-1), PGSZ_8K },
- { 0, PGSZ_8K&0 }
+ { 0, 0 }
};
/*
}
#endif
- first_phys_addr = mem->start;
BDPRINTF(PDB_BOOT1, ("firstaddr after pmap=%08lx\r\n",
(u_long)firstaddr));
* Now we need to remove the area we valloc'ed from the available
* memory lists. (NB: we may have already alloc'ed the entire space).
*/
- npgs = 0;
for (mp = avail; mp->size; mp++) {
/*
* Check whether this region holds all of the kernel.
}
s = mp->start;
sz = mp->size;
- npgs += atop(sz);
for (mp1 = avail; mp1 < mp; mp1++)
if (s < mp1->start)
break;
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
- FORCE_ALIAS /* ALIAS -- Disable D$ */,
+ 0 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
pmap_enter_kpage(va, data);
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
- FORCE_ALIAS /* ALIAS -- Disable D$ */,
+ 0 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
pmap_enter_kpage(vmmap, data);
1 /* priv */,
1 /* Write */,
1 /* Cacheable */,
- FORCE_ALIAS /* ALIAS -- Disable D$ */,
+ 0 /* ALIAS -- Disable D$ */,
1 /* valid */,
0 /* IE */);
pmap_enter_kpage(vmmap, data);
index = 15; /* XXX */
for (va = ktext, pa = ktextp; va < ektext; va += 4*MEG, pa += 4*MEG) {
- data = SUN4U_TSB_DATA(0, PGSZ_4M, pa, 1, 0, 1, FORCE_ALIAS, 1, 0);
+ data = SUN4U_TSB_DATA(0, PGSZ_4M, pa, 1, 0, 1, 0, 1, 0);
data |= SUN4U_TLB_L;
prom_itlb_load(index, data, va);
prom_dtlb_load(index, data, va);
}
for (va = kdata, pa = kdatap; va < ekdata; va += 4*MEG, pa += 4*MEG) {
- data = SUN4U_TSB_DATA(0, PGSZ_4M, pa, 1, 1, 1, FORCE_ALIAS, 1, 0);
+ data = SUN4U_TSB_DATA(0, PGSZ_4M, pa, 1, 1, 1, 0, 1, 0);
data |= SUN4U_TLB_L;
prom_dtlb_load(index, data, va);
index--;
if ((CPU_JUPITERID % 2) == 1)
index--;
- data = SUN4U_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, FORCE_ALIAS, 1, 0);
+ data = SUN4U_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, 0, 1, 0);
data |= SUN4U_TLB_L;
prom_dtlb_load(index, data, va - (CPUINFO_VA - INTSTACK));
* Establish the 64KB locked mapping for the interrupt stack.
*/
- data = SUN4U_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, FORCE_ALIAS, 1, 0);
+ data = SUN4U_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, 0, 1, 0);
data |= SUN4U_TLB_L;
prom_dtlb_load(index, data, INTSTACK);
struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
mtx_enter(&pg->mdpage.pvmtx);
- aliased = (pv->pv_va & (PV_ALIAS|PV_NVC));
+ aliased = (pv->pv_va & PV_ALIAS);
#ifdef DIAGNOSTIC
if ((flags & PROT_MASK) & ~prot)
panic("pmap_enter: access_type exceeds prot");
}
if (pa & PMAP_NVC)
aliased = 1;
-#ifdef NO_VCACHE
- aliased = 1; /* Disable D$ */
-#endif
if (CPU_ISSUN4V) {
tte.data = SUN4V_TSB_DATA(0, size, pa, pm == pmap_kernel(),
(flags & PROT_WRITE), (!(pa & PMAP_NC)),
/* Clear all mappings */
mtx_enter(&pg->mdpage.pvmtx);
pv = pa_to_pvh(pa);
- if (pv->pv_va & PV_MOD)
+ if (pv->pv_va & PV_MOD) {
changed |= 1;
- pv->pv_va &= ~(PV_MOD);
+ pv->pv_va &= ~PV_MOD;
+ }
if (pv->pv_pmap != NULL) {
for (; pv; pv = pv->pv_next) {
int64_t data;
pv->pv_pmap->pm_ctx);
}
/* Then clear the mod bit in the pv */
- if (pv->pv_va & PV_MOD)
+ if (pv->pv_va & PV_MOD) {
changed |= 1;
- pv->pv_va &= ~(PV_MOD);
+ pv->pv_va &= ~PV_MOD;
+ }
dcache_flush_page(pa);
}
}
/* Clear all references */
mtx_enter(&pg->mdpage.pvmtx);
pv = pa_to_pvh(pa);
- if (pv->pv_va & PV_REF)
+ if (pv->pv_va & PV_REF) {
changed = 1;
- pv->pv_va &= ~(PV_REF);
+ pv->pv_va &= ~PV_REF;
+ }
if (pv->pv_pmap != NULL) {
for (; pv; pv = pv->pv_next) {
int64_t data;
pv->pv_pmap->pm_ctx);
*/
}
- if (pv->pv_va & PV_REF)
+ if (pv->pv_va & PV_REF) {
changed = 1;
- pv->pv_va &= ~(PV_REF);
+ pv->pv_va &= ~PV_REF;
+ }
}
}
/* Stupid here will take a cache hit even on unmapped pages 8^( */
if (pmap_tte2flags(data) & PV_MOD)
mod = 1;
/* Migrate modify info to head pv */
- if (npv->pv_va & PV_MOD)
+ if (npv->pv_va & PV_MOD) {
mod = 1;
- npv->pv_va &= ~PV_MOD;
+ npv->pv_va &= ~PV_MOD;
+ }
}
}
/* Save modify info */
if (pmap_tte2flags(data) & PV_REF)
ref = 1;
/* Migrate modify info to head pv */
- if (npv->pv_va & PV_REF)
+ if (npv->pv_va & PV_REF) {
ref = 1;
- npv->pv_va &= ~PV_REF;
+ npv->pv_va &= ~PV_REF;
+ }
}
}
/* Save ref info */
* remove all mappings, flush the cache and set page
* to be mapped uncached. Caching will be restored
* when pages are mapped compatible again.
- * XXX - caching is not currently being restored, but
- * XXX - I haven't seen the pages uncached since
- * XXX - using pmap_prefer(). mhitch
*/
if ((pv->pv_va ^ va) & VA_ALIAS_MASK) {
pv->pv_va |= PV_ALIAS;
pv_entry_t pv, opv, npv = NULL;
struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
int64_t data = 0LL;
+ int alias;
opv = pv = &pg->mdpage.pvent;
mtx_enter(&pg->mdpage.pvmtx);
/* Check to see if the alias went away */
if (opv->pv_va & PV_ALIAS) {
- opv->pv_va &= ~PV_ALIAS;
+ alias = 0;
for (pv = opv; pv; pv = pv->pv_next) {
if ((pv->pv_va ^ opv->pv_va) & VA_ALIAS_MASK) {
- opv->pv_va |= PV_ALIAS;
+ alias = 1;
+ break;
}
}
- if (!(opv->pv_va & PV_ALIAS))
+ if (alias == 0) {
+ opv->pv_va &= ~PV_ALIAS;
pmap_page_cache(pmap, pa, 1);
+ }
}
mtx_leave(&pg->mdpage.pvmtx);
vaddr_t va;
va = (pv->pv_va & PV_VAMASK);
- if (pv->pv_va & PV_NC) {
- /* Non-cached -- I/O mapping */
- if (pseg_set(pv->pv_pmap, va,
- pseg_get(pv->pv_pmap, va) & ~(SUN4U_TLB_CV|SUN4U_TLB_CP),
- 0)) {
- printf("pmap_page_cache: aliased pseg empty!\n");
- db_enter();
- /* panic? */
- }
- } else if (mode && (!(pv->pv_va & PV_NVC))) {
+ if (mode) {
/* Enable caching */
if (pseg_set(pv->pv_pmap, va,
pseg_get(pv->pv_pmap, va) | SUN4U_TLB_CV, 0)) {