[PATCH 4/4] arm: add support for libmm for arm with gumstix bsp

Gedare Bloom gedare at rtems.org
Thu Oct 11 19:10:23 UTC 2012


From: Hesham AL-Matary <heshamelmatary at gmail.com>

---
 c/src/lib/libcpu/arm/Makefile.am                 |   10 +-
 c/src/lib/libcpu/arm/preinstall.am               |    8 +
 c/src/lib/libcpu/arm/shared/arm920/mmu_support.c |  365 ++++++++++++++++++++++
 c/src/lib/libcpu/arm/shared/arm920/mmu_support.h |   95 ++++++
 4 files changed, 476 insertions(+), 2 deletions(-)
 create mode 100644 c/src/lib/libcpu/arm/shared/arm920/mmu_support.c
 create mode 100644 c/src/lib/libcpu/arm/shared/arm920/mmu_support.h

diff --git a/c/src/lib/libcpu/arm/Makefile.am b/c/src/lib/libcpu/arm/Makefile.am
index e488c45..b6f30ec 100644
--- a/c/src/lib/libcpu/arm/Makefile.am
+++ b/c/src/lib/libcpu/arm/Makefile.am
@@ -15,12 +15,18 @@ include_libcpu_HEADERS =
 ## shared/include
 if shared
 
-include_libcpu_HEADERS += shared/include/mmu.h
+include_libcpu_HEADERS += shared/include/mmu.h \
+													../shared/include/memorymanagement.h \
+													shared/arm920/mmu_support.h
 include_libcpu_HEADERS += shared/include/arm-cp15.h
 
 ## shared/arm920
 noinst_PROGRAMS += shared/arm920.rel
-shared_arm920_rel_SOURCES = shared/arm920/mmu.c
+shared_arm920_rel_SOURCES = shared/arm920/mmu.c \
+														shared/arm920/mmu_support.h \
+														shared/arm920/mmu_support.c \
+														../shared/include/memorymanagement.h \
+														../shared/src/memorymanagement_manager.c
 shared_arm920_rel_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/shared/src
 shared_arm920_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
 endif
diff --git a/c/src/lib/libcpu/arm/preinstall.am b/c/src/lib/libcpu/arm/preinstall.am
index 751a085..ecc4509 100644
--- a/c/src/lib/libcpu/arm/preinstall.am
+++ b/c/src/lib/libcpu/arm/preinstall.am
@@ -33,6 +33,14 @@ $(PROJECT_INCLUDE)/libcpu/mmu.h: shared/include/mmu.h $(PROJECT_INCLUDE)/libcpu/
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/mmu.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/mmu.h
 
+$(PROJECT_INCLUDE)/libcpu/memorymanagement.h: ../shared/include/memorymanagement.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/memorymanagement.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/memorymanagement.h
+
+$(PROJECT_INCLUDE)/libcpu/mmu_support.h: shared/arm920/mmu_support.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/mmu_support.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/mmu_support.h
+
 $(PROJECT_INCLUDE)/libcpu/arm-cp15.h: shared/include/arm-cp15.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
diff --git a/c/src/lib/libcpu/arm/shared/arm920/mmu_support.c b/c/src/lib/libcpu/arm/shared/arm920/mmu_support.c
new file mode 100644
index 0000000..00e9049
--- /dev/null
+++ b/c/src/lib/libcpu/arm/shared/arm920/mmu_support.c
@@ -0,0 +1,365 @@
+/* COPYRIGHT (c) 2012. Hesham AL-Matary
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <libcpu/arm-cp15.h>
+#include <rtems/rtems/status.h>
+#include "mmu_support.h"
+#include <libcpu/memorymanagement.h>
+extern uint32_t _ttbl_base;
+
+/*
+ * @brief Deleting MPE and freeing its Control block as well as uninstalling
+ * mpe from HW and uninstall the high-level pointer to cpu_mpe
+ */
+static inline rtems_status_code _CPU_Memory_management_Delete_MPE(rtems_memory_management_entry *mpe)
+{
+  arm_bsp_mm_mpe *arm_mpe;
+  arm_mpe = mpe->cpu_mpe;
+  if ( arm_mpe == NULL )
+    return RTEMS_NO_MEMORY;
+
+  free(arm_mpe);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+/* Changing Page table attributes to new attributes */
+static inline rtems_status_code arm_Region_Change_Attr(
+    arm_bsp_mm_mpe *mpe,
+    uint32_t AP,
+    uint32_t CB
+) {
+  mmu_lvl1_t     *lvl1_pt;
+  int             sectionsNumber; /* 1MB sections */
+  uint32_t        vAddress;
+  int             PTEIndex;
+  uint32_t        paddr;
+  int b,c,i;
+
+  sectionsNumber = mpe->pagesNumber;
+
+  lvl1_pt = (mmu_lvl1_t *) &_ttbl_base;
+  PTEIndex = ((mpe->vAddress & 0xfff00000) >> 20);
+  paddr = (mpe->vAddress & 0xfff00000);
+
+  /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned off */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_DES |
+      MMU_CTRL_I_CACHE_DES |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_DES
+  );
+
+  c = 0;
+  b = 0;
+
+  switch (CB) {
+    case ARM_MMU_cb:
+      c = 0;
+      b = 0;
+      break;
+    case ARM_MMU_cB:
+      c = 0;
+      b = 1;
+      break;
+    case ARM_MMU_WT:
+      c = 1;
+      b = 0;
+      break;
+    case ARM_MMU_WB:
+      c = 1;
+      b = 1;
+      break;
+  }
+
+  /* Return AP/CB for this region to defaults */
+  for ( i = 0; i < sectionsNumber; i++) {
+    uint32_t paddr_base = paddr;
+    paddr_base = (i<<20) + paddr;
+    lvl1_pt[PTEIndex++] = MMU_SET_LVL1_SECT(
+        paddr_base,
+        AP,
+        0,
+        c,
+        b
+    );
+  }
+
+  PTEIndex = ((mpe->vAddress & 0xfff00000) >> 20);
+  uint32_t *PTE_debug = ((uint32_t *) ((mpe->ptAddress) + (mpe->pagesNumber * 4)));
+  printk(" ~~~ Debug : Entered arm_Region_Change_Attr function succesfully and \n\
+      changed the first PTE for region starting at base address %x with assigned \n\
+     pagetable address at address %x is %x ~~~ \n",mpe->vAddress, mpe->ptAddress + (mpe->pagesNumber *4),\
+     lvl1_pt[PTEIndex]);  
+
+  mpe->ap = AP; /* Default when installing entry */
+  mpe->cb = CB; /* Default */
+
+    /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned on */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_EN |
+      MMU_CTRL_I_CACHE_EN |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_EN
+  );
+  return RTEMS_SUCCESSFUL;
+}
+
+/* Verify that size must is multiple of page size */
+inline rtems_status_code _CPU_Memory_management_Verify_size(uint32_t size)
+{
+  if ( (size % MMU_SECT_SIZE) != 0)
+    return RTEMS_INVALID_SIZE;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+/* Verify that size is a multiple of page size */
+inline rtems_status_code _CPU_Memory_management_Initialize(void)
+{
+  mmu_lvl1_t *lvl1_base;
+  int i;
+  uint32_t paddr;
+
+  /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /* set manage mode access for all domains */
+  arm_cp15_set_domain_access_control(0xffffffff);
+
+  lvl1_base = (mmu_lvl1_t *) &_ttbl_base;
+
+  /* set up the trans table */
+  //
+  //mmu_set_map_inval(lvl1_base);
+  arm_cp15_set_translation_table_base(lvl1_base);
+
+  /* fill level 1 pagetable with no protection slots, Cache through attributes
+   * and 1:1 address mapping */
+  paddr = 0x00000000;
+  for (i = 0; i < (0x4000 / 4); i++) {
+    paddr = i; /* i = 1MB page size */
+    lvl1_base[i] = MMU_SET_LVL1_SECT(
+        paddr << 20,
+        ARM_MMU_AP_NOPR,
+        0,
+        1,
+        0
+    );
+  }
+
+  /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned on */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_EN |
+      MMU_CTRL_I_CACHE_EN |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_EN
+  );
+  return RTEMS_SUCCESSFUL;
+}
+
+/* @brief Installing @mpe allocates new arm_bsp_mm_mpe for it
+ * and set its value for then allocate a new lvl2 page table
+ * and activate it */
+rtems_status_code _CPU_Memory_management_Install_MPE(
+  rtems_memory_management_entry *mpe
+) {
+  arm_bsp_mm_mpe *arm_mpe;
+  mmu_lvl1_t     *lvl1_pt;
+  int             sectionsNumber; /* 1MB sections */
+  size_t          size; /* per Byte */
+  uint32_t        vAddress;
+  int             PTEIndex;
+  uint32_t        paddr;
+  uint32_t       *PTE_debug
+  int i;
+  uint32_t        paddr_base;
+
+  lvl1_pt = (mmu_lvl1_t *) &_ttbl_base;
+  PTEIndex = ((((uint32_t)mpe->region.base) & 0xfff00000) >> 20);
+  paddr = ((((uint32_t)mpe->region.base)) & 0xfff00000);
+  size = mpe->region.size;
+
+  arm_mpe = (arm_bsp_mm_mpe *) malloc(sizeof(arm_bsp_mm_mpe));
+
+  if ( arm_mpe == NULL )
+    return RTEMS_NO_MEMORY;
+
+  sectionsNumber = (size / MMU_SECT_SIZE);
+
+  /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned off */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_DES |
+      MMU_CTRL_I_CACHE_DES |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_DES
+  );
+
+  /* Set AP for this region to NO ACCESS */
+
+  for ( i = 0; i < sectionsNumber; i++) {
+    paddr_base = (i<<20) + paddr;
+
+    lvl1_pt[PTEIndex++] = MMU_SET_LVL1_SECT(
+        paddr_base,
+        ARM_MMU_AP_NO_ACCESS,
+        0,
+        1,
+        0
+    );
+  }
+
+  arm_mpe->vAddress = mpe->region.base;
+  /* for level 1 page table ptAddress is the same as ptlvl1Address */
+  arm_mpe->ptAddress = lvl1_pt;
+  arm_mpe->ptlvl1Address = lvl1_pt;
+  arm_mpe->pagesNumber = sectionsNumber;
+  arm_mpe->type = LVL1_PT; /* Default value now */
+  arm_mpe->ap   = ARM_MMU_AP_NO_ACCESS; /* Default when installing entry */
+  arm_mpe->cb   = ARM_MMU_WT; /* Default */
+  /* TODO: Domain may be defined as read only, write.. and any page may
+   * be attached to it */
+  arm_mpe->domain = 0;
+
+  /* install a pointer to high-level API to bsp_mm_mpe */
+  mpe->cpu_mpe = arm_mpe;
+
+  /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned on */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_EN |
+      MMU_CTRL_I_CACHE_EN |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_EN
+  );
+
+  PTEIndex = (arm_mpe->vAddress & 0xfff00000) >> 20;
+#ifdef DEBUG
+  PTE_debug = (uint32_t *)(arm_mpe->ptAddress + arm_mpe->pagesNumber * 4);
+  printk("Installed PTE at base %x with pagetable address %x\n",
+      arm_mpe->vAddress, arm_mpe->ptAddress + (arm_mpe->pagesNumber *4),
+      lvl1_pt[PTEIndex + arm_mpe->pagesNumber - 1]);
+#endif
+  return RTEMS_SUCCESSFUL;
+}
+
+/* @brief Unistalling @mpe from level1 page table and return
+ * access/cache attributes to its defaults. Note that bsp MPE
+ * will still exist even after uninstalling mpe
+ */
+rtems_status_code _CPU_Memory_management_UnInstall_MPE(
+  rtems_memory_management_entry *mpe
+) {
+  arm_bsp_mm_mpe *arm_mpe;
+  mmu_lvl1_t     *lvl1_pt;
+  int             sectionsNumber; /* 1MB sections */
+  size_t          size; /* per Byte */
+  uint32_t        vAddress;
+  int             PTEIndex;
+  uint32_t        paddr;
+
+  arm_mpe = (arm_bsp_mm_mpe *) mpe->cpu_mpe;
+
+  if ( arm_mpe == NULL )
+    return RTEMS_UNSATISFIED;
+
+  sectionsNumber = arm_mpe->pagesNumber;
+
+  lvl1_pt = (mmu_lvl1_t *) &_ttbl_base;
+  PTEIndex = ((((uint32_t)mpe->region.base) & 0xfff00000) >> 20);
+  paddr = (((uint32_t)mpe->region.base) & 0xfff00000);
+
+  /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned off */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_DES |
+      MMU_CTRL_I_CACHE_DES |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_DES
+  );
+
+  /* Return ap/CB for this region to defaults */
+  int i;
+  for ( i = 0; i < sectionsNumber; i++) {
+    uint32_t paddr_base = paddr;
+    paddr_base = (i<<20) + paddr;
+
+    lvl1_pt[PTEIndex++] = MMU_SET_LVL1_SECT(
+        paddr_base,
+        ARM_MMU_AP_NO_ACCESS,
+        0,
+        1,
+        0
+    );
+  }
+
+  arm_mpe->ap   = ARM_MMU_AP_NO_ACCESS; /* Default */
+  arm_mpe->cb   = ARM_MMU_WT; /* Default */
+
+    /* flush the cache and TLB */
+  arm_cp15_cache_invalidate();
+  arm_cp15_tlb_invalidate();
+
+  /*  I & D caches turned on */
+  arm_cp15_set_control(
+      MMU_CTRL_DEFAULT |
+      MMU_CTRL_D_CACHE_EN |
+      MMU_CTRL_I_CACHE_EN |
+      MMU_CTRL_ALIGN_FAULT_EN |
+      MMU_CTRL_LITTLE_ENDIAN |
+      MMU_CTRL_MMU_EN
+  );
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code _CPU_Memory_management_Set_read_only(
+    rtems_memory_management_entry *mpe
+) {
+  arm_bsp_mm_mpe *arm_mpe = (arm_bsp_mm_mpe *)mpe->cpu_mpe;
+  return arm_Region_Change_Attr(arm_mpe, ARM_MMU_AP_USER_READ_ONLY, ARM_MMU_WT);
+}
+
+rtems_status_code _CPU_Memory_management_Set_write(
+    rtems_memory_management_entry *mpe
+) {
+  arm_bsp_mm_mpe *arm_mpe = (arm_bsp_mm_mpe *)mpe->cpu_mpe;
+  return arm_Region_Change_Attr(arm_mpe, ARM_MMU_AP_NOPR, ARM_MMU_WT);
+}
diff --git a/c/src/lib/libcpu/arm/shared/arm920/mmu_support.h b/c/src/lib/libcpu/arm/shared/arm920/mmu_support.h
new file mode 100644
index 0000000..98744e9
--- /dev/null
+++ b/c/src/lib/libcpu/arm/shared/arm920/mmu_support.h
@@ -0,0 +1,95 @@
+/*
+*  COPYRIGHT (c) 2012
+*  On-Line Applications Research Corporation (OAR).
+*
+*  The license and distribution terms for this file may be
+*  found in the file LICENSE in this distribution or at
+*  http://www.rtems.com/license/LICENSE.
+*/
+
+#ifndef __MMU_SUPPORT_H_
+#define __MMU_SUPPORT_H_
+
+#include <stdint.h>
+
+#define MMU_CTRL_MMU_EN             (1 << 0)
+#define MMU_CTRL_MMU_DES            (0 << 0)
+#define MMU_CTRL_ALIGN_FAULT_EN     (1 << 1)
+#define MMU_CTRL_D_CACHE_EN         (1 << 2)
+#define MMU_CTRL_D_CACHE_DES        (0 << 2)
+#define MMU_CTRL_DEFAULT            (0xf << 3)
+#define MMU_CTRL_LITTLE_ENDIAN      (0 << 7)
+#define MMU_CTRL_BIG_ENDIAN         (1 << 7)
+#define MMU_CTRL_SYS_PROT           (1 << 8)
+#define MMU_CTRL_ROM_PROT           (1 << 9)
+#define MMU_CTRL_I_CACHE_EN         (1 << 12)
+#define MMU_CTRL_I_CACHE_DES        (0 << 12)
+#define MMU_CTRL_LOW_VECT           (0 << 13)
+#define MMU_CTRL_HIGH_VECT          (1 << 13)
+
+#define ARM_MMU_AP_NOPR             0x03
+#define ARM_MMU_AP_USER_READ_ONLY   0x02
+#define ARM_MMU_AP_USER_NO_ACCESS   0x01
+#define ARM_MMU_AP_NO_ACCESS        0x00
+
+#define ARM_MMU_cb 0x0 //cache and buffer disabled
+#define ARM_MMU_cB 0x1 // cache disable and buffer enabled
+#define ARM_MMU_WT 0x2 // Write through
+#define ARM_MMU_WB 0x3 // Write Back
+
+/* FAULT ENTRY */
+#define MMU_SET_FAULT (0x0)
+
+/* FIXME: ARM supports various page sizes */
+#define ARM_MMU_PAGE_SIZE  0x1000
+#define MMU_SECT_SIZE      0x100000
+
+/* Set lvl1 PTE to point to the base of a page table mapping
+ * 4K pages
+ */
+#define MMU_SET_LVL1_DIR_4K_PAGES(lvl2_base, dom) \
+           ((((lvl2_base) & 0xfffffc00)) |     \
+           (((dom)&0xf)<<5)                  |     \
+           0x11)
+
+#define MMU_SET_LVL2_PTE_4KB(paddr,ap,c,b) \
+                           (((paddr)&0xfffff000)   | \
+                            ((ap)<<10)      | \
+                            ((ap)<<8)       | \
+                            ((ap)<<6)       | \
+                            ((ap)<<4)       | \
+                            ((c)<<3)        | \
+                            ((b)<<2)        | \
+                            0x2)
+
+#define MMU_SET_LVL1_SECT(addr, ap, dom, ce, be) \
+          ((((addr) & 0xfff00000)) |     \
+           ((ap) << 10)            |     \
+           ((dom) << 5)            |     \
+           ((ce) << 3)             |     \
+           ((be) << 2)             |     \
+           0x12)
+
+/* TODO: Add other page sizes */
+typedef enum { LVL1_PT, LVL2_PT } pt_type;
+
+typedef uint32_t mmu_lvl1_t;
+typedef uint32_t mmu_lvl2_t;
+
+/* This Control Structure applies for most ARM architectures */
+typedef struct{
+uint32_t vAddress;
+/* physical address for page table lvl2 or lvl1 controlling a region */
+uint32_t ptAddress;
+/* physical address for  level 1 page table */
+uint32_t ptlvl1Address;
+/* Number of used PTEs from this page table */
+uint16_t pagesNumber;
+/* lvl2 , lvl1 */
+pt_type  type;
+uint8_t  ap;
+uint8_t  cb;
+uint8_t domain;
+} arm_bsp_mm_mpe;
+
+#endif
-- 
1.7.1




More information about the devel mailing list