summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2016-08-08 14:47:53 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2016-08-08 14:47:53 +0000
commit84634fdb0689056642bc66d89af73f9fccd8a35b (patch)
tree003465c2ca6b83feeac0f88ca757fc67b6808324 /sys/arch
parent138094adfc427eab4ed40210670248b4b6e8240c (diff)
Mapping non-cachable memory as cachable and subsequently changing the mapping
to non-cachable is retarded. Fix this by introducing PMAP_NOCACHE and PMAP_DEVICE flags that can be or'ed into the physical address passed to pmap_kenter(9), like we have on many of our other architectures. This way we can also properly distinguish between device memory and normal (non-cachable) memory. ok visa@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/arm/arm/pmap7.c48
-rw-r--r--sys/arch/arm/armv7/armv7_space.c23
-rw-r--r--sys/arch/arm/include/pmap.h9
3 files changed, 32 insertions, 48 deletions
diff --git a/sys/arch/arm/arm/pmap7.c b/sys/arch/arm/arm/pmap7.c
index e0631efc365..a283779e482 100644
--- a/sys/arch/arm/arm/pmap7.c
+++ b/sys/arch/arm/arm/pmap7.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap7.c,v 1.34 2016/08/08 09:06:47 kettenis Exp $ */
+/* $OpenBSD: pmap7.c,v 1.35 2016/08/08 14:47:52 kettenis Exp $ */
/* $NetBSD: pmap.c,v 1.147 2004/01/18 13:03:50 scw Exp $ */
/*
@@ -928,33 +928,6 @@ pmap_l2ptp_ctor(void *v)
}
/*
- * Make a pmap_kernel() mapping uncached. Used by bus_dma for coherent pages.
- */
-void
-pmap_uncache_page(paddr_t va, vaddr_t pa)
-{
- struct vm_page *pg;
- struct pv_entry *pv;
- pt_entry_t *pte;
-
- if ((pg = PHYS_TO_VM_PAGE(pa)) != NULL) {
- pv = pmap_find_pv(pg, pmap_kernel(), va);
- if (pv != NULL)
- pv->pv_flags |= PVF_NC; /* XXX ought to be pg attr */
- }
-
- pte = vtopte(va);
- *pte &= ~L2_S_CACHE_MASK;
- *pte |= L2_B; /* device memory */
- PTE_SYNC(pte);
- cpu_tlb_flushD_SE(va);
- cpu_cpwait();
-
- cpu_dcache_wbinv_range(va, PAGE_SIZE);
- cpu_sdcache_wbinv_range(va, pa, PAGE_SIZE);
-}
-
-/*
* Modify pte bits for all ptes corresponding to the given physical address.
* We use `maskbits' rather than `clearbits' because we're always passing
* constants and the latter would require an extra inversion at run-time.
@@ -1514,6 +1487,7 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
{
struct l2_bucket *l2b;
pt_entry_t *ptep, opte, npte;
+ pt_entry_t cache_mode = pte_l2_s_cache_mode;
NPDEBUG(PDB_KENTER,
printf("pmap_kenter_pa: va 0x%08lx, pa 0x%08lx, prot 0x%x\n",
@@ -1528,22 +1502,32 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
if (opte == 0)
l2b->l2b_occupancy++;
- npte = L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) |
- pte_l2_s_cache_mode;
+ if (pa & PMAP_DEVICE)
+ cache_mode = L2_B;
+ else if (pa & PMAP_NOCACHE)
+ cache_mode = L2_V7_S_TEX(1);
+
+ npte = L2_S_PROTO | (pa & PMAP_PA_MASK) |
+ L2_S_PROT(PTE_KERNEL, prot) | cache_mode;
*ptep = npte;
PTE_SYNC(ptep);
if (l2pte_valid(opte)) {
cpu_tlb_flushD_SE(va);
cpu_cpwait();
}
+
+ if (pa & PMAP_NOCACHE) {
+ cpu_dcache_wbinv_range(va, PAGE_SIZE);
+ cpu_sdcache_wbinv_range(va, (pa & PMAP_PA_MASK), PAGE_SIZE);
+ }
}
void
pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable)
{
- pmap_kenter_pa(va, pa, prot);
if (cacheable == 0)
- pmap_uncache_page(va, pa);
+ pa |= PMAP_NOCACHE;
+ pmap_kenter_pa(va, pa, prot);
}
void
diff --git a/sys/arch/arm/armv7/armv7_space.c b/sys/arch/arm/armv7/armv7_space.c
index d61549301da..4f6c1e04e73 100644
--- a/sys/arch/arm/armv7/armv7_space.c
+++ b/sys/arch/arm/armv7/armv7_space.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: armv7_space.c,v 1.7 2016/07/27 21:25:25 patrick Exp $ */
+/* $OpenBSD: armv7_space.c,v 1.8 2016/08/08 14:47:52 kettenis Exp $ */
/*
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@@ -166,11 +166,11 @@ struct bus_space armv7_bs_tag = {
int
armv7_bs_map(void *t, bus_addr_t bpa, bus_size_t size,
- int flag, bus_space_handle_t *bshp)
+ int flags, bus_space_handle_t *bshp)
{
u_long startpa, endpa, pa;
vaddr_t va;
- pt_entry_t *pte;
+ int pmap_flags = PMAP_DEVICE;
startpa = trunc_page(bpa);
endpa = round_page(bpa + size);
@@ -183,18 +183,11 @@ armv7_bs_map(void *t, bus_addr_t bpa, bus_size_t size,
*bshp = (bus_space_handle_t)(va + (bpa - startpa));
- for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
- pmap_kenter_pa(va, pa, PROT_READ | PROT_WRITE);
- if ((flag & BUS_SPACE_MAP_CACHEABLE) == 0) {
- pte = vtopte(va);
- *pte &= ~L2_S_CACHE_MASK;
- *pte |= L2_B;
- PTE_SYNC(pte);
- /* XXX: pmap_kenter_pa() also does PTE_SYNC(). a bit of
- * waste.
- */
- }
- }
+ if (flags & BUS_SPACE_MAP_CACHEABLE)
+ pmap_flags = 0;
+
+ for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
+ pmap_kenter_pa(va, pa | pmap_flags, PROT_READ | PROT_WRITE);
pmap_update(pmap_kernel());
return(0);
diff --git a/sys/arch/arm/include/pmap.h b/sys/arch/arm/include/pmap.h
index b382dc3de8f..393b5484373 100644
--- a/sys/arch/arm/include/pmap.h
+++ b/sys/arch/arm/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.40 2016/03/22 23:35:01 patrick Exp $ */
+/* $OpenBSD: pmap.h,v 1.41 2016/08/08 14:47:52 kettenis Exp $ */
/* $NetBSD: pmap.h,v 1.76 2003/09/06 09:10:46 rearnsha Exp $ */
/*
@@ -181,6 +181,13 @@ struct pmap {
typedef struct pmap *pmap_t;
/*
+ * MD flags that we use for pmap_enter (in the pa):
+ */
+#define PMAP_PA_MASK ~((paddr_t)PAGE_MASK) /* to remove the flags */
+#define PMAP_NOCACHE 0x1 /* non-cacheable memory. */
+#define PMAP_DEVICE 0x2 /* device memory. */
+
+/*
* Physical / virtual address structure. In a number of places (particularly
* during bootstrapping) we need to keep track of the physical and virtual
* addresses of various pages