Put page tables in normal cachable memory on armv7. Check if the MMU walks
authorkettenis <kettenis@openbsd.org>
Sat, 6 Aug 2016 16:46:25 +0000 (16:46 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 6 Aug 2016 16:46:25 +0000 (16:46 +0000)
the page tables coherently and also skip flushing modified ptes out of the
cache in that case.  Speeds up building a kernel with a factor of two on
Cortex-A9 (tested by me) and Cortex-A8 (tested by mglocker@).

ok patrick@

sys/arch/arm/arm/cpufunc_asm_armv7.S
sys/arch/arm/arm/pmap7.c
sys/arch/arm/include/armreg.h

index c9f9fd0..dc48d85 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpufunc_asm_armv7.S,v 1.12 2016/08/05 19:56:52 kettenis Exp $ */
+/* $OpenBSD: cpufunc_asm_armv7.S,v 1.13 2016/08/06 16:46:25 kettenis Exp $ */
 /*
  * Copyright (c) 2008 Dale Rahn <drahn@openbsd.org>
  *
@@ -17,6 +17,7 @@
 
 #include <machine/cpu.h>
 #include <machine/asm.h>
+#include <arm/armreg.h>
 #include <arm/sysreg.h>
 
 ENTRY(armv7_cpu_sleep)
@@ -35,6 +36,9 @@ ENTRY(armv7_periphbase)
        mrc     CP15_CBAR(r0)   
        mov     pc, lr
 
+/* Suitable default for a uniprocessor kernel. */
+#define TTBR_DEFAULT   (TTBR_IRGN_WBNWA | TTBR_RGN_WBNWA)
+
 /*
  * Functions to set the MMU Translation Table Base register
  */
@@ -44,6 +48,7 @@ ENTRY(armv7_setttb)
        dsb     sy
        isb     sy
 
+       orr     r0, r0, #TTBR_DEFAULT
        mcr     CP15_TTBR0(r0)          /* load new TTB */
        mcr     CP15_TLBIALL(r0)        /* invalidate unified TLB */
        dsb     sy
@@ -232,6 +237,7 @@ ENTRY(armv7_context_switch)
        dsb     sy
        isb     sy
 
+       orr     r0, r0, #TTBR_DEFAULT
        mcr     CP15_TTBR0(r0)          /* set the new TTB */
        mcr     CP15_TLBIALL(r0)        /* and flush the unified tlb */
        dsb     sy
index a837ce1..fa0b232 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap7.c,v 1.32 2016/08/03 11:52:43 kettenis Exp $     */
+/*     $OpenBSD: pmap7.c,v 1.33 2016/08/06 16:46:25 kettenis Exp $     */
 /*     $NetBSD: pmap.c,v 1.147 2004/01/18 13:03:50 scw Exp $   */
 
 /*
@@ -3291,7 +3291,7 @@ pmap_pte_init_generic(void)
 void
 pmap_pte_init_armv7(void)
 {
-       uint32_t cachereg;
+       uint32_t id_mmfr3;
 
        /*
         * XXX 
@@ -3305,9 +3305,10 @@ pmap_pte_init_armv7(void)
        pte_l2_l_cache_mode = L2_C|L2_B;
        pte_l2_s_cache_mode = L2_C|L2_B;
 
-       pte_l1_s_cache_mode_pt = L1_S_C;
-       pte_l2_l_cache_mode_pt = L2_C;
-       pte_l2_s_cache_mode_pt = L2_C;
+       pte_l1_s_cache_mode_pt = L1_S_B|L1_S_C;
+       pte_l2_l_cache_mode_pt = L2_B|L2_C;
+       pte_l2_s_cache_mode_pt = L2_B|L2_C;
+       pmap_needs_pte_sync = 1;
 
        pte_l1_s_cache_mask = L1_S_CACHE_MASK_v7;
        pte_l2_l_cache_mask = L2_L_CACHE_MASK_v7;
@@ -3339,26 +3340,10 @@ pmap_pte_init_armv7(void)
        pte_l1_c_proto = L1_C_PROTO_v7;
        pte_l2_s_proto = L2_S_PROTO_v7;
 
-       /* probe L1 dcache */
-       __asm volatile("mcr p15, 2, %0, c0, c0, 0" :: "r" (0) );
-       __asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r" (cachereg) );
-       if ((cachereg & 0x80000000) == 0) {
-#if 0
-               /*
-                * pmap_pte_init_generic() has defaulted to write-through
-                * settings for pte pages, but the cache does not support
-                * write-through.
-                */
-               pmap_needs_pte_sync = 1;
-               pte_l1_s_cache_mode_pt = L1_S_B|L1_S_C;
-               pte_l2_l_cache_mode_pt = L2_B|L2_C;
-               pte_l2_s_cache_mode_pt = L2_B|L2_C;
-#endif
-               /* XXX: Don't cache PTEs, until write-back is fixed. */
-               pte_l1_s_cache_mode_pt = L1_S_V7_TEX(1);
-               pte_l2_l_cache_mode_pt = L2_V7_L_TEX(1);
-               pte_l2_s_cache_mode_pt = L2_V7_S_TEX(1);
-       }
+       /* Check for coherent walk. */
+       __asm volatile("mrc p15, 0, %0, c0, c1, 7" : "=r"(id_mmfr3));
+       if ((id_mmfr3 & 0x00f00000) == 0x00100000)
+               pmap_needs_pte_sync = 0;
 }
 
 uint32_t pmap_alias_dist;
index 1ff70a7..5a4a193 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: armreg.h,v 1.32 2016/07/31 06:24:38 jsg Exp $ */
+/*     $OpenBSD: armreg.h,v 1.33 2016/08/06 16:46:25 kettenis Exp $    */
 /*     $NetBSD: armreg.h,v 1.27 2003/09/06 08:43:02 rearnsha Exp $     */
 
 /*
 #define INSN_COND_MASK         0xf0000000      /* Condition mask */
 #define INSN_COND_AL           0xe0000000      /* Always condition */
 
+/* Translation Table Base Register */
+#define TTBR_C                 (1 << 0)        /* without MPE */
+#define TTBR_S                 (1 << 1)
+#define TTBR_IMP               (1 << 2)
+#define TTBR_RGN_MASK          (3 << 3)
+#define  TTBR_RGN_NC           (0 << 3)
+#define  TTBR_RGN_WBWA         (1 << 3)
+#define  TTBR_RGN_WT           (2 << 3)
+#define  TTBR_RGN_WBNWA                (3 << 3)
+#define TTBR_NOS               (1 << 5)
+#define TTBR_IRGN_MASK         ((1 << 0) | (1 << 6))
+#define  TTBR_IRGN_NC          ((0 << 0) | (0 << 6))
+#define  TTBR_IRGN_WBWA                ((0 << 0) | (1 << 6))
+#define  TTBR_IRGN_WT          ((1 << 0) | (0 << 6))
+#define  TTBR_IRGN_WBNWA       ((1 << 0) | (1 << 6))
+
 #endif