[PATCH 6/6 v2] libdl/rtl-obj.c: synchronize cache after code relocation.

Pavel Pisa pisa at cmp.felk.cvut.cz
Wed Jul 20 08:55:20 UTC 2016


From be993a950be6c382b70609bcbc38be9bd161e1d4 Mon Sep 17 00:00:00 2001
Message-Id: <be993a950be6c382b70609bcbc38be9bd161e1d4.1469004576.git.pisa at cmp.felk.cvut.cz>
From: Pavel Pisa <pisa at cmp.felk.cvut.cz>
Date: Wed, 20 Jul 2016 10:49:19 +0200
Subject: [PATCH] libdl/rtl-obj.c: synchronize cache after code relocation.
To: rtems-devel at rtems.org

Memory content changes caused by relocation has to be
propagated to memory/cache level which is used/snooped
during instruction cache fill.
---
 cpukit/libdl/rtl-elf.c |  2 ++
 cpukit/libdl/rtl-obj.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++--
 cpukit/libdl/rtl-obj.h |  7 ++++++
 cpukit/libdl/rtl-rap.c |  2 ++
 4 files changed, 74 insertions(+), 2 deletions(-)

 V2:
   - rtems_rtl_obj_synchronize_cache () without return value
   - use rtems_cache_get_instruction_line_size () to skip
     cache synchronization when given BSP build does not
     provide/use instruction cache but CPUkit architecture
     variant covers even systems with cache

diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index 0eee540..48d81df 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -941,6 +941,8 @@ rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd)
   if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
     return false;
 
+  rtems_rtl_obj_synchronize_cache (obj);
+
   rtems_rtl_symbol_obj_erase_local (obj);
 
   if (!rtems_rtl_elf_load_details (obj))
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 00a1c6e..f61d4e5 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -558,6 +558,69 @@ rtems_rtl_obj_relocate (rtems_rtl_obj_t*             obj,
   return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
 }
 
+/**
+ * Cache synchronization after runtime object load (dlopen)
+ */
+typedef struct
+{
+  uint32_t mask;
+  void     *start_va;
+  void     *end_va;
+} rtems_rtl_obj_sect_sync_ctx_t;
+
+static bool
+rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data)
+{
+  rtems_rtl_obj_sect_t*   sect = (rtems_rtl_obj_sect_t*) node;
+  rtems_rtl_obj_sect_sync_ctx_t* sync_ctx = data;
+  uintptr_t old_end;
+  uintptr_t new_start;
+
+  if ( !(sect->flags & sync_ctx->mask) || !sect->size)
+    return true;
+
+  if (sync_ctx->end_va == sync_ctx->start_va) {
+    sync_ctx->start_va = sect->base;
+  } else {
+    old_end = (uintptr_t)sync_ctx->end_va & ~(CPU_CACHE_LINE_BYTES - 1);
+    new_start = (uintptr_t)sect->base & ~(CPU_CACHE_LINE_BYTES - 1);
+    if ( (sect->base <  sync_ctx->start_va) ||
+         (new_start - old_end > CPU_CACHE_LINE_BYTES) ) {
+      rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va,
+                             sync_ctx->end_va - sync_ctx->start_va + 1);
+      sync_ctx->start_va = sect->base;
+    }
+  }
+
+  sync_ctx->end_va = sect->base + sect->size;
+
+  return true;
+}
+
+void
+rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t*    obj)
+{
+  rtems_rtl_obj_sect_sync_ctx_t sync_ctx;
+
+  if (rtems_cache_get_instruction_line_size() == 0)
+    return;
+
+  sync_ctx.mask = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST |
+                  RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_BSS |
+                  RTEMS_RTL_OBJ_SECT_EXEC;
+
+  sync_ctx.start_va = 0;
+  sync_ctx.end_va = sync_ctx.start_va;
+  rtems_rtl_chain_iterate (&obj->sections,
+                           rtems_rtl_obj_sect_sync_handler,
+                           &sync_ctx);
+
+  if (sync_ctx.end_va != sync_ctx.start_va) {
+    rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va,
+                              sync_ctx.end_va - sync_ctx.start_va);
+  }
+}
+
 bool
 rtems_rtl_obj_load_symbols (rtems_rtl_obj_t*             obj,
                             int                          fd,
@@ -618,8 +681,6 @@ rtems_rtl_obj_sections_loader (uint32_t                     mask,
       first = false;
     }
 
-    rtems_cache_instruction_sync_after_code_change(base, base_offset);
-
     node = rtems_chain_next (node);
   }
 
diff --git a/cpukit/libdl/rtl-obj.h b/cpukit/libdl/rtl-obj.h
index 1202fd5..80fc60f 100644
--- a/cpukit/libdl/rtl-obj.h
+++ b/cpukit/libdl/rtl-obj.h
@@ -494,6 +494,13 @@ bool rtems_rtl_obj_relocate (rtems_rtl_obj_t*             obj,
                              void*                        data);
 
 /**
+ * Synchronize caches to make code visible to CPU(s)
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t*    obj);
+
+/**
  * Relocate an object file's unresolved reference.
  *
  * @param rec The unresolved relocation record.
diff --git a/cpukit/libdl/rtl-rap.c b/cpukit/libdl/rtl-rap.c
index 439eb20..a7fcb9f 100644
--- a/cpukit/libdl/rtl-rap.c
+++ b/cpukit/libdl/rtl-rap.c
@@ -970,6 +970,8 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
   if (!rtems_rtl_rap_relocate (&rap, obj))
     return false;
 
+  rtems_rtl_obj_synchronize_cache (obj);
+
   return true;
 }
 
-- 
1.9.1




More information about the devel mailing list