[PATCH 1/7] spcache01: Add tests for misaligned cache access
Ralf Kirchner
ralf.kirchner at embedded-brains.de
Wed Apr 30 08:00:12 UTC 2014
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
More information about the devel
mailing list