[PATCH 1/4] libmm: new library for memory management hardware
Gedare Bloom
gedare at rtems.org
Thu Oct 11 19:10:20 UTC 2012
From: Hesham AL-Matary <heshamelmatary at gmail.com>
---
c/src/lib/libcpu/Makefile.am | 1 +
c/src/lib/libcpu/shared/include/memorymanagement.h | 51 +++++
.../libcpu/shared/src/memorymanagement_manager.c | 72 +++++++
c/src/lib/libcpu/shared/src/no_memorymanagement.c | 51 +++++
cpukit/Makefile.am | 4 +
cpukit/configure.ac | 1 +
cpukit/libmm/Makefile.am | 7 +
cpukit/libmm/libmm.c | 200 ++++++++++++++++++++
cpukit/libmm/libmm.h | 137 +++++++++++++
cpukit/preinstall.am | 4 +
cpukit/sapi/include/confdefs.h | 10 +
cpukit/wrapup/Makefile.am | 1 +
12 files changed, 539 insertions(+), 0 deletions(-)
create mode 100644 c/src/lib/libcpu/shared/include/memorymanagement.h
create mode 100644 c/src/lib/libcpu/shared/src/memorymanagement_manager.c
create mode 100644 c/src/lib/libcpu/shared/src/no_memorymanagement.c
create mode 100644 cpukit/libmm/Makefile.am
create mode 100644 cpukit/libmm/libmm.c
create mode 100644 cpukit/libmm/libmm.h
diff --git a/c/src/lib/libcpu/Makefile.am b/c/src/lib/libcpu/Makefile.am
index 7d3a43e..53e1146 100644
--- a/c/src/lib/libcpu/Makefile.am
+++ b/c/src/lib/libcpu/Makefile.am
@@ -4,6 +4,7 @@ EXTRA_DIST =
EXTRA_DIST += shared/include/cache.h
EXTRA_DIST += shared/src/cache_aligned_malloc.c
EXTRA_DIST += shared/src/cache_manager.c
+EXTRA_DIST += shared/src/memorymanagement_manager.c
SUBDIRS = @libcpu_cpu_subdir@
DIST_SUBDIRS = @libcpu_cpu_subdir@
diff --git a/c/src/lib/libcpu/shared/include/memorymanagement.h b/c/src/lib/libcpu/shared/include/memorymanagement.h
new file mode 100644
index 0000000..028379f
--- /dev/null
+++ b/c/src/lib/libcpu/shared/include/memorymanagement.h
@@ -0,0 +1,51 @@
+/*
+ * libcpu memory management (libmm) support
+ *
+ * Copyright (c) 2012. Gedare Bloom.
+ *
+ * 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 __LIBCPU_MEMORYMANAGEMENT_h
+#define __LIBCPU_MEMORYMANAGEMENT_h
+
+#include <sys/types.h>
+#include <rtems/rtems/status.h>
+#include <rtems/libmm.h>
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+ * Initialize the hardware to prepare for memory protection directives.
+ */
+rtems_status_code _CPU_Memory_management_Initialize(void);
+
+/*
+ * Install (enforce) the memory protection entry @a mpe
+ */
+rtems_status_code _CPU_Memory_management_Install_MPE(
+ rtems_memory_management_entry *mpe
+);
+
+/*
+ * Check if memory protection region @a size is valid for this CPU
+ */
+rtems_status_code _CPU_Memory_management_Verify_size(
+ size_t size
+);
+
+rtems_status_code _CPU_Memory_management_Set_read_only(
+ rtems_memory_management_entry *mpe
+);
+
+rtems_status_code _CPU_Memory_management_Set_write(
+ rtems_memory_management_entry *mpe
+);
+
+#ifdef __cplusplus
+ }
+#endif
+#endif
diff --git a/c/src/lib/libcpu/shared/src/memorymanagement_manager.c b/c/src/lib/libcpu/shared/src/memorymanagement_manager.c
new file mode 100644
index 0000000..ecd8234
--- /dev/null
+++ b/c/src/lib/libcpu/shared/src/memorymanagement_manager.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012. Gedare Bloom.
+ *
+ * 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 <rtems.h>
+#include <sys/types.h>
+#include <rtems/rtems/status.h>
+#include <libcpu/memorymanagement.h>
+
+/**
+ * @brief initialization of the ALUT (Access Look up Table )
+ */
+rtems_status_code rtems_memory_management_initialize(void)
+{
+ return _CPU_Memory_management_Initialize();
+}
+
+/**
+ * @brief Install the memory protection entry to the enforcement mechanism.
+ */
+rtems_status_code rtems_memory_management_install_entry(
+ rtems_memory_management_entry *mpe
+) {
+ rtems_status_code status;
+ ISR_Level level;
+ _ISR_Disable( level );
+ status = _CPU_Memory_management_Install_MPE(mpe);
+ if ( status == RTEMS_SUCCESSFUL ) {
+ mpe->installed = true;
+ }
+ _ISR_Enable( level );
+ return status;
+}
+
+rtems_status_code rtems_memory_management_verify_size(
+ size_t size
+) {
+ rtems_status_code status;
+ ISR_Level level;
+ _ISR_Disable( level );
+ status = _CPU_Memory_management_Verify_size(size);
+ _ISR_Enable( level );
+ return status;
+}
+
+rtems_status_code rtems_memory_management_set_write
+(
+ rtems_memory_management_entry* const mpe
+){
+ rtems_status_code status;
+ ISR_Level level;
+ _ISR_Disable( level );
+ status = _CPU_Memory_management_Set_write(mpe);
+ _ISR_Enable( level );
+ return status;
+}
+
+rtems_status_code rtems_memory_management_set_read_only
+(
+ rtems_memory_management_entry* const mpe
+){
+ rtems_status_code status;
+ ISR_Level level;
+ _ISR_Disable( level );
+ status = _CPU_Memory_management_Set_read_only(mpe);
+ _ISR_Enable( level );
+ return status;
+}
diff --git a/c/src/lib/libcpu/shared/src/no_memorymanagement.c b/c/src/lib/libcpu/shared/src/no_memorymanagement.c
new file mode 100644
index 0000000..84e68d8
--- /dev/null
+++ b/c/src/lib/libcpu/shared/src/no_memorymanagement.c
@@ -0,0 +1,51 @@
+/*
+ * Stubs for memory management
+ *
+ * Copyright (c) 2012. Gedare Bloom.
+ * 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 <rtems.h>
+#include <sys/types.h>
+#include <rtems/rtems/status.h>
+
+/*
+ * Initialize the hardware to prepare for memory protection directives.
+ */
+rtems_status_code _CPU_Memory_management_Initialize(void)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Install (enforce) the memory protection entry @a mpe
+ */
+rtems_status_code _CPU_Memory_management_Install_MPE(
+ rtems_memory_management_entry *mpe
+){
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Check if memory protection region @a size is valid for this CPU
+ */
+rtems_status_code _CPU_Memory_management_Verify_size(
+ size_t size
+){
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code _CPU_Memory_management_Set_read_only(
+ rtems_memory_management_entry *mpe
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code _CPU_Memory_management_Set_write(
+ rtems_memory_management_entry *mpe
+){
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index b5569fa..8dfdb3b 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -10,6 +10,7 @@ SUBDIRS += libnetworking librpc
SUBDIRS += libi2c
SUBDIRS += libmisc
SUBDIRS += libmd
+SUBDIRS += libmm
SUBDIRS += libgnat
SUBDIRS += wrapup
@@ -157,6 +158,9 @@ include_rtems_HEADERS += libmisc/monitor/monitor.h
include_rtems_HEADERS += libmisc/fb/fb.h
include_rtems_HEADERS += libmisc/fb/mw_uid.h
+## mm
+include_rtems_HEADERS += libmm/libmm.h
+
## mouse
include_rtems_HEADERS += libmisc/mouse/mouse_parser.h
include_rtems_HEADERS += libmisc/mouse/serial_mouse.h
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index b97036c..da2c44b 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -379,6 +379,7 @@ librpc/Makefile
libmisc/Makefile
libi2c/Makefile
libmd/Makefile
+libmm/Makefile
zlib/Makefile
ftpd/Makefile
telnetd/Makefile
diff --git a/cpukit/libmm/Makefile.am b/cpukit/libmm/Makefile.am
new file mode 100644
index 0000000..c19b939
--- /dev/null
+++ b/cpukit/libmm/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/automake/compile.am
+
+noinst_LIBRARIES = libmm.a
+
+libmm_a_SOURCES = libmm.c libmm.h
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libmm/libmm.c b/cpukit/libmm/libmm.c
new file mode 100644
index 0000000..c41f860
--- /dev/null
+++ b/cpukit/libmm/libmm.c
@@ -0,0 +1,200 @@
+/*
+ * @file libmm.c
+ *
+ * @ingroup libmm
+ *
+ * @brief libmm API uses MPU/MMU units to provide memory management.
+ */
+
+/* Copyright (c) 2012. Gedare Bloom.
+ *
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/thread.h>
+#include <rtems/error.h>
+#include <rtems/rtems/cache.h>
+#include "libmm.h"
+
+extern uint32_t libmm_alut_size;
+
+static rtems_memory_management_alut the_rtems_memory_management_alut;
+
+rtems_status_code rtems_memory_management_install_alut(void) {
+ rtems_memory_management_alut* the_alut= &the_rtems_memory_management_alut;
+
+ the_alut->entries = (rtems_memory_management_entry *)
+ malloc(sizeof(rtems_memory_management_entry) * libmm_alut_size);
+ _Chain_Initialize(
+ &(the_alut->ALUT_idle),
+ the_alut->entries,
+ libmm_alut_size,
+ sizeof(rtems_memory_management_entry)
+ );
+
+ if( the_alut->entries == NULL)
+ return RTEMS_NO_MEMORY;
+
+ _Chain_Initialize_empty(&(the_alut->ALUT_mappings));
+
+ int i;
+ for( i = 0; i < libmm_alut_size; i++)
+ {
+ the_alut->entries[i].region.size = 0;
+ the_alut->entries[i].region.base = (void*)0;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_memory_management_find_entry(
+ void* const addr,
+ rtems_memory_management_entry** p_ret)
+{
+ rtems_memory_management_alut* alut_p;
+ rtems_memory_management_entry* current;
+ alut_p = &the_rtems_memory_management_alut;
+
+ if( p_ret == 0 )
+ return RTEMS_INVALID_ADDRESS;
+
+ current = (rtems_memory_management_entry*)rtems_chain_first(
+ &alut_p->ALUT_mappings
+ );
+ while ( ! rtems_chain_is_tail( &alut_p->ALUT_mappings, ¤t->node ) ) {
+ if ( current->region.base <= addr &&
+ current->region.base + current->region.size > addr ) {
+ *p_ret = current;
+ return RTEMS_SUCCESSFUL;
+ }
+ current = (rtems_memory_management_entry*)rtems_chain_next(¤t->node);
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+rtems_status_code rtems_memory_management_create_entry(
+ rtems_memory_management_region_descriptor region,
+ rtems_memory_management_entry** p_ret)
+{
+ rtems_memory_management_entry* current;
+ rtems_memory_management_alut* alut_p;
+ rtems_status_code status;
+ alut_p = &the_rtems_memory_management_alut;
+
+ /* Check for invalid block size */
+ status = rtems_memory_management_verify_size(region.size);
+ if( status != RTEMS_SUCCESSFUL )
+ return RTEMS_INVALID_NUMBER;
+
+ _Thread_Disable_dispatch();
+ /* Check for address map overlaps */
+ current = (rtems_memory_management_entry*)rtems_chain_first(
+ &alut_p->ALUT_mappings
+ );
+ while( ! rtems_chain_is_tail( &alut_p->ALUT_mappings, ¤t->node ) ) {
+ if( !( current->region.base >= region.base + region.size ||
+ current->region.base + current->region.size <= region.base ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ADDRESS;
+ }
+ current = (rtems_memory_management_entry*)rtems_chain_next(¤t->node);
+ }
+
+ /* Check for ALUT full condition and get a valid empty entry */
+ if ( rtems_chain_is_empty(&alut_p->ALUT_idle) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+ current = (rtems_memory_management_entry*)rtems_chain_get_unprotected(
+ &(alut_p->ALUT_idle)
+ );
+
+ /* Append entry to the ALUT */
+ current->region.base = region.base;
+ current->region.size = region.size;
+ rtems_chain_append_unprotected(&alut_p->ALUT_mappings, ¤t->node);
+
+ /* for the new entry block, the attribute may be different from before
+ * so update the related cache tlb and pagetable entry */
+
+ _Thread_Enable_dispatch();
+
+ *p_ret = current;
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_memory_management_delete_entry(
+ rtems_memory_management_entry* const mpe)
+{
+ rtems_memory_management_alut *alut_p;
+ rtems_memory_management_entry *current;
+ alut_p = &the_rtems_memory_management_alut;
+
+ _Thread_Disable_dispatch();
+ if( mpe < alut_p->entries || mpe > alut_p->entries + sizeof(alut_p->entries))
+ return RTEMS_INVALID_ADDRESS;
+
+ /* make sure the mpe point to a mapped entry */
+ current = (rtems_memory_management_entry*)rtems_chain_first(
+ &alut_p->ALUT_mappings
+ );
+ while ( !rtems_chain_is_tail(&alut_p->ALUT_mappings, ¤t->node) ) {
+ if( rtems_chain_are_nodes_equal(¤t->node, &mpe->node) ){
+ rtems_chain_extract_unprotected(&mpe->node );
+
+ /* for the delete entry block, the attribute should become default
+ * so update the related cache tlb and pagetable entry*/
+
+ mpe->region.size = 0;
+ mpe->region.base = 0;
+ rtems_chain_append_unprotected(&alut_p->ALUT_idle, ¤t->node);
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ } else {
+ current = (rtems_memory_management_entry*)rtems_chain_next(
+ ¤t->node
+ );
+ }
+ }
+
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ADDRESS;
+}
+
+rtems_status_code rtems_memory_management_get_size(
+ rtems_memory_management_entry* const mpe,
+ size_t * size)
+{
+ rtems_memory_management_alut* alut_p;
+ alut_p = &the_rtems_memory_management_alut;
+
+ if( mpe < alut_p->entries || mpe > alut_p->entries + sizeof(alut_p->entries))
+ return RTEMS_INVALID_ADDRESS;
+
+ _Thread_Disable_dispatch();
+ if( 0 == mpe->region.size ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ *size = mpe->region.size;
+ _Thread_Enable_dispatch();
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmm/libmm.h b/cpukit/libmm/libmm.h
new file mode 100644
index 0000000..6d4f885
--- /dev/null
+++ b/cpukit/libmm/libmm.h
@@ -0,0 +1,137 @@
+/*
+ * @file libmm.h
+ *
+ * @ingroup libmm
+ *
+ * @brief libmm API make use of MPU/MMU units to provide
+ * memory management
+ */
+
+/*
+ * Copyright (c) 2011. Gedare Bloom.
+ *
+ * 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 _RTEMS_LIBMM_H
+#define _RTEMS_LIBMM_H
+
+#include <inttypes.h>
+#include <rtems/rtems/status.h>
+#include <rtems/chain.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * Define incomplete pointer to point to
+ * bsp_mm_mpe defined at CPU code, the address
+ * is installed at CPU code when Installing an mpe
+ */
+typedef rtems_bsp_mm_mpe;
+
+/*
+ * @brief A region of contiguous memory
+ */
+typedef struct
+{
+ char *name;
+ void *base;
+ size_t size;
+} rtems_memory_management_region_descriptor;
+
+typedef struct
+{
+ rtems_chain_node node;
+ rtems_memory_management_region_descriptor region;
+ bool installed;
+ rtems_bsp_mm_mpe *cpu_mpe;
+} rtems_memory_management_entry;
+
+/**
+ * @brief for now, the ALUT is just an array, we can optimize this by some
+ * kind of advanced data structure, such as hash table, or chain maybe
+ */
+typedef struct
+{
+ rtems_memory_management_entry *entries;
+ rtems_chain_control ALUT_mappings;
+ rtems_chain_control ALUT_idle;
+} rtems_memory_management_alut;
+
+/**
+ * @brief Initializing memory management unit and necessary actions depending
+ * on the target. This function calls corresponding _CPU_Memory_management_xxx
+ * at BSP code to enforce HW initialization. Implemented in libcpu/shared/
+ */
+rtems_status_code rtems_memory_management_initialize ( void );
+
+/**
+ * @brief creating a high-level entry for mpe
+ * the functions returns a pointer to the new allocated
+ * mpe at @a p_ret
+ */
+rtems_status_code rtems_memory_management_create_entry(
+ rtems_memory_management_region_descriptor region,
+ rtems_memory_management_entry** p_ret
+);
+
+/**
+ * @brief rtems_memory_management_install_entry
+ * Calls _CPU_Memory_management_Install_MPE to enforce the permissions
+ * on @a mpe. Implemented in libcpu/shared/
+ */
+rtems_status_code rtems_memory_management_install_entry(
+ rtems_memory_management_entry *mpe
+);
+
+/**
+ * @brief deleting entry from ALUT as well as HW entries
+ */
+rtems_status_code rtems_memory_management_delete_entry(
+ rtems_memory_management_entry* const p_entry
+);
+
+/**
+ * @brief Linear search for the element emtry in the alut for
+ * the address range under which it falls
+ */
+rtems_status_code rtems_memory_management_find_entry(
+ void* const addr,
+ rtems_memory_management_entry** p_ret
+);
+
+rtems_status_code rtems_memory_management_verify_size(
+ size_t size
+);
+
+/**
+ * @brief check if size is supported by the CPU.
+ * this method is implemented at CPU code*/
+rtems_status_code rtems_memory_management_get_size(
+ rtems_memory_management_entry* const p_entry,
+ size_t * size
+);
+
+/**
+ * @brief set HW write AP for that mpe
+ */
+rtems_status_code rtems_memory_management_set_write
+(
+ rtems_memory_management_entry* const mpe;
+);
+
+/**
+ * @brief set HW Read Only AP for that mpe
+ */
+rtems_status_code rtems_memory_management_set_read_only
+(
+ rtems_memory_management_entry* const mpe;
+);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am
index f6d24bb..7069467 100644
--- a/cpukit/preinstall.am
+++ b/cpukit/preinstall.am
@@ -329,6 +329,10 @@ $(PROJECT_INCLUDE)/rtems/mw_uid.h: libmisc/fb/mw_uid.h $(PROJECT_INCLUDE)/rtems/
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mw_uid.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mw_uid.h
+$(PROJECT_INCLUDE)/rtems/libmm.h: libmm/libmm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/libmm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/libmm.h
+
$(PROJECT_INCLUDE)/rtems/mouse_parser.h: libmisc/mouse/mouse_parser.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mouse_parser.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mouse_parser.h
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index d4f21ca..34b9823 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1951,6 +1951,12 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
#ifndef CONFIGURE_EXTRA_TASK_STACKS
#define CONFIGURE_EXTRA_TASK_STACKS 0
#endif
+/**
+ * This is the default alut size for libmm
+ */
+#ifndef CONFIGURE_LIBMM_ALUT_SIZE
+ #define CONFIGURE_LIBMM_ALUT_SIZE 64
+#endif
/*
* Calculate the RAM size based on the maximum number of objects configured.
@@ -2314,6 +2320,10 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
*/
uint8_t rtems_maximum_priority = CONFIGURE_MAXIMUM_PRIORITY;
+ /** This variable specifies the number of entries for libmm alut
+ */
+ uint32_t libmm_alut_size = CONFIGURE_LIBMM_ALUT_SIZE;
+
/**
* This is the primary Configuration Table for this application.
*/
diff --git a/cpukit/wrapup/Makefile.am b/cpukit/wrapup/Makefile.am
index 36d3103..197744d 100644
--- a/cpukit/wrapup/Makefile.am
+++ b/cpukit/wrapup/Makefile.am
@@ -28,6 +28,7 @@ TMP_LIBS += ../libfs/libdevfs.a
TMP_LIBS += ../libfs/libimfs.a
TMP_LIBS += ../libfs/librfs.a
+TMP_LIBS += ../libmm/libmm.a
TMP_LIBS += ../libmisc/libmonitor.a
TMP_LIBS += ../libmisc/libuntar.a
TMP_LIBS += ../libmisc/libstackchk.a
--
1.7.1
More information about the devel
mailing list