summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2009-10-21 18:38:02 +0000
committermarcel <marcel@FreeBSD.org>2009-10-21 18:38:02 +0000
commit51bb720939567fa381c6a03839b51f9c80bc67ef (patch)
tree9665f89431ede73407ae0ad11ebcc8198166085e /sys/ia64
parent5598d561ce3ef08a3a8c5d518ca09e28883ff050 (diff)
downloadFreeBSD-src-51bb720939567fa381c6a03839b51f9c80bc67ef.zip
FreeBSD-src-51bb720939567fa381c6a03839b51f9c80bc67ef.tar.gz
o Introduce vm_sync_icache() for making the I-cache coherent with
the memory or D-cache, depending on the semantics of the platform. vm_sync_icache() is basically a wrapper around pmap_sync_icache(), that translates the vm_map_t argumument to pmap_t. o Introduce pmap_sync_icache() to all PMAP implementation. For powerpc it replaces the pmap_page_executable() function, added to solve the I-cache problem in uiomove_fromphys(). o In proc_rwmem() call vm_sync_icache() when writing to a page that has execute permissions. This assures that when breakpoints are written, the I-cache will be coherent and the process will actually hit the breakpoint. o This also fixes the Book-E PMAP implementation that was missing necessary locking while trying to deal with the I-cache coherency in pmap_enter() (read: mmu_booke_enter_locked). The key property of this change is that the I-cache is made coherent *after* writes have been done. Doing it in the PMAP layer when adding or changing a mapping means that the I-cache is made coherent *before* any writes happen. The difference is key when the I-cache prefetches.
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/pmap.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index a5a2bc3..a6fac1f 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -2276,6 +2276,33 @@ out:
return (prevpm);
}
+void
+pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+ pmap_t oldpm;
+ struct ia64_lpte *pte;
+ vm_offset_t lim;
+ vm_size_t len;
+
+ sz += va & 31;
+ va &= ~31;
+ sz = (sz + 31) & ~31;
+
+ PMAP_LOCK(pm);
+ oldpm = pmap_switch(pm);
+ while (sz > 0) {
+ lim = round_page(va);
+ len = MIN(lim - va, sz);
+ pte = pmap_find_vhpt(va);
+ if (pte != NULL && pmap_present(pte))
+ ia64_sync_icache(va, len);
+ va += len;
+ sz -= len;
+ }
+ pmap_switch(oldpm);
+ PMAP_UNLOCK(pm);
+}
+
/*
* Increase the starting virtual address of the given mapping if a
* different alignment might result in more superpage mappings.
OpenPOWER on IntegriCloud