[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