From e2bd3b65536e140fd1432ff6eb959ca304691d79 Mon Sep 17 00:00:00 2001 From: kettenis Date: Mon, 8 Aug 2016 14:47:52 +0000 Subject: [PATCH] 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@ --- sys/arch/arm/arm/pmap7.c | 48 +++++++++++--------------------- sys/arch/arm/armv7/armv7_space.c | 23 ++++++--------- sys/arch/arm/include/pmap.h | 9 +++++- 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 $ */ /* @@ -927,33 +927,6 @@ pmap_l2ptp_ctor(void *v) PTE_SYNC_RANGE(v, L2_TABLE_SIZE_REAL / sizeof(pt_entry_t)); } -/* - * 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 @@ -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 $ */ /* @@ -180,6 +180,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 -- 2.20.1