[9a9ab85] | 1 | /* |
---|
| 2 | * Copyright (c) 2014 Aeroflex Gaisler AB. All rights reserved. |
---|
| 3 | * |
---|
| 4 | * The license and distribution terms for this file may be |
---|
| 5 | * found in the file LICENSE in this distribution or at |
---|
| 6 | * http://www.rtems.org/license/LICENSE. |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | #ifdef HAVE_CONFIG_H |
---|
| 10 | #include "config.h" |
---|
| 11 | #endif |
---|
| 12 | |
---|
| 13 | #include <rtems/score/atomic.h> |
---|
| 14 | #include <rtems/score/smpbarrier.h> |
---|
[26c142e5] | 15 | #include <rtems/score/smpimpl.h> |
---|
[9a9ab85] | 16 | #include <rtems.h> |
---|
| 17 | #include <limits.h> |
---|
| 18 | #include <string.h> |
---|
| 19 | |
---|
| 20 | #include "tmacros.h" |
---|
| 21 | |
---|
| 22 | const char rtems_test_name[] = "SMPCACHE 1"; |
---|
| 23 | |
---|
[6e1206a] | 24 | CPU_STRUCTURE_ALIGNMENT static int data_to_flush[1024]; |
---|
| 25 | |
---|
[9a9ab85] | 26 | #define CPU_COUNT 32 |
---|
| 27 | |
---|
| 28 | #define WORKER_PRIORITY 100 |
---|
| 29 | |
---|
| 30 | typedef struct { |
---|
| 31 | SMP_barrier_Control barrier; |
---|
| 32 | uint32_t count[CPU_COUNT]; |
---|
| 33 | } test_context; |
---|
| 34 | |
---|
| 35 | static test_context ctx = { |
---|
| 36 | .barrier = SMP_BARRIER_CONTROL_INITIALIZER, |
---|
| 37 | }; |
---|
| 38 | |
---|
[6e1206a] | 39 | static void function_to_flush( void ) |
---|
| 40 | { |
---|
| 41 | /* Does nothing. Used to give a pointer to instruction address space. */ |
---|
| 42 | } |
---|
| 43 | |
---|
[b1b5ddf0] | 44 | static void test_action( void *arg ) |
---|
[9a9ab85] | 45 | { |
---|
[26c142e5] | 46 | rtems_test_assert(arg == &ctx); |
---|
[9a9ab85] | 47 | |
---|
| 48 | ctx.count[rtems_get_current_processor()]++; |
---|
| 49 | } |
---|
| 50 | |
---|
[b1b5ddf0] | 51 | typedef void ( *test_case )( |
---|
| 52 | size_t set_size, |
---|
| 53 | const cpu_set_t *cpu_set, |
---|
| 54 | SMP_barrier_State *bs |
---|
| 55 | ); |
---|
| 56 | |
---|
| 57 | static void test_cache_flush_multiple_data_lines( |
---|
| 58 | size_t set_size, |
---|
| 59 | const cpu_set_t *cpu_set, |
---|
| 60 | SMP_barrier_State *bs |
---|
| 61 | ) |
---|
[9a9ab85] | 62 | { |
---|
[6e1206a] | 63 | rtems_cache_flush_multiple_data_lines_processor_set( &data_to_flush, |
---|
| 64 | sizeof(data_to_flush), set_size, cpu_set ); |
---|
[b1b5ddf0] | 65 | } |
---|
| 66 | |
---|
| 67 | static void test_cache_invalidate_multiple_data_lines( |
---|
| 68 | size_t set_size, |
---|
| 69 | const cpu_set_t *cpu_set, |
---|
| 70 | SMP_barrier_State *bs |
---|
| 71 | ) |
---|
| 72 | { |
---|
[6e1206a] | 73 | rtems_cache_invalidate_multiple_data_lines_processor_set( &data_to_flush, |
---|
| 74 | sizeof(data_to_flush), set_size, cpu_set ); |
---|
[9a9ab85] | 75 | } |
---|
| 76 | |
---|
[b1b5ddf0] | 77 | static void test_cache_flush_entire_data( |
---|
| 78 | size_t set_size, |
---|
| 79 | const cpu_set_t *cpu_set, |
---|
| 80 | SMP_barrier_State *bs |
---|
| 81 | ) |
---|
[9a9ab85] | 82 | { |
---|
[b1b5ddf0] | 83 | rtems_cache_flush_entire_data_processor_set( set_size, cpu_set ); |
---|
[9a9ab85] | 84 | } |
---|
| 85 | |
---|
[b1b5ddf0] | 86 | static void test_cache_invalidate_entire_instruction( |
---|
| 87 | size_t set_size, |
---|
| 88 | const cpu_set_t *cpu_set, |
---|
| 89 | SMP_barrier_State *bs |
---|
| 90 | ) |
---|
[9a9ab85] | 91 | { |
---|
[b1b5ddf0] | 92 | rtems_cache_invalidate_entire_instruction(); |
---|
[9a9ab85] | 93 | } |
---|
| 94 | |
---|
[b1b5ddf0] | 95 | static void test_cache_invalidate_multiple_instruction_lines( |
---|
| 96 | size_t set_size, |
---|
| 97 | const cpu_set_t *cpu_set, |
---|
| 98 | SMP_barrier_State *bs |
---|
| 99 | ) |
---|
[9a9ab85] | 100 | { |
---|
[b1b5ddf0] | 101 | rtems_cache_invalidate_multiple_instruction_lines( &function_to_flush, |
---|
| 102 | 4 /* arbitrary size */ ); |
---|
[9a9ab85] | 103 | } |
---|
| 104 | |
---|
[b1b5ddf0] | 105 | static void test_broadcast_action( |
---|
| 106 | size_t set_size, |
---|
| 107 | const cpu_set_t *cpu_set, |
---|
| 108 | SMP_barrier_State *bs |
---|
| 109 | ) |
---|
[9a9ab85] | 110 | { |
---|
| 111 | ctx.count[rtems_get_current_processor()] = 0; |
---|
| 112 | _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); |
---|
| 113 | |
---|
[b1b5ddf0] | 114 | _SMP_Multicast_action( set_size, cpu_set, test_action, &ctx ); |
---|
[9a9ab85] | 115 | |
---|
| 116 | _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); |
---|
| 117 | |
---|
| 118 | rtems_test_assert( ctx.count[rtems_get_current_processor()] == |
---|
| 119 | rtems_get_processor_count() ); |
---|
| 120 | } |
---|
| 121 | |
---|
[b1b5ddf0] | 122 | static test_case test_cases[] = { |
---|
| 123 | test_cache_flush_multiple_data_lines, |
---|
| 124 | test_cache_invalidate_multiple_data_lines, |
---|
| 125 | test_cache_flush_entire_data, |
---|
| 126 | test_cache_invalidate_entire_instruction, |
---|
| 127 | test_cache_invalidate_multiple_instruction_lines, |
---|
| 128 | test_broadcast_action |
---|
| 129 | }; |
---|
[9a9ab85] | 130 | |
---|
[b1b5ddf0] | 131 | static void call_test( |
---|
| 132 | size_t set_size, |
---|
| 133 | const cpu_set_t *cpu_set, |
---|
| 134 | SMP_barrier_State *bs, |
---|
| 135 | size_t i |
---|
| 136 | ) |
---|
| 137 | { |
---|
[9a9ab85] | 138 | _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); |
---|
[b1b5ddf0] | 139 | ( *test_cases[ i ] )( set_size, cpu_set, bs ); |
---|
[9a9ab85] | 140 | _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); |
---|
[b1b5ddf0] | 141 | } |
---|
[9a9ab85] | 142 | |
---|
[b1b5ddf0] | 143 | static void call_tests( size_t set_size, |
---|
| 144 | const cpu_set_t *cpu_set, SMP_barrier_State *bs ) |
---|
| 145 | { |
---|
| 146 | size_t i; |
---|
| 147 | |
---|
| 148 | for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) { |
---|
| 149 | call_test( set_size, cpu_set, bs, i ); |
---|
| 150 | } |
---|
[9a9ab85] | 151 | } |
---|
| 152 | |
---|
[b1b5ddf0] | 153 | static void call_tests_isr_disabled( size_t set_size, |
---|
| 154 | const cpu_set_t *cpu_set, SMP_barrier_State *bs ) |
---|
[9a9ab85] | 155 | { |
---|
[b1b5ddf0] | 156 | size_t i; |
---|
[9a9ab85] | 157 | |
---|
[b1b5ddf0] | 158 | for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) { |
---|
| 159 | ISR_Level isr_level; |
---|
[9a9ab85] | 160 | |
---|
[4b04cb61] | 161 | _ISR_Local_disable( isr_level ); |
---|
[9a9ab85] | 162 | |
---|
[b1b5ddf0] | 163 | call_test( set_size, cpu_set, bs, i ); |
---|
[9a9ab85] | 164 | |
---|
[4b04cb61] | 165 | _ISR_Local_enable( isr_level ); |
---|
[b1b5ddf0] | 166 | } |
---|
| 167 | } |
---|
[9a9ab85] | 168 | |
---|
[dab902d5] | 169 | static void call_tests_with_thread_dispatch_disabled( size_t set_size, |
---|
[b1b5ddf0] | 170 | const cpu_set_t *cpu_set, SMP_barrier_State *bs ) |
---|
| 171 | { |
---|
| 172 | size_t i; |
---|
| 173 | |
---|
| 174 | for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) { |
---|
[dab902d5] | 175 | Per_CPU_Control *cpu_self; |
---|
| 176 | |
---|
| 177 | cpu_self = _Thread_Dispatch_disable(); |
---|
[b1b5ddf0] | 178 | |
---|
| 179 | call_test( set_size, cpu_set, bs, i ); |
---|
[9a9ab85] | 180 | |
---|
[dab902d5] | 181 | _Thread_Dispatch_enable( cpu_self ); |
---|
[b1b5ddf0] | 182 | } |
---|
[9a9ab85] | 183 | } |
---|
| 184 | |
---|
| 185 | static void cmlog( const char* str ) |
---|
| 186 | { |
---|
| 187 | if ( rtems_get_current_processor() == 0 ) |
---|
| 188 | printf( "%s", str ); |
---|
| 189 | } |
---|
| 190 | |
---|
| 191 | static void all_tests( void ) |
---|
| 192 | { |
---|
| 193 | uint32_t cpu_count = rtems_get_processor_count(); |
---|
| 194 | size_t set_size = CPU_ALLOC_SIZE( rtems_get_processor_count() ); |
---|
| 195 | cpu_set_t *cpu_set = CPU_ALLOC( rtems_get_processor_count() ); |
---|
| 196 | SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER; |
---|
| 197 | |
---|
| 198 | /* Send message to all available CPUs */ |
---|
| 199 | CPU_FILL_S( set_size, cpu_set ); |
---|
| 200 | |
---|
[b1b5ddf0] | 201 | /* Call test cases */ |
---|
| 202 | cmlog( "Calling test cases. " ); |
---|
| 203 | call_tests( set_size, cpu_set, &bs ); |
---|
[9a9ab85] | 204 | cmlog( "Done!\n"); |
---|
| 205 | |
---|
[b1b5ddf0] | 206 | /* Call test cases with ISR disabled */ |
---|
| 207 | cmlog( "Calling test cases with ISR disabled. " ); |
---|
| 208 | call_tests_isr_disabled( set_size, cpu_set, &bs ); |
---|
[9a9ab85] | 209 | cmlog( "Done!\n" ); |
---|
| 210 | |
---|
[dab902d5] | 211 | /* Call test cases with thread dispatch disabled */ |
---|
| 212 | cmlog( "Calling test cases with thread_dispatch_disabled. "); |
---|
| 213 | call_tests_with_thread_dispatch_disabled( set_size, cpu_set, &bs ); |
---|
[9a9ab85] | 214 | cmlog( "Done!\n"); |
---|
| 215 | |
---|
| 216 | /* Done. Free up memory. */ |
---|
| 217 | _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count); |
---|
| 218 | CPU_FREE( cpu_set ); |
---|
| 219 | } |
---|
| 220 | |
---|
| 221 | static void worker_task(rtems_task_argument arg) |
---|
| 222 | { |
---|
| 223 | rtems_status_code sc; |
---|
| 224 | |
---|
| 225 | all_tests(); |
---|
| 226 | |
---|
| 227 | sc = rtems_task_suspend(RTEMS_SELF); |
---|
| 228 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
| 229 | } |
---|
| 230 | |
---|
| 231 | static void test_smp_cache_manager( void ) |
---|
| 232 | { |
---|
| 233 | rtems_status_code sc; |
---|
| 234 | size_t worker_index; |
---|
| 235 | uint32_t cpu_count = rtems_get_processor_count(); |
---|
| 236 | |
---|
| 237 | for (worker_index = 1; worker_index < cpu_count; ++worker_index) { |
---|
| 238 | rtems_id worker_id; |
---|
| 239 | |
---|
| 240 | sc = rtems_task_create( |
---|
| 241 | rtems_build_name('W', 'R', 'K', '0'+worker_index), |
---|
| 242 | WORKER_PRIORITY, |
---|
| 243 | RTEMS_MINIMUM_STACK_SIZE, |
---|
| 244 | RTEMS_DEFAULT_MODES, |
---|
| 245 | RTEMS_DEFAULT_ATTRIBUTES, |
---|
| 246 | &worker_id |
---|
| 247 | ); |
---|
| 248 | rtems_test_assert( sc == RTEMS_SUCCESSFUL ); |
---|
| 249 | |
---|
| 250 | sc = rtems_task_start( worker_id, worker_task, 0 ); |
---|
| 251 | rtems_test_assert( sc == RTEMS_SUCCESSFUL ); |
---|
| 252 | } |
---|
| 253 | |
---|
| 254 | all_tests(); |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | |
---|
| 258 | static void Init(rtems_task_argument arg) |
---|
| 259 | { |
---|
| 260 | TEST_BEGIN(); |
---|
| 261 | |
---|
| 262 | test_smp_cache_manager(); |
---|
| 263 | |
---|
| 264 | TEST_END(); |
---|
| 265 | rtems_test_exit(0); |
---|
| 266 | } |
---|
| 267 | |
---|
| 268 | #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER |
---|
| 269 | #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER |
---|
| 270 | |
---|
[54835ae] | 271 | #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT |
---|
[9a9ab85] | 272 | |
---|
| 273 | #define CONFIGURE_MAXIMUM_TASKS CPU_COUNT |
---|
| 274 | |
---|
| 275 | #define CONFIGURE_MAXIMUM_TIMERS 1 |
---|
| 276 | |
---|
| 277 | #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION |
---|
| 278 | |
---|
| 279 | #define CONFIGURE_RTEMS_INIT_TASKS_TABLE |
---|
| 280 | |
---|
| 281 | #define CONFIGURE_INIT |
---|
| 282 | |
---|
| 283 | #include <rtems/confdefs.h> |
---|