Add tests which ensure that the cache handles start addresses and end addresses which are not exactly on a cache line border correctly. --- testsuites/sptests/spcache01/init.c | 276 +++++++++++++++++++++++++++- testsuites/sptests/spcache01/spcache01.doc | 1 + testsuites/sptests/spcache01/spcache01.scn | 2 + 3 Dateien geändert, 276 Zeilen hinzugefügt(+), 3 Zeilen entfernt(-)
diff --git a/testsuites/sptests/spcache01/init.c b/testsuites/sptests/spcache01/init.c index 2c9d184..303f7f6 100644 --- a/testsuites/sptests/spcache01/init.c +++ b/testsuites/sptests/spcache01/init.c @@ -37,16 +37,282 @@ const char rtems_test_name[] = "SPCACHE 1"; CPU_STRUCTURE_ALIGNMENT static int data[1024]; -static void test_data_flush_and_invalidate(void) +static void test_misalignment( const bool write_through ) { if (rtems_cache_get_data_line_size() > 0) { rtems_interrupt_lock lock; rtems_interrupt_lock_context lock_context; + const uint32_t LINE_SIZE = rtems_cache_get_data_line_size(); + volatile int *vdata = &data[0]; /* Verification start address */ + int *tdata = &data[LINE_SIZE / sizeof(data[0])]; /* test start address (first word in second cache line) */ + int tcount = 1; /* Words to be tested */ + size_t tdata_bytes = tcount * sizeof(data[0]); /* Bytes to be tested */ + size_t vdata_bytes = LINE_SIZE; /* Bytes expected to be affected by cache maintenance */ + int vcount = (vdata_bytes / sizeof(data[0])) + (2 * LINE_SIZE / sizeof(data[0])); /* Words to be verified (Words affected + 2 adjacent cache lines) */ + int i; + int end; + + printf("data cache flush and invalidate test with misaligned addresses\n"); + + rtems_interrupt_lock_initialize(&lock, "test"); + rtems_interrupt_lock_acquire(&lock, &lock_context); + + /* + * Test with flushing/invalidating at the beginning of a cache line + * The modified line shall get invalidated/flushed entirely, + * adjacent cache lines shall remain unchanged. + */ + for (i = 0; i < vcount; ++i) { + vdata[i] = i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + end = LINE_SIZE / sizeof(data[0]); + for (i = 0; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + i = end; + end = i + (vdata_bytes / sizeof(data[0])); + + if (write_through) { + for ( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + } else { + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == i); + } + } + i = end; + end = i + (LINE_SIZE / sizeof(data[0])); + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + /* + * Test with flushing/invalaidating in center of a cache line. + * The modified line shall get invalidated/flushed entirely, + * adjacent cache lines shall remain unchanged. + */ + tdata = &data[(LINE_SIZE / sizeof(data[0])) + 2]; + + for (i = 0; i < vcount; ++i) { + vdata[i] = i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + end = LINE_SIZE / sizeof(data[0]); + for (i = 0; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + i = end; + end = i + (vdata_bytes / sizeof(data[0])); + + if (write_through) { + for ( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + } else { + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == i); + } + } + i = end; + end = i + (LINE_SIZE / sizeof(data[0])); + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + /* + * Test with flushing/invalidating at the end of a cache line. + * The modified line shall get invalidated/flushed entirely, + * adjacent cache lines shall remain unchanged. + */ + tdata = &data[(LINE_SIZE / sizeof(data[0])) + ((LINE_SIZE / sizeof(data[0])) -1)]; + + for (i = 0; i < vcount; ++i) { + vdata[i] = i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + end = LINE_SIZE / sizeof(data[0]); + for (i = 0; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + i = end; + end = i + (vdata_bytes / sizeof(data[0])); + + if (write_through) { + for ( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + } else { + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == i); + } + } + i = end; + end = i + (LINE_SIZE / sizeof(data[0])); + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + /* + * Test with flushing/invalidating from the end of a cache line + * to the beginning of the next cache line. + * The modified lines shall get invalidated/flushed entirely, + * adjacent cache lines shall remain unchanged. + */ + tdata = &data[(LINE_SIZE / sizeof(data[0])) + ((LINE_SIZE / sizeof(data[0])) -1)]; + vdata_bytes = LINE_SIZE * 2; + tcount = 2; + vcount = (vdata_bytes / sizeof(data[0])) + (2 * LINE_SIZE / sizeof(data[0])); + tdata_bytes = tcount * sizeof(data[0]); + + for (i = 0; i < vcount; ++i) { + vdata[i] = i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + end = LINE_SIZE / sizeof(data[0]); + for (i = 0; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + i = end; + end = i + (vdata_bytes / sizeof(data[0])); + + if (write_through) { + for ( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + } else { + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == i); + } + } + i = end; + end = i + (LINE_SIZE / sizeof(data[0])); + for( ; i < end; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + for (i = 0; i < vcount; ++i) { + vdata[i] = ~i; + } + + rtems_cache_flush_multiple_data_lines(tdata, tdata_bytes); + rtems_cache_invalidate_multiple_data_lines(tdata, tdata_bytes); + + for (i = 0; i < vcount; ++i) { + rtems_test_assert(vdata[i] == ~i); + } + + rtems_interrupt_lock_release(&lock, &lock_context); + rtems_interrupt_lock_destroy(&lock); + + printf( + "data cache operations with misaligned addresses passed the test (%s cache detected)\n", + write_through ? "write-through" : "copy-back" + ); + } else { + printf( + "skip data cache flush and invalidate test with misaligned addresses" + " due to cache line size of zero\n" + ); + } +} + +static bool test_data_flush_and_invalidate(void) +{ + bool write_through = true; + if (rtems_cache_get_data_line_size() > 0) { + rtems_interrupt_lock lock; + rtems_interrupt_lock_context lock_context; volatile int *vdata = &data[0]; int n = 32; int i; size_t data_size = n * sizeof(data[0]); - bool write_through; printf("data cache flush and invalidate test\n"); @@ -104,6 +370,8 @@ static void test_data_flush_and_invalidate(void) " due to cache line size of zero\n" ); } + + return write_through; } static uint64_t do_some_work(void) @@ -373,9 +641,11 @@ static void test_timing(void) static void Init(rtems_task_argument arg) { + bool write_through; TEST_BEGIN(); - test_data_flush_and_invalidate(); + write_through = test_data_flush_and_invalidate(); + test_misalignment( write_through ); test_timing(); TEST_END(); diff --git a/testsuites/sptests/spcache01/spcache01.doc b/testsuites/sptests/spcache01/spcache01.doc index bbc8f25..1a56be8 100644 --- a/testsuites/sptests/spcache01/spcache01.doc +++ b/testsuites/sptests/spcache01/spcache01.doc @@ -17,3 +17,4 @@ directives: concepts: - Ensure that some cache manager functions work. + - Ensure they also work with misaligned addesses diff --git a/testsuites/sptests/spcache01/spcache01.scn b/testsuites/sptests/spcache01/spcache01.scn index 8013945..53d3e70 100644 --- a/testsuites/sptests/spcache01/spcache01.scn +++ b/testsuites/sptests/spcache01/spcache01.scn @@ -2,6 +2,8 @@ data cache flush and invalidate test data cache operations by line passed the test data cache operations by line passed the test (copy-back cache detected) +data cache flush and invalidate test with misaligned addresses +data cache operations with misaligned addresses passed the test (copy-back cache detected) data cache line size 32 bytes data cache size 262144 bytes data cache level 1 size 32768 bytes -- 1.7.10.4 _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel