[PATCH 01/12] spcache01: Add tests for misaligned cache access

Ralf Kirchner ralf.kirchner at embedded-brains.de
Tue May 27 14:43:58 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