[PATCH 4/4] arm: add support for libmm for arm with gumstix bsp
Gedare Bloom
gedare at rtems.org
Fri Oct 12 13:40:35 UTC 2012
I did not get a chance to review this code before, so here is my
initial take. Comments in-line.
On Thu, Oct 11, 2012 at 3:10 PM, Gedare Bloom <gedare at rtems.org> wrote:
> 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
Fix tabs replace with spaces, here and more below.
> 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)
Why is this "static inline"? Also, it appears to be unused.
> +{
> + 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]);
> +
Guard this print with #ifdef DEBUG. I think I did this somewhere else already.
> + 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 */
I think this comment is misplaced.
> +inline rtems_status_code _CPU_Memory_management_Initialize(void)
Should this be inline?
> +{
> + 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 */
What is this TODO saying we should do?
> + 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
> + );
> + }
It seems like this code is mostly copy-pasted, can it be consolidated
into some helper functions?
> +
> + 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;
This probably should be arm920_mm_mpe or something, or the definition
should be provided in a shared arm-bsp header file.
> +
> +#endif
> --
> 1.7.1
>
More information about the devel
mailing list