[PATCH 2/2] bsps/arm: Add support for small pages MMU

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Oct 28 14:29:36 UTC 2019


The small page MMU support reduces the granularity for memory settings
through the MMU from 1MiB sections to 4KiB small pages.

Enable it by default on the realview_pbx_a9_qemu BSP.
---
 bsps/arm/include/bsp/arm-cp15-start.h              | 55 ++++++++++++++---
 .../start/linkcmds.realview_pbx_a9_qemu            |  4 +-
 bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c    | 70 ++++++++++++++++------
 c/src/lib/libbsp/arm/realview-pbx-a9/configure.ac  |  2 +
 4 files changed, 101 insertions(+), 30 deletions(-)

diff --git a/bsps/arm/include/bsp/arm-cp15-start.h b/bsps/arm/include/bsp/arm-cp15-start.h
index a749f7dc98..5e46d54e80 100644
--- a/bsps/arm/include/bsp/arm-cp15-start.h
+++ b/bsps/arm/include/bsp/arm-cp15-start.h
@@ -9,7 +9,7 @@
 
 /*
  * Copyright (c) 2013 Hesham AL-Matary.
- * Copyright (c) 2009-2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2009-2019 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -28,6 +28,7 @@
 #include <libcpu/arm-cp15.h>
 #include <bsp/start.h>
 #include <bsp/linker-symbols.h>
+#include <bspopts.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -106,16 +107,35 @@ arm_cp15_start_set_translation_table_entries(
   const arm_cp15_start_section_config *config
 )
 {
-  uint32_t i = ARM_MMU_SECT_GET_INDEX(config->begin);
-  uint32_t iend =
-    ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
-  uint32_t index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
-
   if (config->begin != config->end) {
+    uint32_t i;
+    uint32_t iend;
+    uint32_t index_mask;
+    uint32_t flags;
+#ifdef ARM_MMU_USE_SMALL_PAGES
+    uint32_t *pt;
+
+    pt = &ttb[ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT];
+    i = ARM_MMU_SMALL_PAGE_GET_INDEX(config->begin);
+    iend = ARM_MMU_SMALL_PAGE_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
+    index_mask = (1U << (32 - ARM_MMU_SMALL_PAGE_BASE_SHIFT)) - 1U;
+    flags = ARM_MMU_SECT_FLAGS_TO_SMALL_PAGE(config->flags);
+
+    while (i != iend) {
+      pt[i] = (i << ARM_MMU_SMALL_PAGE_BASE_SHIFT) | flags;
+      i = (i + 1U) & index_mask;
+    }
+#else
+    i = ARM_MMU_SECT_GET_INDEX(config->begin);
+    iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(config->end));
+    index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
+    flags = config->flags;
+
     while (i != iend) {
-      ttb [i] = (i << ARM_MMU_SECT_BASE_SHIFT) | config->flags;
+      ttb[i] = (i << ARM_MMU_SECT_BASE_SHIFT) | flags;
       i = (i + 1U) & index_mask;
     }
+#endif
   }
 }
 
@@ -127,16 +147,33 @@ arm_cp15_start_setup_translation_table(
   size_t config_count
 )
 {
-  uint32_t dac = ARM_CP15_DAC_DOMAIN(client_domain, ARM_CP15_DAC_CLIENT);
+  uint32_t dac;
+  uint32_t *pt;
   size_t i;
 
+  dac = ARM_CP15_DAC_DOMAIN(client_domain, ARM_CP15_DAC_CLIENT);
   arm_cp15_set_domain_access_control(dac);
   arm_cp15_set_translation_table_base(ttb);
 
   /* Initialize translation table with invalid entries */
+#ifdef ARM_MMU_USE_SMALL_PAGES
+  pt = &ttb[ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT];
+  for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
+    size_t j;
+
+    for (j = 0; j < ARM_MMU_SMALL_PAGE_TABLE_ENTRY_COUNT; ++j) {
+      pt[j] = 0;
+    }
+
+    ttb[i] = (uint32_t) pt | (client_domain << ARM_MMU_SECT_DOMAIN_SHIFT)
+      | ARM_MMU_PAGE_TABLE_DEFAULT;
+    pt += ARM_MMU_SMALL_PAGE_TABLE_ENTRY_COUNT;
+  }
+#else
   for (i = 0; i < ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT; ++i) {
-    ttb [i] = 0;
+    ttb[i] = 0;
   }
+#endif
 
   for (i = 0; i < config_count; ++i) {
     arm_cp15_start_set_translation_table_entries(ttb, &config_table [i]);
diff --git a/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu b/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu
index 00d8bba972..3bf5b4f161 100644
--- a/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu
+++ b/bsps/arm/realview-pbx-a9/start/linkcmds.realview_pbx_a9_qemu
@@ -1,7 +1,7 @@
 MEMORY {
 	/* Waste the first 1MiB for NULL pointer protection */
-	RAM : ORIGIN = 0x00100000, LENGTH = 255M - 16k
-	RAM_MMU : ORIGIN = 0x0fffc000, LENGTH = 16k
+	RAM : ORIGIN = 0x00100000, LENGTH = 0x0fafc000
+	RAM_MMU : ORIGIN = 0x0fbfc000, LENGTH = 0x404000
 }
 
 REGION_ALIAS ("REGION_START", RAM);
diff --git a/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c b/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c
index fae6a6ba79..507277dca1 100644
--- a/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c
+++ b/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2010-2013 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2010-2019 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -14,6 +14,7 @@
 
 #include <rtems.h>
 #include <libcpu/arm-cp15.h>
+#include <bspopts.h>
 
 /*
  * Translation table modification requires to propagate
@@ -35,36 +36,67 @@ static uint32_t set_translation_table_entries(
   uint32_t section_flags
 )
 {
-  uint32_t *ttb = arm_cp15_get_translation_table_base();
-  uint32_t istart = ARM_MMU_SECT_GET_INDEX(begin);
-  uint32_t iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end));
-  uint32_t index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
-  uint32_t ctrl;
+  uint32_t *ttb;
+#ifdef ARM_MMU_USE_SMALL_PAGES
+  uint32_t *pt;
+  uint32_t flags;
+#endif
+  uint32_t istart;
+  uint32_t iend;
+  uint32_t index_mask;
   uint32_t section_flags_of_first_entry;
   uint32_t i;
-  void *first_ttb_addr;
-  void *last_ttb_end;
+  uint32_t *modified_begin;
+  size_t modified_size;
 
-  ctrl = arm_cp15_get_control();
-  section_flags_of_first_entry = ttb [istart];
-  last_ttb_end = first_ttb_addr = ttb + istart;
+  ttb = arm_cp15_get_translation_table_base();
+#ifdef ARM_MMU_USE_SMALL_PAGES
+  pt = &ttb[ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT];
+  istart = ARM_MMU_SMALL_PAGE_GET_INDEX(begin);
+  iend = ARM_MMU_SMALL_PAGE_GET_INDEX(ARM_MMU_SMALL_PAGE_MVA_ALIGN_UP(end));
+  index_mask = (1U << (32 - ARM_MMU_SMALL_PAGE_BASE_SHIFT)) - 1U;
+  section_flags_of_first_entry = ARM_MMU_SMALL_PAGE_FLAGS_TO_SECT(pt[istart])
+    | ARM_MMU_PAGE_TABLE_FLAGS_TO_SECT(ttb[ARM_MMU_SECT_GET_INDEX(begin)]);
+  modified_begin = &pt[istart];
+  flags = ARM_MMU_SECT_FLAGS_TO_SMALL_PAGE(section_flags);
+#else
+  istart = ARM_MMU_SECT_GET_INDEX(begin);
+  iend = ARM_MMU_SECT_GET_INDEX(ARM_MMU_SECT_MVA_ALIGN_UP(end));
+  index_mask = (1U << (32 - ARM_MMU_SECT_BASE_SHIFT)) - 1U;
+  section_flags_of_first_entry = ttb[istart];
+  modified_begin = &ttb[istart];
+#endif
+  modified_size = 0;
 
   for ( i = istart; i != iend; i = (i + 1U) & index_mask ) {
-    uint32_t addr = i << ARM_MMU_SECT_BASE_SHIFT;
+    uint32_t pa;
 
-    ttb [i] = addr | section_flags;
-    last_ttb_end = ttb + i + 1;
+#ifdef ARM_MMU_USE_SMALL_PAGES
+    pa = i << ARM_MMU_SMALL_PAGE_BASE_SHIFT;
+    pt[i] = pa | flags;
+    modified_size += ARM_MMU_SMALL_PAGE_TABLE_ENTRY_SIZE;
+#else
+    pa = i << ARM_MMU_SECT_BASE_SHIFT;
+    ttb[i] = pa | section_flags;
+    modified_size += ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE;
+#endif
   }
 
-  if ( ctrl & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M ) ) {
-    rtems_cache_flush_multiple_data_lines(first_ttb_addr,
-                last_ttb_end - first_ttb_addr);
+  if ((arm_cp15_get_control() & (ARM_CP15_CTRL_C | ARM_CP15_CTRL_M)) != 0) {
+    rtems_cache_flush_multiple_data_lines(modified_begin, modified_size);
   }
 
   _ARM_Data_synchronization_barrier();
 
   for ( i = istart; i != iend; i = (i + 1U) & index_mask ) {
-    void *mva = (void *) (i << ARM_MMU_SECT_BASE_SHIFT);
+    void *mva;
+
+#ifdef ARM_MMU_USE_SMALL_PAGES
+    mva = (void *) (i << ARM_MMU_SMALL_PAGE_BASE_SHIFT);
+#else
+    mva = (void *) (i << ARM_MMU_SECT_BASE_SHIFT);
+#endif
+
 #if defined(__ARM_ARCH_7A__)
     /*
      * Bit 31 needs to be 1 to indicate the register implements the
diff --git a/c/src/lib/libbsp/arm/realview-pbx-a9/configure.ac b/c/src/lib/libbsp/arm/realview-pbx-a9/configure.ac
index 9d0679b59b..0718865a69 100644
--- a/c/src/lib/libbsp/arm/realview-pbx-a9/configure.ac
+++ b/c/src/lib/libbsp/arm/realview-pbx-a9/configure.ac
@@ -43,6 +43,8 @@ RTEMS_BSPOPTS_HELP([CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR],
 [If defined, then do the clock tick processing on the boot processor on behalf
 of all other processors.])
 
+RTEMS_BSPOPTS_SET([ARM_MMU_USE_SMALL_PAGES],[*],[1])
+RTEMS_BSPOPTS_HELP([ARM_MMU_USE_SMALL_PAGES],[use MMU with small pages (4KiB)])
 
 RTEMS_BSP_CLEANUP_OPTIONS
 
-- 
2.16.4



More information about the devel mailing list