summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFiras Sammoura <fsammoura@google.com>2023-03-10 18:59:06 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-05-15 16:30:29 +0000
commit9a21e1e51a47b5adff47990e75e62661e9b33827 (patch)
treeb3dddc0f6888b6f0582eb4d4c08b79aae1d7e460
parent888cbb55c3c1d1169bdf9f541b0fd31054ff1bc4 (diff)
downloadchrome-ec-9a21e1e51a47b5adff47990e75e62661e9b33827.tar.gz
ec: Enable unaligned access for cortex-m
Enable unaligned access for cortext-m and. Add a unit test to validate that unaligned access runs properly on both bloonchipper and dartmonkey. Add benchmarks to measure the speed gain between aligned and unaligned access. BRANCH=none BUG=b:239254184 TEST=test/run_device_tests.py -b dartmonkey -t unaligned_access TEST=test/run_device_tests.py -b bloonchipper -t unaligned_access Change-Id: I7d75433e6b7b33d7c82ad740dc85a8646d891c6a Signed-off-by: Firas Sammoura <fsammoura@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4327795 Reviewed-by: Bobby Casey <bobbycasey@google.com> Reviewed-by: Mike Frysinger <vapier@chromium.org>
-rw-r--r--board/hatch_fp/build.mk1
-rw-r--r--board/nocturne_fp/build.mk1
-rw-r--r--core/cortex-m/cpu.c4
-rw-r--r--test/build.mk1
-rwxr-xr-xtest/run_device_tests.py1
-rw-r--r--test/unaligned_access.cc157
-rw-r--r--test/unaligned_access.tasklist9
7 files changed, 172 insertions, 2 deletions
diff --git a/board/hatch_fp/build.mk b/board/hatch_fp/build.mk
index 7ded3aeb6a..5e7af56ae2 100644
--- a/board/hatch_fp/build.mk
+++ b/board/hatch_fp/build.mk
@@ -69,6 +69,7 @@ test-list-y=\
timer \
timer_dos \
tpm_seed_clear \
+ unaligned_access \
utils \
utils_str \
diff --git a/board/nocturne_fp/build.mk b/board/nocturne_fp/build.mk
index dc99c72f85..e36309c4f0 100644
--- a/board/nocturne_fp/build.mk
+++ b/board/nocturne_fp/build.mk
@@ -68,6 +68,7 @@ test-list-y=\
timer \
timer_dos \
tpm_seed_clear \
+ unaligned_access \
utils \
utils_str \
diff --git a/core/cortex-m/cpu.c b/core/cortex-m/cpu.c
index 5a882bb532..adcdb4e1a3 100644
--- a/core/cortex-m/cpu.c
+++ b/core/cortex-m/cpu.c
@@ -15,8 +15,8 @@
void cpu_init(void)
{
- /* Catch divide by 0 and unaligned access */
- CPU_NVIC_CCR |= CPU_NVIC_CCR_DIV_0_TRAP | CPU_NVIC_CCR_UNALIGN_TRAP;
+ /* Catch divide by 0 */
+ CPU_NVIC_CCR |= CPU_NVIC_CCR_DIV_0_TRAP;
/* Enable reporting of memory faults, bus faults and usage faults */
CPU_NVIC_SHCSR |= CPU_NVIC_SHCSR_MEMFAULTENA |
diff --git a/test/build.mk b/test/build.mk
index 2d2f9341a3..d948fd5f6e 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -277,6 +277,7 @@ timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
timer-y=timer.o
tpm_seed_clear-y=tpm_seed_clear.o
+unaligned_access-y=unaligned_access.o
uptime-y=uptime.o
usb_common-y=usb_common_test.o fake_battery.o
usb_pd_int-y=usb_pd_int.o
diff --git a/test/run_device_tests.py b/test/run_device_tests.py
index f385441f6d..dc454527e7 100755
--- a/test/run_device_tests.py
+++ b/test/run_device_tests.py
@@ -332,6 +332,7 @@ class AllTests:
TestConfig(test_name="timer"),
TestConfig(test_name="timer_dos"),
TestConfig(test_name="tpm_seed_clear"),
+ TestConfig(test_name="unaligned_access"),
TestConfig(test_name="utils", timeout_secs=20),
TestConfig(test_name="utils_str"),
]
diff --git a/test/unaligned_access.cc b/test/unaligned_access.cc
new file mode 100644
index 0000000000..f3dc99d432
--- /dev/null
+++ b/test/unaligned_access.cc
@@ -0,0 +1,157 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * Test if unaligned access works properly
+ */
+
+#include "common.h"
+#include "console.h"
+#include "test_util.h"
+
+extern "C" {
+#include "shared_mem.h"
+#include "timer.h"
+}
+
+#include <array>
+#include <cstdio>
+#include <cstring>
+
+test_static int test_unaligned_access()
+{
+ /* This is equivalent to {0xff, 0x09, 0x04, 0x06, 0x04, 0x06, 0x07,
+ * 0xed, 0x0a, 0x0b, 0x0d, 0x38, 0xbd, 0x57, 0x59} */
+ alignas(int32_t) constexpr std::array<int8_t, 15> test_array = {
+ -1, 9, 4, 6, 4, 6, 7, -19, 10, 11, 13, 56, -67, 87, 89
+ };
+
+ constexpr std::array<int32_t, 12> expected_results = {
+ 0x060409ff,
+ 0x04060409,
+ 0x06040604,
+ 0x07060406,
+ static_cast<int32_t>(0xed070604),
+ 0x0aed0706,
+ 0x0b0aed07,
+ 0x0d0b0aed,
+ 0x380d0b0a,
+ static_cast<int32_t>(0xbd380d0b),
+ 0x57bd380d,
+ 0x5957bd38
+ };
+
+ /* If i % 4 = 0, we have an aligned access. Otherwise, it is
+ unaligned access. */
+ for (int i = 0; i < expected_results.size(); ++i) {
+ const int32_t *test_array_ptr =
+ reinterpret_cast<const int32_t *>(test_array.data() +
+ i);
+
+ TEST_EQ(*test_array_ptr, expected_results[i], "0x%08x");
+ }
+
+ return EC_SUCCESS;
+}
+
+test_static int benchmark_unaligned_access_memcpy()
+{
+ int i;
+ timestamp_t t0, t1, t2, t3;
+ char *buf;
+ const int buf_size = 1000;
+ const int len = 400;
+ const int dest_offset = 500;
+ const int iteration = 1000;
+
+ TEST_ASSERT(shared_mem_acquire(buf_size, &buf) == EC_SUCCESS);
+
+ for (i = 0; i < len; ++i)
+ buf[i] = i & 0x7f;
+ for (i = len; i < buf_size; ++i)
+ buf[i] = 0;
+
+ t0 = get_time();
+ for (i = 0; i < iteration; ++i) {
+ memcpy(buf + dest_offset + 1, buf, len); /* unaligned */
+ }
+ t1 = get_time();
+ TEST_ASSERT_ARRAY_EQ(buf + dest_offset + 1, buf, len);
+ ccprintf(" (speed gain: %" PRId64 " ->", t1.val - t0.val);
+
+ t2 = get_time();
+ for (i = 0; i < iteration; ++i) {
+ memcpy(buf + dest_offset, buf, len); /* aligned */
+ }
+ t3 = get_time();
+ ccprintf(" %" PRId64 " us) ", t3.val - t2.val);
+ TEST_ASSERT_ARRAY_EQ(buf + dest_offset, buf, len);
+ return EC_SUCCESS;
+}
+
+test_static int benchmark_unaligned_access_array()
+{
+ timestamp_t t0, t1, t2, t3;
+ const int iteration = 1000;
+
+ alignas(int32_t) std::array<int8_t, 100> test_array_1;
+ std::array<int32_t, 20> test_array_2;
+ constexpr std::array<int32_t, 20> test_array_3 = {
+ 67305985, 134678021, 202050057, 269422093, 336794129,
+ 404166165, 471538201, 538910237, 606282273, 673654309,
+ 741026345, 808398381, 875770417, 943142453, 1010514489,
+ 1077886525, 1145258561, 1212630597, 1280002633, 1347374669
+ };
+ constexpr std::array<int32_t, 20> test_array_4 = {
+ 50462976, 117835012, 185207048, 252579084, 319951120,
+ 387323156, 454695192, 522067228, 589439264, 656811300,
+ 724183336, 791555372, 858927408, 926299444, 993671480,
+ 1061043516, 1128415552, 1195787588, 1263159624, 1330531660
+ };
+
+ for (int i = 0; i < test_array_1.size(); ++i) {
+ test_array_1[i] = static_cast<int8_t>(i);
+ }
+
+ t0 = get_time();
+ for (int t = 0; t < iteration; ++t) {
+ const int32_t *test_array_1_ptr =
+ reinterpret_cast<const int32_t *>(test_array_1.data() +
+ 1);
+
+ for (int i = 0; i < test_array_2.size(); ++i) {
+ test_array_2[i] = (*test_array_1_ptr++); /* unaligned */
+ }
+ TEST_ASSERT_ARRAY_EQ(test_array_2.data(), test_array_3.data(),
+ test_array_2.size());
+ }
+ t1 = get_time();
+ ccprintf(" (speed gain: %" PRId64 " ->", t1.val - t0.val);
+
+ t2 = get_time();
+ for (int t = 0; t < iteration; ++t) {
+ const int32_t *test_array_1_ptr =
+ reinterpret_cast<const int32_t *>(test_array_1.data());
+
+ for (int i = 0; i < test_array_2.size(); ++i) {
+ test_array_2[i] = (*test_array_1_ptr++); /* aligned */
+ }
+ TEST_ASSERT_ARRAY_EQ(test_array_2.data(), test_array_4.data(),
+ test_array_2.size());
+ }
+ t3 = get_time();
+ ccprintf(" %" PRId64 " us) ", t3.val - t2.val);
+
+ return EC_SUCCESS;
+}
+
+extern "C" void run_test(int, const char **)
+{
+ test_reset();
+ RUN_TEST(test_unaligned_access);
+ RUN_TEST(benchmark_unaligned_access_memcpy);
+ RUN_TEST(benchmark_unaligned_access_array);
+ test_print_result();
+}
diff --git a/test/unaligned_access.tasklist b/test/unaligned_access.tasklist
new file mode 100644
index 0000000000..2d177cee59
--- /dev/null
+++ b/test/unaligned_access.tasklist
@@ -0,0 +1,9 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST \ No newline at end of file