From 9a21e1e51a47b5adff47990e75e62661e9b33827 Mon Sep 17 00:00:00 2001 From: Firas Sammoura Date: Fri, 10 Mar 2023 18:59:06 +0000 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4327795 Reviewed-by: Bobby Casey Reviewed-by: Mike Frysinger --- board/hatch_fp/build.mk | 1 + board/nocturne_fp/build.mk | 1 + core/cortex-m/cpu.c | 4 +- test/build.mk | 1 + test/run_device_tests.py | 1 + test/unaligned_access.cc | 157 +++++++++++++++++++++++++++++++++++++++++ test/unaligned_access.tasklist | 9 +++ 7 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 test/unaligned_access.cc create mode 100644 test/unaligned_access.tasklist 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 +#include +#include + +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 test_array = { + -1, 9, 4, 6, 4, 6, 7, -19, 10, 11, 13, 56, -67, 87, 89 + }; + + constexpr std::array expected_results = { + 0x060409ff, + 0x04060409, + 0x06040604, + 0x07060406, + static_cast(0xed070604), + 0x0aed0706, + 0x0b0aed07, + 0x0d0b0aed, + 0x380d0b0a, + static_cast(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(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 test_array_1; + std::array test_array_2; + constexpr std::array 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 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(i); + } + + t0 = get_time(); + for (int t = 0; t < iteration; ++t) { + const int32_t *test_array_1_ptr = + reinterpret_cast(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(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 -- cgit v1.2.1