Subject: Using different cache modes for r/o vs r/w pages
To: None <port-arm@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: port-arm
Date: 01/29/2002 20:53:08
--+Yg8W10oK6rlW0RR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi folks...
To work around some errata in current XScale CPUs, I need to use
different cache modes for r/o vs r/w pages. In particular, I need
to use write-back for r/w pages and write-though for r/o pages (if
r/o pages have a write-back cache mode in the PTE, a write-fault
to the page doesn't always cancel the store to memory, causing
obvious problems).
I've more-or-less implemented this, but there are some problems. I
seem to have memory corruption when e.g. forks occur (i.e. transitioning
pages from write-back to write-though when they are made r/o for COW).
All works "fine" with I use write-through for both r/o and r/w pages.
Diff of arch/arm and arch/evbarm is attached (I've actually modified all
of the relevant code in all the ports, but I have ommitted them for the
sake of brevity).
The patch essentially does:
* Replace PT_CACHEABLE with a pte_cache_mode[] array, indexed
by protection code (e.g. VM_PROT_READ, VM_PROT_READ|VM_PROT_WRITE,
etc.) Replace all uses of PT_CACHEABLE with an access of the
array.
* Replace uses of (PT_B | PT_C) when clearing cache bits from a
PTE with a new global pte_cache_bits. This will be more
important for a future change, which will make the kernel
use the extended cache modes available on the XScale.
* When changing permission on a page, clear the existing
cache bits in the PTE and set new cache bits based on the
new page protection. This requires a Wb cache operation
on the page. (I certainly hope it doesn't require a
WbInv.)
I would like someone to review my changes to see if I've missed anything
really obvious. In particular, someone who's actually hacked on the
cache stuff inside the pmap (Richard?)
Thanks.
--
-- Jason R. Thorpe <thorpej@wasabisystems.com>
--+Yg8W10oK6rlW0RR
Content-Type: text/plain; charset=us-ascii
Content-Description: pmap-cache-diff
Content-Disposition: attachment; filename=foo
Index: arm/arm/cpufunc.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/arm/cpufunc.c,v
retrieving revision 1.29
diff -c -r1.29 cpufunc.c
*** arm/arm/cpufunc.c 2002/01/30 00:37:18 1.29
--- arm/arm/cpufunc.c 2002/01/30 04:25:58
***************
*** 53,58 ****
--- 53,61 ----
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
+
+ #include <uvm/uvm_extern.h>
+
#include <machine/cpu.h>
#include <machine/bootconfig.h>
#include <arch/arm/arm/disassem.h>
***************
*** 650,655 ****
--- 653,659 ----
cpu_reset_needs_v4_MMU_disable = 0;
/* XXX Cache info? */
arm_dcache_align_mask = -1;
+ pmap_pte_protos_init_arm678();
return 0;
}
#endif /* CPU_ARM6 */
***************
*** 661,666 ****
--- 665,671 ----
cpu_reset_needs_v4_MMU_disable = 0;
/* XXX Cache info? */
arm_dcache_align_mask = -1;
+ pmap_pte_protos_init_arm678();
return 0;
}
#endif /* CPU_ARM7 */
***************
*** 671,676 ****
--- 676,682 ----
cpufuncs = arm7tdmi_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0;
get_cachetype();
+ pmap_pte_protos_init_arm678();
return 0;
}
#endif
***************
*** 680,694 ****
cpufuncs = arm8_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */
get_cachetype();
return 0;
}
#endif /* CPU_ARM8 */
#ifdef CPU_ARM9
if (cputype == CPU_ID_ARM920T) {
- pte_cache_mode = PT_C; /* Select write-through cacheing. */
cpufuncs = arm9_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
get_cachetype();
return 0;
}
#endif /* CPU_ARM9 */
--- 686,701 ----
cpufuncs = arm8_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */
get_cachetype();
+ pmap_pte_protos_init_arm678();
return 0;
}
#endif /* CPU_ARM8 */
#ifdef CPU_ARM9
if (cputype == CPU_ID_ARM920T) {
cpufuncs = arm9_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
get_cachetype();
+ pmap_pte_protos_init_arm9();
return 0;
}
#endif /* CPU_ARM9 */
***************
*** 698,703 ****
--- 705,711 ----
cpufuncs = sa110_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */
get_cachetype();
+ pmap_pte_protos_init_arm678(); /* XXX */
/*
* Enable the right variant of sleeping.
*/
***************
*** 743,749 ****
:
: "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV));
- pte_cache_mode = PT_C; /* Select write-through cacheing. */
cpufuncs = xscale_cpufuncs;
/*
--- 751,756 ----
***************
*** 758,763 ****
--- 765,771 ----
cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
get_cachetype();
+ pmap_pte_protos_init_xscale();
return 0;
}
#endif /* CPU_XSCALE */
Index: arm/arm32/arm32_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/arm32/arm32_machdep.c,v
retrieving revision 1.11
diff -c -r1.11 arm32_machdep.c
*** arm/arm32/arm32_machdep.c 2002/01/20 03:41:47 1.11
--- arm/arm32/arm32_machdep.c 2002/01/30 04:25:58
***************
*** 168,174 ****
if (cacheable)
((u_int *)pagetable)[(va >> PDSHIFT)] =
! L1_SEC((pa & PD_MASK), pte_cache_mode);
else
((u_int *)pagetable)[(va >> PDSHIFT)] =
L1_SEC((pa & PD_MASK), 0);
--- 168,175 ----
if (cacheable)
((u_int *)pagetable)[(va >> PDSHIFT)] =
! L1_SEC((pa & PD_MASK),
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
else
((u_int *)pagetable)[(va >> PDSHIFT)] =
L1_SEC((pa & PD_MASK), 0);
***************
*** 280,289 ****
{
#ifndef cats
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000003ff)] =
! L2_PTE((pa & PG_FRAME), AP_KRW);
#else
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000007ff)] =
! L2_PTE((pa & PG_FRAME), AP_KRW);
#endif
}
--- 281,292 ----
{
#ifndef cats
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000003ff)] =
! L2_SPTE((pa & PG_FRAME), AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
#else
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000007ff)] =
! L2_SPTE((pa & PG_FRAME), AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
#endif
}
***************
*** 296,305 ****
{
#ifndef cats
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000003ff)] =
! L2_PTE_NC_NB((pa & PG_FRAME), AP_KRW);
#else
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000007ff)] =
! L2_PTE_NC_NB((pa & PG_FRAME), AP_KRW);
#endif
}
--- 299,308 ----
{
#ifndef cats
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000003ff)] =
! L2_SPTE((pa & PG_FRAME), AP_KRW, 0);
#else
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000007ff)] =
! L2_SPTE((pa & PG_FRAME), AP_KRW, 0);
#endif
}
***************
*** 312,321 ****
{
#ifndef cats
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000003ff)] =
! L2_PTE((pa & PG_FRAME), AP_KR);
#else
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000007ff)] =
! L2_PTE((pa & PG_FRAME), AP_KR);
#endif
}
--- 315,326 ----
{
#ifndef cats
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000003ff)] =
! L2_SPTE((pa & PG_FRAME), AP_KR,
! pte_cache_mode[VM_PROT_READ]);
#else
((pt_entry_t *)pagetable)[((va >> PGSHIFT) & 0x000007ff)] =
! L2_SPTE((pa & PG_FRAME), AP_KR,
! pte_cache_mode[VM_PROT_READ]);
#endif
}
***************
*** 487,493 ****
zero_page_readonly()
{
WriteWord(PROCESS_PAGE_TBLS_BASE + 0,
! L2_PTE((systempage.pv_pa & PG_FRAME), AP_KR));
cpu_tlb_flushID_SE(0x00000000);
}
--- 492,499 ----
zero_page_readonly()
{
WriteWord(PROCESS_PAGE_TBLS_BASE + 0,
! L2_SPTE((systempage.pv_pa & PG_FRAME), AP_KR,
! pte_cache_mode[VM_PROT_READ]));
cpu_tlb_flushID_SE(0x00000000);
}
***************
*** 503,509 ****
zero_page_readwrite()
{
WriteWord(PROCESS_PAGE_TBLS_BASE + 0,
! L2_PTE((systempage.pv_pa & PG_FRAME), AP_KRW));
cpu_tlb_flushID_SE(0x00000000);
}
--- 509,516 ----
zero_page_readwrite()
{
WriteWord(PROCESS_PAGE_TBLS_BASE + 0,
! L2_SPTE((systempage.pv_pa & PG_FRAME), AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]));
cpu_tlb_flushID_SE(0x00000000);
}
Index: arm/arm32/bus_dma.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/arm32/bus_dma.c,v
retrieving revision 1.8
diff -c -r1.8 bus_dma.c
*** arm/arm32/bus_dma.c 2002/01/25 20:57:41 1.8
--- arm/arm32/bus_dma.c 2002/01/30 04:25:59
***************
*** 547,553 ****
cpu_dcache_wbinv_range(va, NBPG);
cpu_drain_writebuf();
ptep = vtopte(va);
! *ptep = ((*ptep) & (~PT_C | PT_B));
tlb_flush();
}
#ifdef DEBUG_DMA
--- 547,553 ----
cpu_dcache_wbinv_range(va, NBPG);
cpu_drain_writebuf();
ptep = vtopte(va);
! *ptep = *ptep & ~pte_cache_bits;
tlb_flush();
}
#ifdef DEBUG_DMA
Index: arm/arm32/pmap.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/arm32/pmap.c,v
retrieving revision 1.36
diff -c -r1.36 pmap.c
*** arm/arm32/pmap.c 2002/01/25 19:19:25 1.36
--- arm/arm32/pmap.c 2002/01/30 04:26:03
***************
*** 193,198 ****
--- 193,199 ----
extern caddr_t msgbufaddr;
boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
+
/*
* locking data structures
*/
***************
*** 326,336 ****
pt_entry_t *, boolean_t));
/*
! * Cache enable bits in PTE to use on pages that are cacheable.
! * On most machines this is cacheable/bufferable, but on some, eg arm10, we
! * can chose between write-through and write-back cacheing.
*/
! pt_entry_t pte_cache_mode = (PT_C | PT_B);
/*
* real definition of pv_entry.
--- 327,336 ----
pt_entry_t *, boolean_t));
/*
! * PTE cache mode array.
*/
! pt_entry_t pte_cache_mode[8];
! pt_entry_t pte_cache_bits;
/*
* real definition of pv_entry.
***************
*** 943,954 ****
pmap->pm_pdir[ptva + 3] = L1_PTE(l2pa + 0xc00);
PDEBUG(0, printf("pt self reference %lx in %lx\n",
! L2_PTE_NC_NB(l2pa, AP_KRW), pmap->pm_vptpt));
/* Map the page table into the page table area. */
if (selfref) {
*((pt_entry_t *)(pmap->pm_vptpt + ptva)) =
! L2_PTE_NC_NB(l2pa, AP_KRW);
}
/* XXX should be a purge */
/* cpu_tlb_flushD();*/
--- 943,954 ----
pmap->pm_pdir[ptva + 3] = L1_PTE(l2pa + 0xc00);
PDEBUG(0, printf("pt self reference %lx in %lx\n",
! L2_SPTE(l2pa, AP_KRW, 0), pmap->pm_vptpt));
/* Map the page table into the page table area. */
if (selfref) {
*((pt_entry_t *)(pmap->pm_vptpt + ptva)) =
! L2_SPTE(l2pa, AP_KRW, 0);
}
/* XXX should be a purge */
/* cpu_tlb_flushD();*/
***************
*** 1392,1398 ****
/* Revoke cacheability and bufferability */
/* XXX should be done better than this */
! ptes[arm_byte_to_page(va)] &= ~(PT_C | PT_B);
va += NBPG;
m = m->pageq.tqe_next;
--- 1392,1398 ----
/* Revoke cacheability and bufferability */
/* XXX should be done better than this */
! ptes[arm_byte_to_page(va)] &= ~pte_cache_bits;
va += NBPG;
m = m->pageq.tqe_next;
***************
*** 1506,1512 ****
/* Revoke cacheability and bufferability */
/* XXX should be done better than this */
pte = pmap_pte(pmap_kernel(), pmap->pm_vptpt);
! *pte = *pte & ~(PT_C | PT_B);
/* Wire in this page table */
pmap_map_in_l1(pmap, PROCESS_PAGE_TBLS_BASE, pmap->pm_pptpt, TRUE);
--- 1506,1512 ----
/* Revoke cacheability and bufferability */
/* XXX should be done better than this */
pte = pmap_pte(pmap_kernel(), pmap->pm_vptpt);
! *pte = *pte & ~pte_cache_bits;
/* Wire in this page table */
pmap_map_in_l1(pmap, PROCESS_PAGE_TBLS_BASE, pmap->pm_pptpt, TRUE);
***************
*** 1878,1884 ****
* Hook in the page, zero it, and purge the cache for that
* zeroed page. Invalidate the TLB as needed.
*/
! *page_hook0.pte = L2_PTE(phys & PG_FRAME, AP_KRW);
cpu_tlb_flushD_SE(page_hook0.va);
cpu_cpwait();
bzero_page(page_hook0.va);
--- 1878,1885 ----
* Hook in the page, zero it, and purge the cache for that
* zeroed page. Invalidate the TLB as needed.
*/
! *page_hook0.pte = L2_SPTE(phys & PG_FRAME, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
cpu_tlb_flushD_SE(page_hook0.va);
cpu_cpwait();
bzero_page(page_hook0.va);
***************
*** 1910,1916 ****
* Hook in the page, zero it, and purge the cache for that
* zeroed page. Invalidate the TLB as needed.
*/
! *page_hook0.pte = L2_PTE(phys & PG_FRAME, AP_KRW);
cpu_tlb_flushD_SE(page_hook0.va);
cpu_cpwait();
--- 1911,1918 ----
* Hook in the page, zero it, and purge the cache for that
* zeroed page. Invalidate the TLB as needed.
*/
! *page_hook0.pte = L2_SPTE(phys & PG_FRAME, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
cpu_tlb_flushD_SE(page_hook0.va);
cpu_cpwait();
***************
*** 1971,1978 ****
* the cache for the appropriate page. Invalidate the TLB
* as required.
*/
! *page_hook0.pte = L2_PTE(src & PG_FRAME, AP_KRW);
! *page_hook1.pte = L2_PTE(dest & PG_FRAME, AP_KRW);
cpu_tlb_flushD_SE(page_hook0.va);
cpu_tlb_flushD_SE(page_hook1.va);
cpu_cpwait();
--- 1973,1982 ----
* the cache for the appropriate page. Invalidate the TLB
* as required.
*/
! *page_hook0.pte = L2_SPTE(src & PG_FRAME, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
! *page_hook1.pte = L2_SPTE(dest & PG_FRAME, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
cpu_tlb_flushD_SE(page_hook0.va);
cpu_tlb_flushD_SE(page_hook1.va);
cpu_cpwait();
***************
*** 2194,2199 ****
--- 2198,2204 ----
int cacheable_entries = 0;
int kern_cacheable = 0;
int other_writable = 0;
+ int prot;
pv = pvh->pvh_list;
KASSERT(ptes != NULL);
***************
*** 2237,2247 ****
if (cacheable_entries == 0)
return;
for (npv = pv; npv; npv = npv->pv_next) {
! if ((pmap == npv->pv_pmap
! || kpmap == npv->pv_pmap) &&
(npv->pv_flags & PT_NC) == 0) {
ptes[arm_byte_to_page(npv->pv_va)] &=
! ~(PT_C | PT_B);
npv->pv_flags |= PT_NC;
/*
* If this page needs flushing from the
--- 2242,2252 ----
if (cacheable_entries == 0)
return;
for (npv = pv; npv; npv = npv->pv_next) {
! if ((pmap == npv->pv_pmap ||
! kpmap == npv->pv_pmap) &&
(npv->pv_flags & PT_NC) == 0) {
ptes[arm_byte_to_page(npv->pv_va)] &=
! ~pte_cache_bits;
npv->pv_flags |= PT_NC;
/*
* If this page needs flushing from the
***************
*** 2273,2280 ****
if ((pmap == npv->pv_pmap ||
(kpmap == npv->pv_pmap && other_writable == 0)) &&
(npv->pv_flags & PT_NC)) {
ptes[arm_byte_to_page(npv->pv_va)] |=
! pte_cache_mode;
npv->pv_flags &= ~PT_NC;
}
}
--- 2278,2288 ----
if ((pmap == npv->pv_pmap ||
(kpmap == npv->pv_pmap && other_writable == 0)) &&
(npv->pv_flags & PT_NC)) {
+ prot = (npv->pv_flags & PT_Wr) ?
+ VM_PROT_READ | VM_PROT_WRITE :
+ VM_PROT_READ;
ptes[arm_byte_to_page(npv->pv_va)] |=
! pte_cache_mode[prot];
npv->pv_flags &= ~PT_NC;
}
}
***************
*** 2829,2844 ****
if ((flags & VM_PROT_ALL) & ~prot)
panic("pmap_enter: access_type exceeds prot");
#endif
- npte |= pte_cache_mode;
if (flags & VM_PROT_WRITE) {
! npte |= L2_SPAGE | PT_AP(AP_W);
vm_physmem[bank].pmseg.attrs[off] |= PT_H | PT_M;
} else if (flags & VM_PROT_ALL) {
! npte |= L2_SPAGE;
vm_physmem[bank].pmseg.attrs[off] |= PT_H;
} else
! npte |= L2_INVAL;
} else {
if (prot & VM_PROT_WRITE)
npte |= L2_SPAGE | PT_AP(AP_W);
else if (prot & VM_PROT_ALL)
--- 2837,2854 ----
if ((flags & VM_PROT_ALL) & ~prot)
panic("pmap_enter: access_type exceeds prot");
#endif
if (flags & VM_PROT_WRITE) {
! npte |=
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE] |
! L2_SPAGE | PT_AP(AP_W);
vm_physmem[bank].pmseg.attrs[off] |= PT_H | PT_M;
} else if (flags & VM_PROT_ALL) {
! npte |= pte_cache_mode[VM_PROT_READ] | L2_SPAGE;
vm_physmem[bank].pmseg.attrs[off] |= PT_H;
} else
! npte |= pte_cache_mode[VM_PROT_READ] | L2_INVAL;
} else {
+ /* Implicitly un-cached. */
if (prot & VM_PROT_WRITE)
npte |= L2_SPAGE | PT_AP(AP_W);
else if (prot & VM_PROT_ALL)
***************
*** 2920,2926 ****
}
pte = vtopte(va);
KASSERT(!pmap_pte_v(pte));
! *pte = L2_PTE(pa, AP_KRW);
}
void
--- 2930,2942 ----
}
pte = vtopte(va);
KASSERT(!pmap_pte_v(pte));
! #if 1 /* XXX */
! *pte = L2_SPTE(pa, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
! #else
! *pte = L2_SPTE(pa, (prot & VM_PROT_WRITE) ? AP_KRW : AP_KR,
! pte_cache_mode[prot]);
! #endif
}
void
***************
*** 3357,3363 ****
pte = pmap_pte(pv->pv_pmap, va);
KASSERT(pte != NULL);
if (maskbits & (PT_Wr|PT_M)) {
! if ((pv->pv_flags & PT_NC)) {
/*
* Entry is not cacheable: reenable
* the cache, nothing to flush
--- 3373,3379 ----
pte = pmap_pte(pv->pv_pmap, va);
KASSERT(pte != NULL);
if (maskbits & (PT_Wr|PT_M)) {
! if (pv->pv_flags & PT_NC) {
/*
* Entry is not cacheable: reenable
* the cache, nothing to flush
***************
*** 3375,3399 ****
*
*/
if (maskbits & PT_Wr) {
! *pte |= pte_cache_mode;
pv->pv_flags &= ~PT_NC;
}
! } else if (pmap_is_curpmap(pv->pv_pmap))
! /*
* Entry is cacheable: check if pmap is
* current if it is flush it,
* otherwise it won't be in the cache
*/
cpu_idcache_wbinv_range(pv->pv_va, NBPG);
/* make the pte read only */
*pte &= ~PT_AP(AP_W);
}
! if (maskbits & PT_H)
! *pte = (*pte & ~L2_MASK) | L2_INVAL;
! if (pmap_is_curpmap(pv->pv_pmap))
/*
* if we had cacheable pte's we'd clean the
* pte out to memory here
--- 3391,3435 ----
*
*/
if (maskbits & PT_Wr) {
! /*
! * Clear the NC bit in the pv
! * entry; we'll update the PTE
! * below.
! */
pv->pv_flags &= ~PT_NC;
}
! } else if (pmap_is_curpmap(pv->pv_pmap)) {
! /*
* Entry is cacheable: check if pmap is
* current if it is flush it,
* otherwise it won't be in the cache
*/
cpu_idcache_wbinv_range(pv->pv_va, NBPG);
+ }
/* make the pte read only */
*pte &= ~PT_AP(AP_W);
+ if ((pv->pv_flags & PT_NC) == 0)
+ *pte = (*pte & ~pte_cache_bits) |
+ pte_cache_mode[VM_PROT_READ];
}
! if (maskbits & PT_H) {
! /*
! * We might be going from write-back to write-though,
! * so make sure the cache is flushed.
! *
! * XXXJRT This flush might be redundant!
! */
! if ((pv->pv_flags & PT_Wr) != 0 &&
! pmap_is_curpmap(pv->pv_pmap))
! cpu_idcache_wbinv_range(pv->pv_va, NBPG);
! *pte = (*pte & ~(L2_MASK | pte_cache_bits)) |
! L2_INVAL | pte_cache_mode[VM_PROT_READ];
! }
!
! if (pmap_is_curpmap(pv->pv_pmap)) {
/*
* if we had cacheable pte's we'd clean the
* pte out to memory here
***************
*** 3401,3406 ****
--- 3437,3443 ----
* flush tlb entry as it's in the current pmap
*/
cpu_tlb_flushID_SE(pv->pv_va);
+ }
}
cpu_cpwait();
***************
*** 3540,3546 ****
* already set the cacheable bits based on the assumption that we
* can write to this page.
*/
! *pte = (*pte & ~L2_MASK) | L2_SPAGE | PT_AP(AP_W);
PDEBUG(0, printf("->(%08x)\n", *pte));
simple_unlock(&pvh->pvh_lock);
--- 3577,3585 ----
* already set the cacheable bits based on the assumption that we
* can write to this page.
*/
! *pte = (*pte & ~(L2_MASK | pte_cache_bits)) |
! L2_SPAGE | PT_AP(AP_W) |
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE];
PDEBUG(0, printf("->(%08x)\n", *pte));
simple_unlock(&pvh->pvh_lock);
***************
*** 3719,3723 ****
// pmap->pm_ptphint = ptp;
return (ptp);
}
! /* End of pmap.c */
--- 3758,3830 ----
// pmap->pm_ptphint = ptp;
return (ptp);
}
+
+ /*
+ * pmap_pte_protos_init:
+ *
+ * Initialize the prototype PTE arrays. This is done very
+ * early, right after the cpufunc vector is selected.
+ */
+ #if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \
+ defined(CPU_ARM8) || defined(CPU_SA110)
+ void
+ pmap_pte_protos_init_arm678(void)
+ {
+ int prot;
+
+ pte_cache_bits = PT_B | PT_C;
+
+ for (prot = 0; prot < 8; prot++)
+ pte_cache_mode[prot] = PT_B | PT_C;
+ }
+ #endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */
! #if defined(CPU_ARM9)
! void
! pmap_pte_protos_init_arm9(void)
! {
! int prot;
!
! pte_cache_bits = PT_B | PT_C;
!
! /* We use the cache in write-through mode. */
!
! for (prot = 0; prot < 8; prot++)
! pte_cache_mode[prot] = PT_C;
! }
! #endif /* CPU_ARM9 */
!
! #if defined(CPU_XSCALE)
! void
! pmap_pte_protos_init_xscale(void)
! {
! int prot;
!
! /* XXX X-bit */
! pte_cache_bits = PT_B | PT_C;
!
! /* We use the cache in write-through mode. */
!
! for (prot = 0; prot < 8; prot++) {
! /*
! * i80200 errata item #40: Store to cacheable memory,
! * interrupted by an exception, may inadvertently
! * write to memory.
! *
! * This can have an adverse affect on copy-on-write
! * operation.
! *
! * Work-around: Non-writable mappings should have
! * a cache mode of write-through (this avoids the
! * problem). This has no adverse performance affect,
! * since the mappings are read-only.
! */
! if ((prot & VM_PROT_WRITE) == 0)
! pte_cache_mode[prot] = PT_C;
! else {
! /* Use the cache in write-though mode for now... */
! pte_cache_mode[prot] = PT_C;
! }
! }
! }
! #endif /* CPU_XSCALE */
Index: arm/footbridge/footbridge_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/footbridge/footbridge_machdep.c,v
retrieving revision 1.5
diff -c -r1.5 footbridge_machdep.c
*** arm/footbridge/footbridge_machdep.c 2002/01/05 22:41:48 1.5
--- arm/footbridge/footbridge_machdep.c 2002/01/30 04:26:03
***************
*** 77,83 ****
for (loop = 0; loop < cleanarea; loop += NBPG) {
pte = pmap_pte(pmap_kernel(), (addr + loop));
! *pte = L2_PTE(DC21285_SA_CACHE_FLUSH_BASE + loop, AP_KR);
}
sa110_cache_clean_addr = addr;
sa110_cache_clean_size = cleanarea / 2;
--- 77,84 ----
for (loop = 0; loop < cleanarea; loop += NBPG) {
pte = pmap_pte(pmap_kernel(), (addr + loop));
! *pte = L2_SPTE(DC21285_SA_CACHE_FLUSH_BASE + loop, AP_KR,
! pte_cache_mode[VM_PROT_READ]);
}
sa110_cache_clean_addr = addr;
sa110_cache_clean_size = cleanarea / 2;
Index: arm/include/arm32/pmap.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/include/arm32/pmap.h,v
retrieving revision 1.20
diff -c -r1.20 pmap.h
*** arm/include/arm32/pmap.h 2002/01/19 16:55:22 1.20
--- arm/include/arm32/pmap.h 2002/01/30 04:26:03
***************
*** 138,147 ****
} pv_addr_t;
/*
! * _KERNEL specific macros, functions and prototypes
*/
! #ifdef _KERNEL
/*
* Commonly referenced structures
--- 138,151 ----
} pv_addr_t;
/*
! * Cache mode for each prot type.
*/
+ extern pt_entry_t pte_cache_mode[8];
+ extern pt_entry_t pte_cache_bits;
! void pmap_pte_protos_init_arm678(void);
! void pmap_pte_protos_init_arm9(void);
! void pmap_pte_protos_init_xscale(void);
/*
* Commonly referenced structures
***************
*** 181,188 ****
*/
boolean_t pmap_pageidlezero __P((paddr_t));
#define PMAP_PAGEIDLEZERO(pa) pmap_pageidlezero((pa))
-
- #endif /* _KERNEL */
/*
* Useful macros and constants
--- 185,190 ----
Index: arm/include/arm32/pte.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/include/arm32/pte.h,v
retrieving revision 1.1
diff -c -r1.1 pte.h
*** arm/include/arm32/pte.h 2001/11/23 17:39:04 1.1
--- arm/include/arm32/pte.h 2002/01/30 04:26:03
***************
*** 74,85 ****
#define PT_C 0x08 /* Phys - Cacheable */
#define PT_U 0x10 /* Phys - Updateable */
- #ifndef _LOCORE
- extern pt_entry_t pte_cache_mode;
-
- #define PT_CACHEABLE (pte_cache_mode)
- #endif
-
/* Page R/M attributes (in pmseg.attrs). */
#define PT_M 0x01 /* Virt - Modified */
#define PT_H 0x02 /* Virt - Handled (Used) */
--- 74,79 ----
***************
*** 107,115 ****
/* PTE construction macros */
#define L2_LPTE(p, a, f) ((p) | PT_AP(a) | L2_LPAGE | (f))
#define L2_SPTE(p, a, f) ((p) | PT_AP(a) | L2_SPAGE | (f))
- #define L2_PTE(p, a) L2_SPTE((p), (a), PT_CACHEABLE)
- #define L2_PTE_NC(p, a) L2_SPTE((p), (a), PT_B)
- #define L2_PTE_NC_NB(p, a) L2_SPTE((p), (a), 0)
#define L1_SECPTE(p, a, f) ((p) | ((a) << AP_SECTION_SHIFT) | (f) \
| L1_SECTION | PT_U)
--- 101,106 ----
Index: arm/mainbus/mainbus_io.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/mainbus/mainbus_io.c,v
retrieving revision 1.6
diff -c -r1.6 mainbus_io.c
*** arm/mainbus/mainbus_io.c 2001/11/23 17:23:42 1.6
--- arm/mainbus/mainbus_io.c 2002/01/30 04:26:04
***************
*** 165,173 ****
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
pte = pmap_pte(pmap_kernel(), va);
if (cacheable)
! *pte |= PT_CACHEABLE;
else
! *pte &= ~PT_CACHEABLE;
}
pmap_update(pmap_kernel());
--- 165,173 ----
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
pte = pmap_pte(pmap_kernel(), va);
if (cacheable)
! *pte |= pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE];
else
! *pte &= ~pte_cache_bits;
}
pmap_update(pmap_kernel());
Index: arm/sa11x0/sa11x0_io.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/sa11x0/sa11x0_io.c,v
retrieving revision 1.5
diff -c -r1.5 sa11x0_io.c
*** arm/sa11x0/sa11x0_io.c 2001/11/23 17:23:42 1.5
--- arm/sa11x0/sa11x0_io.c 2002/01/30 04:26:04
***************
*** 168,176 ****
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
pte = pmap_pte(pmap_kernel(), va);
if (cacheable)
! *pte |= PT_CACHEABLE;
else
! *pte &= ~PT_CACHEABLE;
}
pmap_update(pmap_kernel());
--- 168,176 ----
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
pte = pmap_pte(pmap_kernel(), va);
if (cacheable)
! *pte |= pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE];
else
! *pte &= ~pte_cache_bits;
}
pmap_update(pmap_kernel());
Index: evbarm/integrator/int_bus_dma.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/evbarm/integrator/int_bus_dma.c,v
retrieving revision 1.5
diff -c -r1.5 int_bus_dma.c
*** evbarm/integrator/int_bus_dma.c 2002/01/25 20:57:43 1.5
--- evbarm/integrator/int_bus_dma.c 2002/01/30 04:26:05
***************
*** 350,356 ****
cpu_dcache_wbinv_range(va, NBPG);
cpu_drain_writebuf();
ptep = vtopte(va);
! *ptep = ((*ptep) & (~PT_C | PT_B));
tlb_flush();
}
#ifdef DEBUG_DMA
--- 350,356 ----
cpu_dcache_wbinv_range(va, NBPG);
cpu_drain_writebuf();
ptep = vtopte(va);
! *ptep = *ptep & ~pte_cache_bits;
tlb_flush();
}
#ifdef DEBUG_DMA
Index: evbarm/integrator/integrator_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/evbarm/integrator/integrator_machdep.c,v
retrieving revision 1.8
diff -c -r1.8 integrator_machdep.c
*** evbarm/integrator/integrator_machdep.c 2002/01/30 04:00:47 1.8
--- evbarm/integrator/integrator_machdep.c 2002/01/30 04:26:06
***************
*** 645,662 ****
totalsize = (totalsize + PGOFSET) & ~PGOFSET;
/* logical = map_chunk(l1pagetable, l2pagetable, KERNEL_BASE,
physical_start, KERNEL_TEXT_BASE - KERNEL_BASE,
! AP_KRW, PT_CACHEABLE); */
logical = map_chunk(l1pagetable, l2pagetable,
KERNEL_TEXT_BASE, physical_start, textsize,
! AP_KRW, PT_CACHEABLE);
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_TEXT_BASE + logical, physical_start + logical,
! totalsize - textsize, AP_KRW, PT_CACHEABLE);
#if 0
logical += map_chunk(0, l2pagetable, KERNEL_BASE + logical,
physical_start + logical, kernexec->a_syms + sizeof(int)
+ *(u_int *)((int)end + kernexec->a_syms + sizeof(int)),
! AP_KRW, PT_CACHEABLE);
#endif
}
--- 645,663 ----
totalsize = (totalsize + PGOFSET) & ~PGOFSET;
/* logical = map_chunk(l1pagetable, l2pagetable, KERNEL_BASE,
physical_start, KERNEL_TEXT_BASE - KERNEL_BASE,
! AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]); */
logical = map_chunk(l1pagetable, l2pagetable,
KERNEL_TEXT_BASE, physical_start, textsize,
! AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_TEXT_BASE + logical, physical_start + logical,
! totalsize - textsize, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
#if 0
logical += map_chunk(0, l2pagetable, KERNEL_BASE + logical,
physical_start + logical, kernexec->a_syms + sizeof(int)
+ *(u_int *)((int)end + kernexec->a_syms + sizeof(int)),
! AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
#endif
}
***************
*** 671,683 ****
/* Map the stack pages */
map_chunk(0, l2pagetable, irqstack.pv_va, irqstack.pv_pa,
! IRQ_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, abtstack.pv_va, abtstack.pv_pa,
! ABT_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, undstack.pv_va, undstack.pv_pa,
! UND_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, kernelstack.pv_va, kernelstack.pv_pa,
! UPAGES * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
PD_SIZE, AP_KRW, 0);
--- 672,688 ----
/* Map the stack pages */
map_chunk(0, l2pagetable, irqstack.pv_va, irqstack.pv_pa,
! IRQ_STACK_SIZE * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, abtstack.pv_va, abtstack.pv_pa,
! ABT_STACK_SIZE * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, undstack.pv_va, undstack.pv_pa,
! UND_STACK_SIZE * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, kernelstack.pv_va, kernelstack.pv_pa,
! UPAGES * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
PD_SIZE, AP_KRW, 0);
Index: evbarm/iq80310/iq80310_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/evbarm/iq80310/iq80310_machdep.c,v
retrieving revision 1.18
diff -c -r1.18 iq80310_machdep.c
*** evbarm/iq80310/iq80310_machdep.c 2002/01/30 04:01:36 1.18
--- evbarm/iq80310/iq80310_machdep.c 2002/01/30 04:26:06
***************
*** 612,629 ****
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_BASE + logical,
physical_start + logical, textsize,
! AP_KRW, PT_CACHEABLE);
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_BASE + logical,
physical_start + logical, totalsize - textsize,
! AP_KRW, PT_CACHEABLE);
#if 0 /* XXX No symbols yet. */
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_BASE + logical,
physical_start + logical, kernexec->a_syms + sizeof(int)
+ *(u_int *)((int)end + kernexec->a_syms + sizeof(int)),
! AP_KRW, PT_CACHEABLE);
#endif
}
--- 612,629 ----
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_BASE + logical,
physical_start + logical, textsize,
! AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_BASE + logical,
physical_start + logical, totalsize - textsize,
! AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
#if 0 /* XXX No symbols yet. */
logical += map_chunk(l1pagetable, l2pagetable,
KERNEL_BASE + logical,
physical_start + logical, kernexec->a_syms + sizeof(int)
+ *(u_int *)((int)end + kernexec->a_syms + sizeof(int)),
! AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
#endif
}
***************
*** 633,651 ****
/* Map the stack pages */
map_chunk(0, l2pagetable, irqstack.pv_va, irqstack.pv_pa,
! IRQ_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, abtstack.pv_va, abtstack.pv_pa,
! ABT_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, undstack.pv_va, undstack.pv_pa,
! UND_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, kernelstack.pv_va, kernelstack.pv_pa,
! UPAGES * NBPG, AP_KRW, PT_CACHEABLE);
map_chunk(0, l2pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
PD_SIZE, AP_KRW, 0);
/* Map the Mini-Data cache clean area. */
map_chunk(0, l2pagetable, minidataclean.pv_va, minidataclean.pv_pa,
! NBPG, AP_KRW, PT_CACHEABLE);
/* Map the page table that maps the kernel pages */
map_entry_nc(l2pagetable, kernel_ptpt.pv_pa, kernel_ptpt.pv_pa);
--- 633,655 ----
/* Map the stack pages */
map_chunk(0, l2pagetable, irqstack.pv_va, irqstack.pv_pa,
! IRQ_STACK_SIZE * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, abtstack.pv_va, abtstack.pv_pa,
! ABT_STACK_SIZE * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, undstack.pv_va, undstack.pv_pa,
! UND_STACK_SIZE * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, kernelstack.pv_va, kernelstack.pv_pa,
! UPAGES * NBPG, AP_KRW,
! pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
map_chunk(0, l2pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
PD_SIZE, AP_KRW, 0);
/* Map the Mini-Data cache clean area. */
map_chunk(0, l2pagetable, minidataclean.pv_va, minidataclean.pv_pa,
! NBPG, AP_KRW, pte_cache_mode[VM_PROT_READ|VM_PROT_WRITE]);
/* Map the page table that maps the kernel pages */
map_entry_nc(l2pagetable, kernel_ptpt.pv_pa, kernel_ptpt.pv_pa);
--+Yg8W10oK6rlW0RR--