Ok, a bit of explanation first.
On macppc because the AGP chips do not translate pages, the kernel and
the applications have access to the AGP memory regions through standard
mappings. Because these regions are mean to share commands and data and
the AGP bridges are not cache-coherent, they are mapped NOCACHE by the
appleagp driver.
However in the case of the dri/drm infrastructure these memory regions
are first allocated and mapped by the agp driver then mmap'ed by the
userland graphic driver.
In this case for an AGP memory region you have at least 4 different way
to address it:
- its physical address
- its virtual address in the GPU space
- its kernel virtual address
- at least one user virtual address
So the aim of the diff below, thanks to kettenis@, is to keep track of
uncached managed memory pages to be sure that a page mapped cache-
inhibited first will not be re-mapped write-back (or write-through)
later.
However this diff does not deal with the case where a page is first
mapped as cacheable then remapped later as cache-inhibited. I've no
idea how to do this easily and I do not need this in the actual case.
Do you think it is required? Any hint?
This solve a cache-coherency problem where menus and windows wouldn't
disappear from my screen because the userland mmap'ed memory regions
were cached while the kernel ones weren't.
Comments? Ok?
Martin
Index: include/pmap.h
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/include/pmap.h,v
retrieving revision 1.48
diff -u -p -r1.48 pmap.h
--- include/pmap.h 30 Aug 2012 18:14:26 -0000 1.48
+++ include/pmap.h 19 Nov 2012 14:41:45 -0000
@@ -141,9 +141,10 @@ int reserve_dumppages(caddr_t p);
#define PMAP_STEAL_MEMORY
-#define PG_PMAP_MOD PG_PMAP0
-#define PG_PMAP_REF PG_PMAP1
-#define PG_PMAP_EXE PG_PMAP2
+#define PG_PMAP_MOD PG_PMAP0
+#define PG_PMAP_REF PG_PMAP1
+#define PG_PMAP_EXE PG_PMAP2
+#define PG_PMAP_NC PG_PMAP3
/*
* MD flags to pmap_enter:
Index: powerpc/pmap.c
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/powerpc/pmap.c,v
retrieving revision 1.119
diff -u -p -r1.119 pmap.c
--- powerpc/pmap.c 30 Aug 2012 18:14:26 -0000 1.119
+++ powerpc/pmap.c 23 Nov 2012 10:42:42 -0000
@@ -586,8 +586,13 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
/* Calculate PTE */
pg = PHYS_TO_VM_PAGE(pa);
- if (pg != NULL && !nocache)
- cache = PMAP_CACHE_WB; /* managed memory is cacheable */
+
+ /*
+ * Managed memory is cacheable if it has not already been mapped
+ * as non-cacheable and the PMAP_NOCACHE flag was not specified.
+ */
+ if (pg != NULL && !(pg->pg_flags & PG_PMAP_NC) && !nocache)
+ cache = PMAP_CACHE_WB;
else
cache = PMAP_CACHE_CI;
@@ -597,6 +602,13 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
pmap_fill_pte32(pm, va, pa, pted, prot, flags, cache);
if (pg != NULL) {
+ /*
+ * Keep track of non-cacheable managed memory pages to
+ * be sure they won't be remaped cacheable later.
+ */
+ if (nocache && !(pg->pg_flags & PG_PMAP_NC))
+ atomic_setbits_int(&pg->pg_flags, PG_PMAP_NC);
+
pmap_enter_pv(pted, pg); /* only managed mem */
}