summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Cederman <cederman@gaisler.com>2014-07-03 16:42:24 +0200
committerDaniel Hellstrom <daniel@gaisler.com>2014-08-22 13:10:59 +0200
commit9a9ab85b45260be326d7a59f40c2d7363097eb10 (patch)
tree9117260c8bebfe126bdc041a1b8680374f7b40fb
parentscore: Add SMP support to the cache manager (diff)
downloadrtems-9a9ab85b45260be326d7a59f40c2d7363097eb10.tar.bz2
smptests/smpcache01: Test the SMP cache manager
Invokes SMP cache management routines under different scenarios.
-rw-r--r--testsuites/smptests/Makefile.am1
-rw-r--r--testsuites/smptests/configure.ac1
-rw-r--r--testsuites/smptests/smpcache01/Makefile.am19
-rw-r--r--testsuites/smptests/smpcache01/init.c291
-rw-r--r--testsuites/smptests/smpcache01/smpcache01.doc16
-rw-r--r--testsuites/smptests/smpcache01/smpcache01.scn14
6 files changed, 342 insertions, 0 deletions
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 <rtems/score/atomic.h>
+#include <rtems/score/smpbarrier.h>
+#include <rtems.h>
+#include <limits.h>
+#include <string.h>
+
+#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 <rtems/confdefs.h>
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 ***