summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2016-07-03 23:30:05 (UTC)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2016-07-04 13:55:58 (UTC)
commit06165554b62e3ba5bf322a8c3cfc2879e344bb1a (patch)
tree5a494af384f593e189d2733e48352b52b0793d7d
parent2b885d6084e5cf9595afb218364e117287015a3b (diff)
downloadrtems-06165554b62e3ba5bf322a8c3cfc2879e344bb1a.tar.bz2
bsps/arm: basic on core cache support changed to use l1 functions.
The basic data and instruction rage functions should be compatible for all ARMv4,5,6,7 functions. On the other hand, some functions are not portable, for example arm_cp15_data_cache_test_and_clean() and arm_cp15_data_cache_invalidate() for all versions and there has to be specialized version for newer cores. arm_cache_l1_properties_for_level uses CCSIDR which is not present on older chips. Actual version is only experimental, needs more changes and problem has been found on RPi1 with dlopen so there seems to be real problem.
-rw-r--r--c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h43
-rw-r--r--c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h71
-rw-r--r--c/src/lib/libcpu/arm/shared/include/arm-cp15.h31
3 files changed, 97 insertions, 48 deletions
diff --git a/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h b/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h
index bc19cb7..de5fddb 100644
--- a/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h
+++ b/c/src/lib/libbsp/arm/shared/armv467ar-basic-cache/cache_.h
@@ -24,6 +24,7 @@
#define LIBBSP_ARM_ARMV467AR_BASIC_CACHE_H
#include <libcpu/arm-cp15.h>
+#include "../include/arm-cache-l1.h"
#define CPU_DATA_CACHE_ALIGNMENT 32
#define CPU_INSTRUCTION_CACHE_ALIGNMENT 32
@@ -32,14 +33,44 @@
#define CPU_MAXIMAL_CACHE_ALIGNMENT 64
#endif
+#define CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS \
+ ARM_CACHE_L1_CPU_SUPPORT_PROVIDES_RANGE_FUNCTIONS
+
+
static inline void _CPU_cache_flush_1_data_line(const void *d_addr)
{
- arm_cp15_data_cache_clean_line(d_addr);
+ arm_cache_l1_flush_1_data_line(d_addr);
+}
+
+static inline void
+_CPU_cache_flush_data_range(
+ const void *d_addr,
+ size_t n_bytes
+)
+{
+ _ARM_Data_synchronization_barrier();
+ arm_cp15_drain_write_buffer();
+ arm_cache_l1_flush_data_range(
+ d_addr,
+ n_bytes
+ );
}
static inline void _CPU_cache_invalidate_1_data_line(const void *d_addr)
{
- arm_cp15_data_cache_invalidate_line(d_addr);
+ arm_cache_l1_invalidate_1_data_line(d_addr);
+}
+
+static inline void
+_CPU_cache_invalidate_data_range(
+ const void *addr_first,
+ size_t n_bytes
+)
+{
+ arm_cache_l1_invalidate_data_range(
+ addr_first,
+ n_bytes
+ );
}
static inline void _CPU_cache_freeze_data(void)
@@ -54,7 +85,13 @@ static inline void _CPU_cache_unfreeze_data(void)
static inline void _CPU_cache_invalidate_1_instruction_line(const void *d_addr)
{
- arm_cp15_instruction_cache_invalidate_line(d_addr);
+ arm_cache_l1_invalidate_1_instruction_line(d_addr);
+}
+
+static inline void
+_CPU_cache_invalidate_instruction_range( const void *i_addr, size_t n_bytes)
+{
+ arm_cache_l1_invalidate_instruction_range( i_addr, n_bytes );
}
static inline void _CPU_cache_freeze_instruction(void)
diff --git a/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h b/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h
index 1c3d9cf..74a65c5 100644
--- a/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h
+++ b/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h
@@ -37,8 +37,10 @@ extern "C" {
#define ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT 32
#define ARM_CACHE_L1_CPU_SUPPORT_PROVIDES_RANGE_FUNCTIONS
-#define ARM_CACHE_L1_CSS_ID_DATA 0
-#define ARM_CACHE_L1_CSS_ID_INSTRUCTION 1
+#define ARM_CACHE_L1_CSS_ID_DATA \
+ (ARM_CP15_CACHE_CSS_ID_DATA | ARM_CP15_CACHE_CSS_LEVEL(0))
+#define ARM_CACHE_L1_CSS_ID_INSTRUCTION \
+ (ARM_CP15_CACHE_CSS_ID_INSTRUCTION | ARM_CP15_CACHE_CSS_LEVEL(0))
#define ARM_CACHE_L1_DATA_LINE_MASK ( ARM_CACHE_L1_CPU_DATA_ALIGNMENT - 1 )
#define ARM_CACHE_L1_INSTRUCTION_LINE_MASK \
( ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT \
@@ -52,15 +54,6 @@ static void arm_cache_l1_errata_764369_handler( void )
#endif
}
-static void arm_cache_l1_select( const uint32_t selection )
-{
- /* select current cache level in cssr */
- arm_cp15_set_cache_size_selection( selection );
-
- /* isb to sych the new cssr&csidr */
- _ARM_Instruction_synchronization_barrier();
-}
-
/*
* @param l1LineSize Number of bytes in cache line expressed as power of
* 2 value
@@ -69,22 +62,23 @@ static void arm_cache_l1_select( const uint32_t selection )
* qparam liNumSets Number of sets in cache
* */
-static inline void arm_cache_l1_properties(
+static inline void arm_cache_l1_properties_for_level(
uint32_t *l1LineSize,
uint32_t *l1Associativity,
- uint32_t *l1NumSets )
+ uint32_t *l1NumSets,
+ uint32_t level_and_inst_dat
+)
{
- uint32_t id;
+ uint32_t ccsidr;
- _ARM_Instruction_synchronization_barrier();
- id = arm_cp15_get_cache_size_id();
+ ccsidr = arm_cp15_get_cache_size_id_for_level(level_and_inst_dat);
/* Cache line size in words + 2 -> bytes) */
- *l1LineSize = ( id & 0x0007U ) + 2 + 2;
+ *l1LineSize = arm_ccsidr_get_line_power(ccsidr);
/* Number of Ways */
- *l1Associativity = ( ( id >> 3 ) & 0x03ffU ) + 1;
+ *l1Associativity = arm_ccsidr_get_associativity(ccsidr);
/* Number of Sets */
- *l1NumSets = ( ( id >> 13 ) & 0x7fffU ) + 1;
+ *l1NumSets = arm_ccsidr_get_num_sets(ccsidr);
}
/*
@@ -130,8 +124,9 @@ static inline void arm_cache_l1_flush_entire_data( void )
_ARM_Data_memory_barrier();
/* Get the L1 cache properties */
- arm_cache_l1_properties( &l1LineSize, &l1Associativity,
- &l1NumSets );
+ arm_cache_l1_properties_for_level( &l1LineSize,
+ &l1Associativity, &l1NumSets,
+ ARM_CACHE_L1_CSS_ID_DATA);
for ( w = 0; w < l1Associativity; ++w ) {
for ( s = 0; s < l1NumSets; ++s ) {
@@ -160,8 +155,9 @@ static inline void arm_cache_l1_invalidate_entire_data( void )
_ARM_Data_memory_barrier();
/* Get the L1 cache properties */
- arm_cache_l1_properties( &l1LineSize, &l1Associativity,
- &l1NumSets );
+ arm_cache_l1_properties_for_level( &l1LineSize,
+ &l1Associativity, &l1NumSets,
+ ARM_CACHE_L1_CSS_ID_DATA);
for ( w = 0; w < l1Associativity; ++w ) {
for ( s = 0; s < l1NumSets; ++s ) {
@@ -191,8 +187,9 @@ static inline void arm_cache_l1_clean_and_invalidate_entire_data( void )
/* Get the L1 cache properties */
- arm_cache_l1_properties( &l1LineSize, &l1Associativity,
- &l1NumSets );
+ arm_cache_l1_properties_for_level( &l1LineSize,
+ &l1Associativity, &l1NumSets,
+ ARM_CACHE_L1_CSS_ID_DATA);
for ( w = 0; w < l1Associativity; ++w ) {
for ( s = 0; s < l1NumSets; ++s ) {
@@ -371,19 +368,14 @@ static inline void arm_cache_l1_disable_instruction( void )
static inline size_t arm_cache_l1_get_data_cache_size( void )
{
- rtems_interrupt_level level;
size_t size;
uint32_t line_size = 0;
uint32_t associativity = 0;
uint32_t num_sets = 0;
- rtems_interrupt_local_disable(level);
-
- arm_cache_l1_select( ARM_CACHE_L1_CSS_ID_DATA );
- arm_cache_l1_properties( &line_size, &associativity,
- &num_sets );
-
- rtems_interrupt_local_enable(level);
+ arm_cache_l1_properties_for_level( &line_size,
+ &associativity, &num_sets,
+ ARM_CACHE_L1_CSS_ID_DATA);
size = (1 << line_size) * associativity * num_sets;
@@ -392,22 +384,17 @@ static inline size_t arm_cache_l1_get_data_cache_size( void )
static inline size_t arm_cache_l1_get_instruction_cache_size( void )
{
- rtems_interrupt_level level;
size_t size;
uint32_t line_size = 0;
uint32_t associativity = 0;
uint32_t num_sets = 0;
- rtems_interrupt_local_disable(level);
-
- arm_cache_l1_select( ARM_CACHE_L1_CSS_ID_INSTRUCTION );
- arm_cache_l1_properties( &line_size, &associativity,
- &num_sets );
-
- rtems_interrupt_local_enable(level);
+ arm_cache_l1_properties_for_level( &line_size,
+ &associativity, &num_sets,
+ ARM_CACHE_L1_CSS_ID_INSTRUCTION);
size = (1 << line_size) * associativity * num_sets;
-
+
return size;
}
diff --git a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
index 8357656..ca7a11e 100644
--- a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
+++ b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
@@ -210,6 +210,18 @@ extern "C" {
/** @} */
+/**
+ * @name CCSIDR, Cache Size ID Register Defines
+ *
+ * @{
+ */
+
+#define ARM_CP15_CACHE_CSS_ID_DATA 0
+#define ARM_CP15_CACHE_CSS_ID_INSTRUCTION 1
+#define ARM_CP15_CACHE_CSS_LEVEL(level) ((level) << 1)
+
+/** @} */
+
ARM_CP15_TEXT_SECTION static inline uint32_t
arm_cp15_get_id_code(void)
{
@@ -819,6 +831,21 @@ arm_cp15_set_cache_size_selection(uint32_t val)
);
}
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_cache_size_id_for_level(uint32_t level_and_inst_dat)
+{
+ rtems_interrupt_level irq_level;
+ uint32_t ccsidr;
+
+ rtems_interrupt_local_disable(irq_level);
+ arm_cp15_set_cache_size_selection(level_and_inst_dat);
+ _ARM_Instruction_synchronization_barrier();
+ ccsidr = arm_cp15_get_cache_size_id();
+ rtems_interrupt_local_enable(irq_level);
+
+ return ccsidr;
+}
+
ARM_CP15_TEXT_SECTION static inline void
arm_cp15_cache_invalidate(void)
{
@@ -1036,10 +1063,8 @@ arm_cp15_data_cache_invalidate_all_levels(void)
uint32_t way;
uint32_t way_shift;
- arm_cp15_set_cache_size_selection(level << 1);
- _ARM_Instruction_synchronization_barrier();
+ ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
- ccsidr = arm_cp15_get_cache_size_id();
line_power = arm_ccsidr_get_line_power(ccsidr);
associativity = arm_ccsidr_get_associativity(ccsidr);
way_shift = __builtin_clz(associativity - 1);