summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2016-07-03 00:19:38 +0200
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2016-10-02 10:40:33 +0200
commiteb3af275ead2a9f5972fa1a7b69a4017a8cdf606 (patch)
treecc61eea50a586b4c4666a21e80669ec94f249f4f
parentscore/arm: Ensure that copile time alignment is 64 bytes for Cortex-A multilib. (diff)
downloadrtems-eb3af275ead2a9f5972fa1a7b69a4017a8cdf606.tar.bz2
rtems+bsps/cache: Define cache manager operations for code synchronization and maximal alignment.
There is need for unambiguous named and defined cache function which should be called when code is updated, loaded or is self-modifying. There should be function to obtain maximal cache line length as well. This function can and should be used for allocations which can be used for data and or code and ensures that there are no partial cache lines overlaps on start and end of allocated region. Updates #2782
-rw-r--r--c/src/lib/libcpu/shared/src/cache_manager.c42
-rw-r--r--cpukit/libcsupport/src/cachealignedalloc.c2
-rw-r--r--cpukit/rtems/include/rtems/rtems/cache.h29
3 files changed, 72 insertions, 1 deletions
diff --git a/c/src/lib/libcpu/shared/src/cache_manager.c b/c/src/lib/libcpu/shared/src/cache_manager.c
index 202ea8e1ba..00d2476fa9 100644
--- a/c/src/lib/libcpu/shared/src/cache_manager.c
+++ b/c/src/lib/libcpu/shared/src/cache_manager.c
@@ -469,3 +469,45 @@ rtems_cache_disable_instruction( void )
_CPU_cache_disable_instruction();
#endif
}
+
+/* Returns the maximal cache line size of all cache kinds in bytes. */
+size_t rtems_cache_get_maximal_line_size( void )
+{
+#if defined(CPU_MAXIMAL_CACHE_ALIGNMENT)
+ return CPU_MAXIMAL_CACHE_ALIGNMENT;
+#endif
+ size_t max_line_size = 0;
+#if defined(CPU_DATA_CACHE_ALIGNMENT)
+ {
+ size_t data_line_size = CPU_DATA_CACHE_ALIGNMENT;
+ if ( max_line_size < data_line_size )
+ max_line_size = data_line_size;
+ }
+#endif
+#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
+ {
+ size_t instruction_line_size = CPU_INSTRUCTION_CACHE_ALIGNMENT;
+ if ( max_line_size < instruction_line_size )
+ max_line_size = instruction_line_size;
+ }
+#endif
+ return max_line_size;
+}
+
+/*
+ * Purpose is to synchronize caches after code has been loaded
+ * or self modified. Actual implementation is simple only
+ * but it can and should be repaced by optimized version
+ * which does not need flush and invalidate all cache levels
+ * when code is changed.
+ */
+void
+rtems_cache_instruction_sync_after_code_change( const void * code_addr, size_t n_bytes )
+{
+#if defined(CPU_CACHE_SUPPORT_PROVIDES_INSTRUCTION_SYNC_FUNCTION)
+ _CPU_cache_instruction_sync_after_code_change( code_addr, n_bytes );
+#else
+ rtems_cache_flush_multiple_data_lines( code_addr, n_bytes );
+ rtems_cache_invalidate_multiple_instruction_lines( code_addr, n_bytes );
+#endif
+}
diff --git a/cpukit/libcsupport/src/cachealignedalloc.c b/cpukit/libcsupport/src/cachealignedalloc.c
index a704859dbe..764fdfb331 100644
--- a/cpukit/libcsupport/src/cachealignedalloc.c
+++ b/cpukit/libcsupport/src/cachealignedalloc.c
@@ -15,7 +15,7 @@
void *rtems_cache_aligned_malloc( size_t nbytes )
{
- size_t line_size = rtems_cache_get_data_line_size();
+ size_t line_size = rtems_cache_get_maximal_line_size();
if ( line_size > 0 ) {
/* Assume that the cache line size is a power of two */
diff --git a/cpukit/rtems/include/rtems/rtems/cache.h b/cpukit/rtems/include/rtems/rtems/cache.h
index a7dcaa60fd..f1dc9bf03d 100644
--- a/cpukit/rtems/include/rtems/rtems/cache.h
+++ b/cpukit/rtems/include/rtems/rtems/cache.h
@@ -61,6 +61,17 @@ size_t rtems_cache_get_data_line_size( void );
size_t rtems_cache_get_instruction_line_size( void );
/**
+ * @brief Returns the maximal cache line size of all cache kinds in bytes.
+ *
+ * Returns computed or obtained maximal cache line size of all
+ * all caches in the system.
+ *
+ * @retval 0 No cache is present
+ * @retval positive The maximal cache line size in bytes.
+ */
+size_t rtems_cache_get_maximal_line_size( void );
+
+/**
* @brief Returns the data cache size in bytes.
*
* @param[in] level The cache level of interest. The cache level zero
@@ -125,6 +136,24 @@ void rtems_cache_invalidate_multiple_instruction_lines(
size_t size
);
+
+/**
+ * @brief Ensure necessary synchronization required after code changes
+ *
+ * When code is loaded or modified then many Harvard cache equipped
+ * systems require synchronization of main memory and or updated
+ * code in data cache to ensure visibility of change in all
+ * connected CPUs instruction memory view. This operation
+ * should be used by run time loader for example.
+ *
+ * @param[in] addr The start address of the area to invalidate.
+ * @param[in] size The size in bytes of the area to invalidate.
+ */
+void rtems_cache_instruction_sync_after_code_change(
+ const void * code_addr,
+ size_t n_bytes
+);
+
/**
* @brief Flushes the entire data cache.
*