From 9a9ab85b45260be326d7a59f40c2d7363097eb10 Mon Sep 17 00:00:00 2001 From: Daniel Cederman Date: Thu, 3 Jul 2014 16:42:24 +0200 Subject: smptests/smpcache01: Test the SMP cache manager Invokes SMP cache management routines under different scenarios. --- testsuites/smptests/Makefile.am | 1 + testsuites/smptests/configure.ac | 1 + testsuites/smptests/smpcache01/Makefile.am | 19 ++ testsuites/smptests/smpcache01/init.c | 291 ++++++++++++++++++++++++++ testsuites/smptests/smpcache01/smpcache01.doc | 16 ++ testsuites/smptests/smpcache01/smpcache01.scn | 14 ++ 6 files changed, 342 insertions(+) create mode 100644 testsuites/smptests/smpcache01/Makefile.am create mode 100644 testsuites/smptests/smpcache01/init.c create mode 100644 testsuites/smptests/smpcache01/smpcache01.doc create mode 100644 testsuites/smptests/smpcache01/smpcache01.scn diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am index a6e7209df0..1e72d43ce4 100644 --- a/testsuites/smptests/Makefile.am +++ b/testsuites/smptests/Makefile.am @@ -11,6 +11,7 @@ SUBDIRS += smp08 SUBDIRS += smp09 SUBDIRS += smpaffinity01 SUBDIRS += smpatomic01 +SUBDIRS += smpcache01 SUBDIRS += smpfatal01 SUBDIRS += smpfatal02 SUBDIRS += smpfatal03 diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac index d88b9a0775..9b6d99b023 100644 --- a/testsuites/smptests/configure.ac +++ b/testsuites/smptests/configure.ac @@ -66,6 +66,7 @@ smp08/Makefile smp09/Makefile smpaffinity01/Makefile smpatomic01/Makefile +smpcache01/Makefile smpfatal01/Makefile smpfatal02/Makefile smpfatal03/Makefile diff --git a/testsuites/smptests/smpcache01/Makefile.am b/testsuites/smptests/smpcache01/Makefile.am new file mode 100644 index 0000000000..3b092bc4df --- /dev/null +++ b/testsuites/smptests/smpcache01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = smpcache01 +smpcache01_SOURCES = init.c + +dist_rtems_tests_DATA = smpcache01.scn smpcache01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(smpcache01_OBJECTS) +LINK_LIBS = $(smpcache01_LDLIBS) + +smpcache01$(EXEEXT): $(smpcache01_OBJECTS) $(smpcache01_DEPENDENCIES) + @rm -f smpcache01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/smptests/smpcache01/init.c b/testsuites/smptests/smpcache01/init.c new file mode 100644 index 0000000000..dd2f9f15fa --- /dev/null +++ b/testsuites/smptests/smpcache01/init.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2014 Aeroflex Gaisler AB. All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "tmacros.h" + +const char rtems_test_name[] = "SMPCACHE 1"; + +#define CPU_COUNT 32 + +#define WORKER_PRIORITY 100 + +typedef void (*Cache_manager_Function_ptr)(const void *d_addr, size_t n_bytes); + +void +_Cache_manager_Send_smp_msg( + const size_t setsize, + const cpu_set_t *set, + Cache_manager_Function_ptr func, + const void * addr, + size_t size + ); + +typedef struct { + SMP_barrier_Control barrier; + uint32_t count[CPU_COUNT]; +} test_context; + +static test_context ctx = { + .barrier = SMP_BARRIER_CONTROL_INITIALIZER, +}; + +static void test_cache_message( const void *d_addr, size_t n_bytes ) +{ + rtems_test_assert(n_bytes == 123); + rtems_test_assert(d_addr == 0); + + ctx.count[rtems_get_current_processor()]++; +} + +static void all_cache_manager_smp_functions( size_t set_size, + cpu_set_t *cpu_set ) +{ + rtems_cache_flush_multiple_data_lines_processor_set( 0, 10, set_size, + cpu_set ); + rtems_cache_invalidate_multiple_data_lines_processor_set( 0, 10, set_size, + cpu_set ); + rtems_cache_flush_entire_data_processor_set( set_size, cpu_set ); + rtems_cache_invalidate_entire_data_processor_set( set_size, cpu_set ); + rtems_cache_invalidate_entire_instruction(); + rtems_cache_invalidate_multiple_instruction_lines( 0, 10 ); +} + +static void standard_funcs_test( size_t set_size, cpu_set_t *cpu_set ) +{ + all_cache_manager_smp_functions( set_size, cpu_set ); +} + +static void standard_funcs_isrdisabled_test( size_t set_size, + cpu_set_t *cpu_set, SMP_barrier_State *bs ) +{ + ISR_Level isr_level; + + _ISR_Disable_without_giant( isr_level ); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + all_cache_manager_smp_functions( set_size, cpu_set ); + + _ISR_Enable_without_giant( isr_level ); +} + +static void standard_funcs_giant_taken_test( size_t set_size, + cpu_set_t *cpu_set, SMP_barrier_State *bs ) +{ + if ( rtems_get_current_processor() == 0) + _Giant_Acquire(); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + all_cache_manager_smp_functions( set_size, cpu_set ); + + if ( rtems_get_current_processor() == 0) + _Giant_Release(); +} + +static void test_func_test( size_t set_size, cpu_set_t *cpu_set, + SMP_barrier_State *bs ) +{ + ctx.count[rtems_get_current_processor()] = 0; + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + _Cache_manager_Send_smp_msg( set_size, cpu_set, test_cache_message, 0, 123 ); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + rtems_test_assert( ctx.count[rtems_get_current_processor()] == + rtems_get_processor_count() ); +} + +static void test_func_isrdisabled_test( size_t set_size, cpu_set_t *cpu_set, + SMP_barrier_State *bs ) +{ + ISR_Level isr_level; + + ctx.count[rtems_get_current_processor()] = 0; + _ISR_Disable_without_giant( isr_level ); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + _Cache_manager_Send_smp_msg( set_size, cpu_set, test_cache_message, 0, 123 ); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + rtems_test_assert( ctx.count[rtems_get_current_processor()] == + rtems_get_processor_count() ); + + _ISR_Enable_without_giant( isr_level ); +} + +static void test_func_giant_taken_test( size_t set_size, cpu_set_t *cpu_set, + SMP_barrier_State *bs ) +{ + ctx.count[rtems_get_current_processor()] = 0; + + if ( rtems_get_current_processor() == 0) + _Giant_Acquire(); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + _Cache_manager_Send_smp_msg( set_size, cpu_set, test_cache_message, 0, 123 ); + + _SMP_barrier_Wait( &ctx.barrier, bs, rtems_get_processor_count() ); + + rtems_test_assert( ctx.count[rtems_get_current_processor()] == + rtems_get_processor_count() ); + + if ( rtems_get_current_processor() == 0) + _Giant_Release(); +} + +static void cmlog( const char* str ) +{ + if ( rtems_get_current_processor() == 0 ) + printf( "%s", str ); +} + +static void all_tests( void ) +{ + uint32_t cpu_count = rtems_get_processor_count(); + size_t set_size = CPU_ALLOC_SIZE( rtems_get_processor_count() ); + cpu_set_t *cpu_set = CPU_ALLOC( rtems_get_processor_count() ); + SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER; + + /* Send message to all available CPUs */ + CPU_FILL_S( set_size, cpu_set ); + + /* Call all SMP cache manager functions */ + cmlog( "Calling all standard SMP cache functions\n" ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + standard_funcs_test( set_size, cpu_set ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + cmlog( "Done!\n"); + + /* Call all SMP cache manager functions with ISR disabled */ + cmlog( "Calling all standard SMP cache functions. With ISR disabled\n" ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + standard_funcs_isrdisabled_test( set_size, cpu_set, &bs ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + cmlog( "Done!\n" ); + + /* Call all SMP cache manager functions with core 0 holding the giant lock */ + cmlog( "Calling all standard SMP cache functions. With CPU0 holding " + "the giant lock\n" ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + standard_funcs_giant_taken_test( set_size, cpu_set, &bs ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + cmlog( "Done!\n"); + + /* Call a test function using SMP cache manager and verify that all + * cores invoke the function */ + cmlog( "Calling a test function using the SMP cache manager to " + "verify that all CPUs receive the SMP message\n" ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + test_func_test( set_size, cpu_set, &bs ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + cmlog( "Done!\n"); + + /* Call a test function using SMP cache manager and verify that all + * cores invoke the function. ISR disabled. */ + cmlog( "Calling a test function using the SMP cache manager to " + "verify that all CPUs receive the SMP message. With ISR disabled\n" ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + test_func_isrdisabled_test( set_size, cpu_set, &bs ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + cmlog( "Done!\n" ); + + /* Call a test function using SMP cache manager and verify that all + * cores invoke the function. Core 0 holding giant lock. */ + cmlog( "Calling a test function using the SMP cache manager to " + "verify that all CPUs receive the SMP message. With CPU0 " + "holding the giant lock\n" ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + test_func_giant_taken_test( set_size, cpu_set, &bs ); + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count ); + cmlog( "Done!\n" ); + + /* Done. Free up memory. */ + _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count); + CPU_FREE( cpu_set ); +} + +static void worker_task(rtems_task_argument arg) +{ + rtems_status_code sc; + + all_tests(); + + sc = rtems_task_suspend(RTEMS_SELF); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void test_smp_cache_manager( void ) +{ + rtems_status_code sc; + size_t worker_index; + uint32_t cpu_count = rtems_get_processor_count(); + + for (worker_index = 1; worker_index < cpu_count; ++worker_index) { + rtems_id worker_id; + + sc = rtems_task_create( + rtems_build_name('W', 'R', 'K', '0'+worker_index), + WORKER_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &worker_id + ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + + sc = rtems_task_start( worker_id, worker_task, 0 ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + } + + all_tests(); +} + + +static void Init(rtems_task_argument arg) +{ + TEST_BEGIN(); + + test_smp_cache_manager(); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_SMP_APPLICATION + +#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT + +#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT + +#define CONFIGURE_MAXIMUM_TIMERS 1 + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/smptests/smpcache01/smpcache01.doc b/testsuites/smptests/smpcache01/smpcache01.doc new file mode 100644 index 0000000000..f6041b254d --- /dev/null +++ b/testsuites/smptests/smpcache01/smpcache01.doc @@ -0,0 +1,16 @@ +This file describes the directives and concepts tested by this test set. + +test set name: smpcache01 + +directives: + + - rtems_cache_flush_multiple_data_lines_processor_set + - rtems_cache_invalidate_multiple_data_lines_processor_set + - rtems_cache_flush_entire_data_processor_set + - rtems_cache_invalidate_entire_data_processor_set + - rtems_cache_invalidate_entire_instruction + - rtems_cache_invalidate_multiple_instruction_lines + +concepts: + + - Ensure that cache related SMP messages are delivered properly. diff --git a/testsuites/smptests/smpcache01/smpcache01.scn b/testsuites/smptests/smpcache01/smpcache01.scn new file mode 100644 index 0000000000..5964d3eb3e --- /dev/null +++ b/testsuites/smptests/smpcache01/smpcache01.scn @@ -0,0 +1,14 @@ +*** BEGIN OF TEST SMPCACHE 1 *** +Calling all standard SMP cache functions +Done! +Calling all standard SMP cache functions. With ISR disabled +Done! +Calling all standard SMP cache functions. With CPU0 holding the giant lock +Done! +Calling a test function using the SMP cache manager to verify that all CPUs receive the SMP message +Done! +Calling a test function using the SMP cache manager to verify that all CPUs receive the SMP message. With ISR disabled +Done! +Calling a test function using the SMP cache manager to verify that all CPUs receive the SMP message. With CPU0 holding the giant lock +Done! +*** END OF TEST SMPCACHE 1 *** -- cgit v1.2.3