Modify the cache handling code to assume 2 virtual colours, which is much

simpler and easier to get right.  Add comments.  Add more statistic
gathering on cacheable and uncacheable mappings.
This commit is contained in:
Jake Burkholder 2002-08-01 00:16:22 +00:00
parent b519494ef1
commit 256e0b2bbb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=101121

View File

@ -179,7 +179,13 @@ static long pmap_enter_nupdate;
static long pmap_enter_nreplace;
static long pmap_enter_nnew;
static long pmap_ncache_enter;
static long pmap_ncache_enter_c;
static long pmap_ncache_enter_cc;
static long pmap_ncache_enter_nc;
static long pmap_ncache_remove;
static long pmap_ncache_remove_c;
static long pmap_ncache_remove_cc;
static long pmap_ncache_remove_nc;
static long pmap_niflush;
SYSCTL_NODE(_debug, OID_AUTO, pmap_stats, CTLFLAG_RD, 0, "Statistics");
@ -191,8 +197,20 @@ SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_enter_nnew, CTLFLAG_RD,
&pmap_enter_nnew, 0, "Number of pmap_enter() additions");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_enter, CTLFLAG_RD,
&pmap_ncache_enter, 0, "Number of pmap_cache_enter() calls");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_enter_c, CTLFLAG_RD,
&pmap_ncache_enter_c, 0, "Number of pmap_cache_enter() cacheable");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_enter_cc, CTLFLAG_RD,
&pmap_ncache_enter_cc, 0, "Number of pmap_cache_enter() change color");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_enter_nc, CTLFLAG_RD,
&pmap_ncache_enter_nc, 0, "Number of pmap_cache_enter() nc");
&pmap_ncache_enter_nc, 0, "Number of pmap_cache_enter() noncacheable");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_remove, CTLFLAG_RD,
&pmap_ncache_remove, 0, "Number of pmap_cache_remove() calls");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_remove_c, CTLFLAG_RD,
&pmap_ncache_remove_c, 0, "Number of pmap_cache_remove() cacheable");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_remove_cc, CTLFLAG_RD,
&pmap_ncache_remove_cc, 0, "Number of pmap_cache_remove() change color");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_ncache_remove_nc, CTLFLAG_RD,
&pmap_ncache_remove_nc, 0, "Number of pmap_cache_remove() noncacheable");
SYSCTL_LONG(_debug_pmap_stats, OID_AUTO, pmap_niflush, CTLFLAG_RD,
&pmap_niflush, 0, "Number of pmap I$ flushes");
@ -585,32 +603,53 @@ pmap_cache_enter(vm_page_t m, vm_offset_t va)
{
struct tte *tp;
int color;
int c, i;
CTR2(KTR_PMAP, "pmap_cache_enter: m=%p va=%#lx", m, va);
PMAP_STATS_INC(pmap_ncache_enter);
/*
* Find the color for this virtual address and note the added mapping.
*/
color = DCACHE_COLOR(va);
m->md.colors[color]++;
/*
* If all existing mappings have the same color, the mapping is
* cacheable.
*/
if (m->md.color == color) {
CTR0(KTR_PMAP, "pmap_cache_enter: cacheable");
KASSERT(m->md.colors[DCACHE_OTHER_COLOR(color)] == 0,
("pmap_cache_enter: cacheable, mappings of other color"));
PMAP_STATS_INC(pmap_ncache_enter_c);
return (1);
}
for (c = 0, i = 0; i < DCACHE_COLORS; i++) {
if (m->md.colors[i] != 0)
c++;
}
if (c == 1) {
/*
* If there are no mappings of the other color, and the page still has
* the wrong color, this must be a new mapping. Change the color to
* match the new mapping, which is cacheable. We must flush the page
* from the cache now.
*/
if (m->md.colors[DCACHE_OTHER_COLOR(color)] == 0) {
KASSERT(m->md.colors[color] == 1,
("pmap_cache_enter: changing color, not new mapping"));
dcache_page_inval(VM_PAGE_TO_PHYS(m));
m->md.color = color;
CTR0(KTR_PMAP, "pmap_cache_enter: cacheable");
PMAP_STATS_INC(pmap_ncache_enter_cc);
return (1);
}
PMAP_STATS_INC(pmap_ncache_enter_nc);
if (m->md.color == -1) {
CTR0(KTR_PMAP, "pmap_cache_enter: already uncacheable");
/*
* If the mapping is already non-cacheable, just return.
*/
if (m->md.color == -1)
return (0);
}
CTR0(KTR_PMAP, "pmap_cache_enter: marking uncacheable");
/*
* Mark all mappings as uncacheable, flush any lines with the other
* color out of the dcache, and set the color to none (-1).
*/
STAILQ_FOREACH(tp, &m->md.tte_list, tte_link) {
tp->tte_data &= ~TD_CV;
tlb_page_demap(TTE_GET_PMAP(tp), TTE_GET_VA(tp));
@ -625,28 +664,56 @@ pmap_cache_remove(vm_page_t m, vm_offset_t va)
{
struct tte *tp;
int color;
int c, i;
CTR3(KTR_PMAP, "pmap_cache_remove: m=%p va=%#lx c=%d", m, va,
m->md.colors[DCACHE_COLOR(va)]);
KASSERT(m->md.colors[DCACHE_COLOR(va)] > 0,
("pmap_cache_remove: no mappings %d <= 0",
m->md.colors[DCACHE_COLOR(va)]));
PMAP_STATS_INC(pmap_ncache_remove);
/*
* Find the color for this virtual address and note the removal of
* the mapping.
*/
color = DCACHE_COLOR(va);
m->md.colors[color]--;
if (m->md.color != -1 || m->md.colors[color] != 0)
/*
* If the page is cacheable, just return and keep the same color, even
* if there are no longer any mappings.
*/
if (m->md.color != -1) {
PMAP_STATS_INC(pmap_ncache_remove_c);
return;
for (c = 0, i = 0; i < DCACHE_COLORS; i++) {
if (m->md.colors[i] != 0)
c++;
}
if (c == 0)
KASSERT(m->md.colors[DCACHE_OTHER_COLOR(color)] != 0,
("pmap_cache_remove: uncacheable, no mappings of other color"));
/*
* If the page is not cacheable (color is -1), and the number of
* mappings for this color is not zero, just return. There are
* mappings of the other color still, so remain non-cacheable.
*/
if (m->md.colors[color] != 0) {
PMAP_STATS_INC(pmap_ncache_remove_nc);
return;
}
PMAP_STATS_INC(pmap_ncache_remove_cc);
/*
* The number of mappings for this color is now zero. Recache the
* other colored mappings, and change the page color to the other
* color. There should be no lines in the data cache for this page,
* so flushing should not be needed.
*/
STAILQ_FOREACH(tp, &m->md.tte_list, tte_link) {
tp->tte_data |= TD_CV;
tlb_page_demap(TTE_GET_PMAP(tp), TTE_GET_VA(tp));
}
m->md.color = color;
m->md.color = DCACHE_OTHER_COLOR(color);
}
/*
@ -782,11 +849,16 @@ pmap_map_direct(vm_page_t m)
vm_offset_t va;
pa = VM_PAGE_TO_PHYS(m);
if (m->md.color == -1)
if (m->md.color == -1) {
KASSERT(m->md.colors[0] != 0 && m->md.colors[1] != 0,
("pmap_map_direct: non-cacheable, only 1 color"));
va = TLB_DIRECT_MASK | pa | TLB_DIRECT_UNCACHEABLE;
else
} else {
KASSERT(m->md.colors[DCACHE_OTHER_COLOR(m->md.color)] == 0,
("pmap_map_direct: cacheable, mappings of other color"));
va = TLB_DIRECT_MASK | pa |
(m->md.color << TLB_DIRECT_COLOR_SHIFT);
}
return (va << TLB_DIRECT_SHIFT);
}