summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/sparc64/include/tte.h2
-rw-r--r--sys/sparc64/sparc64/pmap.c63
-rw-r--r--sys/sparc64/sparc64/tsb.c18
3 files changed, 61 insertions, 22 deletions
diff --git a/sys/sparc64/include/tte.h b/sys/sparc64/include/tte.h
index bc81cb0..70337fe 100644
--- a/sys/sparc64/include/tte.h
+++ b/sys/sparc64/include/tte.h
@@ -68,6 +68,8 @@
#define TD_NFO (1UL << 60)
#define TD_IE (1UL << 59)
#define TD_PA(pa) ((pa) & (TD_PA_MASK << TD_PA_SHIFT))
+/* NOTE: bit 6 of TD_SOFT will be sign-extended if used as an immediate. */
+#define TD_FAKE ((1UL << 5) << TD_SOFT_SHIFT)
#define TD_EXEC ((1UL << 4) << TD_SOFT_SHIFT)
#define TD_REF ((1UL << 3) << TD_SOFT_SHIFT)
#define TD_PV ((1UL << 2) << TD_SOFT_SHIFT)
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index 1d6619f..10f5ccc 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -670,6 +670,8 @@ pmap_cache_enter(vm_page_t m, vm_offset_t va)
struct tte *tp;
int color;
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("pmap_cache_enter: fake page"));
PMAP_STATS_INC(pmap_ncache_enter);
/*
@@ -741,6 +743,8 @@ pmap_cache_remove(vm_page_t m, vm_offset_t va)
CTR3(KTR_PMAP, "pmap_cache_remove: m=%p va=%#lx c=%d", m, va,
m->md.colors[DCACHE_COLOR(va)]);
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("pmap_cache_remove: fake page"));
KASSERT(m->md.colors[DCACHE_COLOR(va)] > 0,
("pmap_cache_remove: no mappings %d <= 0",
m->md.colors[DCACHE_COLOR(va)]));
@@ -1252,20 +1256,22 @@ pmap_remove_tte(struct pmap *pm, struct pmap *pm2, struct tte *tp,
u_long data;
data = atomic_readandclear_long(&tp->tte_data);
- m = PHYS_TO_VM_PAGE(TD_PA(data));
- TAILQ_REMOVE(&m->md.tte_list, tp, tte_link);
- if ((data & TD_WIRED) != 0)
- pm->pm_stats.wired_count--;
- if ((data & TD_PV) != 0) {
- if ((data & TD_W) != 0 && pmap_track_modified(pm, va))
- vm_page_dirty(m);
- if ((data & TD_REF) != 0)
- vm_page_flag_set(m, PG_REFERENCED);
- if (TAILQ_EMPTY(&m->md.tte_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
- pm->pm_stats.resident_count--;
+ if ((data & TD_FAKE) == 0) {
+ m = PHYS_TO_VM_PAGE(TD_PA(data));
+ TAILQ_REMOVE(&m->md.tte_list, tp, tte_link);
+ if ((data & TD_WIRED) != 0)
+ pm->pm_stats.wired_count--;
+ if ((data & TD_PV) != 0) {
+ if ((data & TD_W) != 0 && pmap_track_modified(pm, va))
+ vm_page_dirty(m);
+ if ((data & TD_REF) != 0)
+ vm_page_flag_set(m, PG_REFERENCED);
+ if (TAILQ_EMPTY(&m->md.tte_list))
+ vm_page_flag_clear(m, PG_WRITEABLE);
+ pm->pm_stats.resident_count--;
+ }
+ pmap_cache_remove(m, va);
}
- pmap_cache_remove(m, va);
TTE_ZERO(tp);
if (PMAP_REMOVE_DONE(pm))
return (0);
@@ -1308,7 +1314,7 @@ pmap_remove_all(vm_page_t m)
vm_offset_t va;
KASSERT((m->flags & (PG_FICTITIOUS|PG_UNMANAGED)) == 0,
- ("pv_remove_all: illegal for unmanaged page %#lx",
+ ("pmap_remove_all: illegal for unmanaged/fake page %#lx",
VM_PAGE_TO_PHYS(m)));
for (tp = TAILQ_FIRST(&m->md.tte_list); tp != NULL; tp = tpn) {
tpn = TAILQ_NEXT(tp, tte_link);
@@ -1395,9 +1401,24 @@ pmap_enter(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
struct tte *tp;
vm_offset_t pa;
u_long data;
+ int i;
PMAP_STATS_INC(pmap_nenter);
pa = VM_PAGE_TO_PHYS(m);
+
+ /*
+ * If this is a fake page from the device_pager, but it covers actual
+ * physical memory, convert to the real backing page.
+ */
+ if ((m->flags & PG_FICTITIOUS) != 0) {
+ for (i = 0; phys_avail[i + 1] != 0; i += 2) {
+ if (pa >= phys_avail[i] && pa <= phys_avail[i + 1]) {
+ m = PHYS_TO_VM_PAGE(pa);
+ break;
+ }
+ }
+ }
+
CTR6(KTR_PMAP,
"pmap_enter: ctx=%p m=%p va=%#lx pa=%#lx prot=%#x wired=%d",
pm->pm_context[PCPU_GET(cpuid)], m, va, pa, prot, wired);
@@ -1479,7 +1500,7 @@ pmap_enter(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
/*
* Now set up the data and install the new mapping.
*/
- data = TD_V | TD_8K | TD_PA(pa) | TD_CP;
+ data = TD_V | TD_8K | TD_PA(pa);
if (pm == kernel_pmap)
data |= TD_P;
if (prot & VM_PROT_WRITE)
@@ -1585,6 +1606,8 @@ pmap_zero_page(vm_page_t m)
vm_offset_t va;
struct tte *tp;
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("pmap_zero_page: fake page"));
PMAP_STATS_INC(pmap_nzero_page);
pa = VM_PAGE_TO_PHYS(m);
if (m->md.color == -1) {
@@ -1612,6 +1635,8 @@ pmap_zero_page_area(vm_page_t m, int off, int size)
vm_offset_t va;
struct tte *tp;
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("pmap_zero_page_area: fake page"));
KASSERT(off + size <= PAGE_SIZE, ("pmap_zero_page_area: bad off/size"));
PMAP_STATS_INC(pmap_nzero_page_area);
pa = VM_PAGE_TO_PHYS(m);
@@ -1640,6 +1665,8 @@ pmap_zero_page_idle(vm_page_t m)
vm_offset_t va;
struct tte *tp;
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("pmap_zero_page_idle: fake page"));
PMAP_STATS_INC(pmap_nzero_page_idle);
pa = VM_PAGE_TO_PHYS(m);
if (m->md.color == -1) {
@@ -1669,6 +1696,10 @@ pmap_copy_page(vm_page_t msrc, vm_page_t mdst)
vm_offset_t vsrc;
struct tte *tp;
+ KASSERT((mdst->flags & PG_FICTITIOUS) == 0,
+ ("pmap_copy_page: fake dst page"));
+ KASSERT((msrc->flags & PG_FICTITIOUS) == 0,
+ ("pmap_copy_page: fake src page"));
PMAP_STATS_INC(pmap_ncopy_page);
pdst = VM_PAGE_TO_PHYS(mdst);
psrc = VM_PAGE_TO_PHYS(msrc);
@@ -1777,6 +1808,8 @@ void
pmap_page_protect(vm_page_t m, vm_prot_t prot)
{
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("pmap_page_protect: fake page"));
if ((prot & VM_PROT_WRITE) == 0) {
if (prot & (VM_PROT_READ | VM_PROT_EXECUTE))
pmap_clear_write(m);
diff --git a/sys/sparc64/sparc64/tsb.c b/sys/sparc64/sparc64/tsb.c
index 2f2df1d..7b678d0 100644
--- a/sys/sparc64/sparc64/tsb.c
+++ b/sys/sparc64/sparc64/tsb.c
@@ -154,16 +154,20 @@ tsb_tte_enter(pmap_t pm, vm_page_t m, vm_offset_t va, u_long sz, u_long data)
}
enter:
- if ((m->flags & (PG_UNMANAGED | PG_FICTITIOUS)) == 0) {
- pm->pm_stats.resident_count++;
- data |= TD_PV;
- }
- if (pmap_cache_enter(m, va) != 0)
- data |= TD_CV;
+ if ((m->flags & PG_FICTITIOUS) == 0) {
+ data |= TD_CP;
+ if ((m->flags & PG_UNMANAGED) == 0) {
+ pm->pm_stats.resident_count++;
+ data |= TD_PV;
+ }
+ if (pmap_cache_enter(m, va) != 0)
+ data |= TD_CV;
+ TAILQ_INSERT_TAIL(&m->md.tte_list, tp, tte_link);
+ } else
+ data |= TD_FAKE | TD_E;
tp->tte_vpn = TV_VPN(va, sz);
tp->tte_data = data;
- TAILQ_INSERT_TAIL(&m->md.tte_list, tp, tte_link);
return (tp);
}
OpenPOWER on IntegriCloud