Module Name: src
Committed By: skrll
Date: Wed Feb 5 07:37:36 UTC 2020
Modified Files:
src/sys/arch/arm/arm: cpufunc.c
src/sys/arch/arm/arm32: armv7_generic_space.c pmap.c
src/sys/arch/arm/conf: Makefile.arm
src/sys/arch/arm/include/arm32: pmap.h
Log Message:
Fix the armv[67] memory attributes for uncached memory. Previously it was
mapped as strongly-ordered which meant that unaligned accesses would fault.
armv7_generic_bs_map now maps pages with PMAP_DEV which is treated as SO
bus_dma continues to use PMAP_NOCACHE as appropriate, but this now get
mapped to the correct memory attribute bits for armv[67]
DEVMAP_ENTRY usees a new flag PTE_DEV.
The workaround for the unaligned access faults is now removed.
XXX Other armv[67] boards bus_space implementations should be checked.
XXX There is scope to reduce the difference to aarch64
To generate a diff of this commit:
cvs rdiff -u -r1.175 -r1.176 src/sys/arch/arm/arm/cpufunc.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/arm32/armv7_generic_space.c
cvs rdiff -u -r1.387 -r1.388 src/sys/arch/arm/arm32/pmap.c
cvs rdiff -u -r1.53 -r1.54 src/sys/arch/arm/conf/Makefile.arm
cvs rdiff -u -r1.160 -r1.161 src/sys/arch/arm/include/arm32/pmap.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/arm/cpufunc.c
diff -u src/sys/arch/arm/arm/cpufunc.c:1.175 src/sys/arch/arm/arm/cpufunc.c:1.176
--- src/sys/arch/arm/arm/cpufunc.c:1.175 Sat Oct 20 06:35:34 2018
+++ src/sys/arch/arm/arm/cpufunc.c Wed Feb 5 07:37:35 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpufunc.c,v 1.175 2018/10/20 06:35:34 skrll Exp $ */
+/* $NetBSD: cpufunc.c,v 1.176 2020/02/05 07:37:35 skrll Exp $ */
/*
* arm7tdmi support code Copyright (c) 2001 John Fremlin
@@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.175 2018/10/20 06:35:34 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.176 2020/02/05 07:37:35 skrll Exp $");
#include "opt_arm_start.h"
#include "opt_compat_netbsd.h"
@@ -1776,7 +1776,7 @@ set_cpufuncs(void)
#ifdef ARM11_CACHE_WRITE_THROUGH
pmap_pte_init_arm11();
#else
- pmap_pte_init_generic();
+ pmap_pte_init_armv6();
#endif
if (arm_cache_prefer_mask)
uvmexp.ncolors = (arm_cache_prefer_mask >> PGSHIFT) + 1;
Index: src/sys/arch/arm/arm32/armv7_generic_space.c
diff -u src/sys/arch/arm/arm32/armv7_generic_space.c:1.10 src/sys/arch/arm/arm32/armv7_generic_space.c:1.11
--- src/sys/arch/arm/arm32/armv7_generic_space.c:1.10 Mon Nov 19 10:45:47 2018
+++ src/sys/arch/arm/arm32/armv7_generic_space.c Wed Feb 5 07:37:35 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: armv7_generic_space.c,v 1.10 2018/11/19 10:45:47 jmcneill Exp $ */
+/* $NetBSD: armv7_generic_space.c,v 1.11 2020/02/05 07:37:35 skrll Exp $ */
/*-
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: armv7_generic_space.c,v 1.10 2018/11/19 10:45:47 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: armv7_generic_space.c,v 1.11 2020/02/05 07:37:35 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -319,7 +319,7 @@ armv7_generic_bs_map(void *t, bus_addr_t
else if (flag & BUS_SPACE_MAP_CACHEABLE)
pmapflags = 0;
else
- pmapflags = PMAP_NOCACHE;
+ pmapflags = PMAP_DEV;
for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags);
Index: src/sys/arch/arm/arm32/pmap.c
diff -u src/sys/arch/arm/arm32/pmap.c:1.387 src/sys/arch/arm/arm32/pmap.c:1.388
--- src/sys/arch/arm/arm32/pmap.c:1.387 Sun Feb 2 08:56:29 2020
+++ src/sys/arch/arm/arm32/pmap.c Wed Feb 5 07:37:35 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.387 2020/02/02 08:56:29 skrll Exp $ */
+/* $NetBSD: pmap.c,v 1.388 2020/02/05 07:37:35 skrll Exp $ */
/*
* Copyright 2003 Wasabi Systems, Inc.
@@ -198,7 +198,7 @@
#endif
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.387 2020/02/02 08:56:29 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.388 2020/02/05 07:37:35 skrll Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -3768,8 +3768,11 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
if (!(flags & PMAP_NOCACHE))
npte |= pte_l2_s_cache_mode_pt;
} else {
- switch (flags & PMAP_CACHE_MASK) {
+ switch (flags & (PMAP_CACHE_MASK | PMAP_DEV_MASK)) {
+ case PMAP_DEV ... PMAP_DEV | PMAP_CACHE_MASK:
+ break;
case PMAP_NOCACHE:
+ npte |= pte_l2_s_nocache_mode;
break;
case PMAP_WRITE_COMBINE:
npte |= pte_l2_s_wc_mode;
@@ -6759,8 +6762,7 @@ pmap_map_section(vaddr_t l1pt, vaddr_t v
switch (cache) {
case PTE_NOCACHE:
- default:
- fl = 0;
+ fl = pte_l1_s_nocache_mode;
break;
case PTE_CACHE:
@@ -6770,6 +6772,11 @@ pmap_map_section(vaddr_t l1pt, vaddr_t v
case PTE_PAGETABLE:
fl = pte_l1_s_cache_mode_pt;
break;
+
+ case PTE_DEV:
+ default:
+ fl = 0;
+ break;
}
const pd_entry_t npde = L1_S_PROTO | pa |
@@ -6795,8 +6802,7 @@ pmap_map_entry(vaddr_t l1pt, vaddr_t va,
switch (cache) {
case PTE_NOCACHE:
- default:
- npte = 0;
+ npte = pte_l2_s_nocache_mode;
break;
case PTE_CACHE:
@@ -6806,6 +6812,10 @@ pmap_map_entry(vaddr_t l1pt, vaddr_t va,
case PTE_PAGETABLE:
npte = pte_l2_s_cache_mode_pt;
break;
+
+ default:
+ npte = 0;
+ break;
}
if ((pdep[l1slot] & L1_TYPE_MASK) != L1_TYPE_C)
@@ -6874,10 +6884,9 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
switch (cache) {
case PTE_NOCACHE:
- default:
- f1 = 0;
- f2l = 0;
- f2s = 0;
+ f1 = pte_l1_s_nocache_mode;
+ f2l = pte_l2_l_nocache_mode;
+ f2s = pte_l2_s_nocache_mode;
break;
case PTE_CACHE:
@@ -6891,6 +6900,13 @@ pmap_map_chunk(vaddr_t l1pt, vaddr_t va,
f2l = pte_l2_l_cache_mode_pt;
f2s = pte_l2_s_cache_mode_pt;
break;
+
+ case PTE_DEV:
+ default:
+ f1 = 0;
+ f2l = 0;
+ f2s = 0;
+ break;
}
size = resid;
@@ -7102,16 +7118,19 @@ pmap_devmap_find_va(vaddr_t va, vsize_t
* them (though, they shouldn't).
*/
+pt_entry_t pte_l1_s_nocache_mode;
pt_entry_t pte_l1_s_cache_mode;
pt_entry_t pte_l1_s_wc_mode;
pt_entry_t pte_l1_s_cache_mode_pt;
pt_entry_t pte_l1_s_cache_mask;
+pt_entry_t pte_l2_l_nocache_mode;
pt_entry_t pte_l2_l_cache_mode;
pt_entry_t pte_l2_l_wc_mode;
pt_entry_t pte_l2_l_cache_mode_pt;
pt_entry_t pte_l2_l_cache_mask;
+pt_entry_t pte_l2_s_nocache_mode;
pt_entry_t pte_l2_s_cache_mode;
pt_entry_t pte_l2_s_wc_mode;
pt_entry_t pte_l2_s_cache_mode_pt;
@@ -7145,14 +7164,17 @@ void
pmap_pte_init_generic(void)
{
+ pte_l1_s_nocache_mode = 0;
pte_l1_s_cache_mode = L1_S_B|L1_S_C;
pte_l1_s_wc_mode = L1_S_B;
pte_l1_s_cache_mask = L1_S_CACHE_MASK_generic;
+ pte_l2_l_nocache_mode = 0;
pte_l2_l_cache_mode = L2_B|L2_C;
pte_l2_l_wc_mode = L2_B;
pte_l2_l_cache_mask = L2_L_CACHE_MASK_generic;
+ pte_l2_s_nocache_mode = 0;
pte_l2_s_cache_mode = L2_B|L2_C;
pte_l2_s_wc_mode = L2_B;
pte_l2_s_cache_mask = L2_S_CACHE_MASK_generic;
@@ -7536,12 +7558,11 @@ pmap_uarea(vaddr_t va)
#if defined(CPU_ARM11MPCORE)
-
void
pmap_pte_init_arm11mpcore(void)
{
- /* cache mode is controlled by 5 bits (B, C, TEX) */
+ /* cache mode is controlled by 5 bits (B, C, TEX[2:0]) */
pte_l1_s_cache_mask = L1_S_CACHE_MASK_armv6;
pte_l2_l_cache_mask = L2_L_CACHE_MASK_armv6;
#if defined(ARM11MPCORE_COMPAT_MMU) || defined(ARMV6_EXTENDED_SMALL_PAGE)
@@ -7620,6 +7641,54 @@ pmap_pte_init_arm11mpcore(void)
#endif /* CPU_ARM11MPCORE */
+#if ARM_MMU_V6 == 1
+void
+pmap_pte_init_armv6(void)
+{
+ /*
+ * The ARMv6-A MMU is mostly compatible with generic. If the
+ * AP field is zero, that now means "no access" rather than
+ * read-only. The prototypes are a little different because of
+ * the XN bit.
+ */
+ pmap_pte_init_generic();
+
+ pte_l1_s_nocache_mode = L1_S_XS_TEX(1);
+ pte_l2_l_nocache_mode = L2_XS_L_TEX(1);
+ pte_l2_s_nocache_mode = L2_XS_T_TEX(1);
+
+#ifdef ARM11_COMPAT_MMU
+ /* with AP[0..3] */
+ pte_l1_ss_proto = L1_SS_PROTO_armv6;
+#else
+ pte_l1_s_cache_mask = L1_S_CACHE_MASK_armv6n;
+ pte_l2_l_cache_mask = L2_L_CACHE_MASK_armv6n;
+ pte_l2_s_cache_mask = L2_S_CACHE_MASK_armv6n;
+
+ pte_l1_ss_proto = L1_SS_PROTO_armv6;
+ pte_l1_s_proto = L1_S_PROTO_armv6;
+ pte_l1_c_proto = L1_C_PROTO_armv6;
+ pte_l2_s_proto = L2_S_PROTO_armv6n;
+
+ pte_l1_s_prot_u = L1_S_PROT_U_armv6;
+ pte_l1_s_prot_w = L1_S_PROT_W_armv6;
+ pte_l1_s_prot_ro = L1_S_PROT_RO_armv6;
+ pte_l1_s_prot_mask = L1_S_PROT_MASK_armv6;
+
+ pte_l2_l_prot_u = L2_L_PROT_U_armv6n;
+ pte_l2_l_prot_w = L2_L_PROT_W_armv6n;
+ pte_l2_l_prot_ro = L2_L_PROT_RO_armv6n;
+ pte_l2_l_prot_mask = L2_L_PROT_MASK_armv6n;
+
+ pte_l2_s_prot_u = L2_S_PROT_U_armv6n;
+ pte_l2_s_prot_w = L2_S_PROT_W_armv6n;
+ pte_l2_s_prot_ro = L2_S_PROT_RO_armv6n;
+ pte_l2_s_prot_mask = L2_S_PROT_MASK_armv6n;
+
+#endif
+}
+#endif /* ARM_MMU_V6 */
+
#if ARM_MMU_V7 == 1
void
pmap_pte_init_armv7(void)
@@ -7634,6 +7703,10 @@ pmap_pte_init_armv7(void)
pmap_needs_pte_sync = 1;
+ pte_l1_s_nocache_mode = L1_S_XS_TEX(1);
+ pte_l2_l_nocache_mode = L2_XS_L_TEX(1);
+ pte_l2_s_nocache_mode = L2_XS_T_TEX(1);
+
pte_l1_s_cache_mask = L1_S_CACHE_MASK_armv7;
pte_l2_l_cache_mask = L2_L_CACHE_MASK_armv7;
pte_l2_s_cache_mask = L2_S_CACHE_MASK_armv7;
@@ -7785,22 +7858,28 @@ pmap_dump(pmap_t pm)
ch = '.';
} else {
occ--;
- switch (pte & 0x0c) {
+ switch (pte & 0x4c) {
case 0x00:
- ch = 'D'; /* No cache No buff */
+ ch = 'N'; /* No cache No buff */
break;
case 0x04:
ch = 'B'; /* No cache buff */
break;
case 0x08:
- if (pte & 0x40)
- ch = 'm';
- else
- ch = 'C'; /* Cache No buff */
+ ch = 'C'; /* Cache No buff */
break;
case 0x0c:
ch = 'F'; /* Cache Buff */
break;
+ case 0x40:
+ ch = 'D';
+ break;
+ case 0x48:
+ ch = 'm'; /* Xscale mini-data */
+ break;
+ default:
+ ch = '?';
+ break;
}
if ((pte & L2_S_PROT_U) == L2_S_PROT_U)
Index: src/sys/arch/arm/conf/Makefile.arm
diff -u src/sys/arch/arm/conf/Makefile.arm:1.53 src/sys/arch/arm/conf/Makefile.arm:1.54
--- src/sys/arch/arm/conf/Makefile.arm:1.53 Mon Jan 6 07:40:45 2020
+++ src/sys/arch/arm/conf/Makefile.arm Wed Feb 5 07:37:36 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.arm,v 1.53 2020/01/06 07:40:45 skrll Exp $
+# $NetBSD: Makefile.arm,v 1.54 2020/02/05 07:37:36 skrll Exp $
# Makefile for NetBSD
#
@@ -56,26 +56,6 @@ CPPFLAGS.cpufunc_asm_armv6.S+= -mcpu=arm
CPPFLAGS.cpufunc_asm_arm11.S+= -mcpu=arm1136j-s
CPPFLAGS.cpufunc_asm_xscale.S+= -mcpu=xscale
-.if !empty(MACHINE_ARCH:Mearmv6*) || !empty(MACHINE_ARCH:Mearmv7*)
-# XXX
-#
-# Workaround for alignment faults on ARMv6+, at least occur with
-# axe(4) and athn(4) drivers.
-#
-# For ARMv6+, unaligned access is enabled by default. However, it
-# cannot be used for non-cacheable memory, which is used as DMA
-# buffers. This results in alignment faults above. A real fix is
-# to use cacheable memory as DMA buffers. However, it breaks some
-# drivers, awge(4) and vchiq(4) at least.
-#
-# Until we figure out problems and fix them, we choose a fail-safe
-# workaround here; forbid unaligned memory access for whole kernel.
-# Affects on performance is negligibly small as far as we can see.
-#
-# See PR kern/54486 for more details.
-CFLAGS+= -mno-unaligned-access
-.endif
-
OPT_DDB= %DDB%
.if !empty(OPT_DDB) && ${HAVE_GCC:U0} > 0
CFLAGS+= -mapcs-frame
Index: src/sys/arch/arm/include/arm32/pmap.h
diff -u src/sys/arch/arm/include/arm32/pmap.h:1.160 src/sys/arch/arm/include/arm32/pmap.h:1.161
--- src/sys/arch/arm/include/arm32/pmap.h:1.160 Mon Jan 20 22:13:58 2020
+++ src/sys/arch/arm/include/arm32/pmap.h Wed Feb 5 07:37:36 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.160 2020/01/20 22:13:58 skrll Exp $ */
+/* $NetBSD: pmap.h,v 1.161 2020/02/05 07:37:36 skrll Exp $ */
/*
* Copyright (c) 2002, 2003 Wasabi Systems, Inc.
@@ -221,7 +221,7 @@ struct pmap_devmap {
.pd_pa = DEVMAP_ALIGN(pa), \
.pd_size = DEVMAP_SIZE(sz), \
.pd_prot = VM_PROT_READ|VM_PROT_WRITE, \
- .pd_cache = PTE_NOCACHE \
+ .pd_cache = PTE_DEV \
}
#define DEVMAP_ENTRY_END { 0 }
@@ -302,6 +302,7 @@ extern bool arm_has_tlbiasid_p; /* also
#define PTE_NOCACHE 0
#define PTE_CACHE 1
#define PTE_PAGETABLE 2
+#define PTE_DEV 3
/*
* Flags that indicate attributes of pages or mappings of pages.
@@ -366,6 +367,9 @@ u_int arm32_mmap_flags(paddr_t);
#define pmap_mmap_flags(ppn) arm32_mmap_flags(ppn)
#define PMAP_PTE 0x10000000 /* kenter_pa */
+#define PMAP_DEV 0x20000000 /* kenter_pa */
+#define PMAP_DEV_SO 0x40000000 /* kenter_pa */
+#define PMAP_DEV_MASK (PMAP_DEV | PMAP_DEV_SO)
/*
* Functions that we need to export
@@ -662,6 +666,9 @@ void pmap_pte_init_arm11(void);
#if defined(CPU_ARM11MPCORE) /* ARM_MMU_V6 */
void pmap_pte_init_arm11mpcore(void);
#endif
+#if ARM_MMU_V6 == 1
+void pmap_pte_init_armv6(void);
+#endif /* ARM_MMU_V6 */
#if ARM_MMU_V7 == 1
void pmap_pte_init_armv7(void);
#endif /* ARM_MMU_V7 */
@@ -683,14 +690,13 @@ void xscale_setup_minidata(vaddr_t, vadd
void pmap_uarea(vaddr_t);
#endif /* ARM_MMU_XSCALE == 1 */
-extern pt_entry_t pte_l1_s_cache_mode;
-extern pt_entry_t pte_l1_s_cache_mask;
+extern pt_entry_t pte_l1_s_nocache_mode;
+extern pt_entry_t pte_l2_l_nocache_mode;
+extern pt_entry_t pte_l2_s_nocache_mode;
+extern pt_entry_t pte_l1_s_cache_mode;
extern pt_entry_t pte_l2_l_cache_mode;
-extern pt_entry_t pte_l2_l_cache_mask;
-
extern pt_entry_t pte_l2_s_cache_mode;
-extern pt_entry_t pte_l2_s_cache_mask;
extern pt_entry_t pte_l1_s_cache_mode_pt;
extern pt_entry_t pte_l2_l_cache_mode_pt;
@@ -700,6 +706,10 @@ extern pt_entry_t pte_l1_s_wc_mode;
extern pt_entry_t pte_l2_l_wc_mode;
extern pt_entry_t pte_l2_s_wc_mode;
+extern pt_entry_t pte_l1_s_cache_mask;
+extern pt_entry_t pte_l2_l_cache_mask;
+extern pt_entry_t pte_l2_s_cache_mask;
+
extern pt_entry_t pte_l1_s_prot_u;
extern pt_entry_t pte_l1_s_prot_w;
extern pt_entry_t pte_l1_s_prot_ro;