[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, &current->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(&current->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, &current->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(&current->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, &current->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, &current->node) ) {
+    if( rtems_chain_are_nodes_equal(&current->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, &current->node);
+
+      _Thread_Enable_dispatch();
+      return RTEMS_SUCCESSFUL;
+    } else {
+      current = (rtems_memory_management_entry*)rtems_chain_next(
+          &current->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