From 9332d2ccd22738eb11b01bcc6c24a68cdbebc81f Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Sun, 17 Aug 2025 11:52:05 +0700 Subject: [PATCH] fix(newlib): fix CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS for c2/c3/c6/h2/h21 PMP configurations for load and store addresses may have different permissions (e.g., "R" vs. "RW"). Due to the timing alignment of internal signals, the address permission check may be incorrectly applied during the second part of a misaligned access transaction. As a workaround, insert two instructions (e.g. ADDI/NOP) between accessing to different memory regions. This spacing avoids the false permission check caused by signal timing overlap. --- components/esp_rom/CMakeLists.txt | 2 +- .../test_apps/newlib/main/CMakeLists.txt | 7 +- .../newlib/main/test_misaligned_access.c | 2 +- .../main/test_misaligned_mem_performance.c | 108 ------------------ .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c2/include/soc/soc_caps.h | 2 + .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c3/include/soc/soc_caps.h | 2 + .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/soc_caps.h | 2 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h2/include/soc/soc_caps.h | 2 + .../esp32h21/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h21/include/soc/soc_caps.h | 2 + 14 files changed, 33 insertions(+), 116 deletions(-) delete mode 100644 components/newlib/test_apps/newlib/main/test_misaligned_mem_performance.c diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index b120d67bf74..ccf89f1df41 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -148,7 +148,7 @@ if(ESP_TEE_BUILD) rom_linker_script("newlib-nano") endif() rom_linker_script("libc") - if(CONFIG_ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY) + if(CONFIG_ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY) # TODO IDF-13852: use optimized memcpy for TEE ? rom_linker_script("libc-suboptimal_for_misaligned_mem") endif() endif() diff --git a/components/newlib/test_apps/newlib/main/CMakeLists.txt b/components/newlib/test_apps/newlib/main/CMakeLists.txt index d91fc695dc7..474b1050f9c 100644 --- a/components/newlib/test_apps/newlib/main/CMakeLists.txt +++ b/components/newlib/test_apps/newlib/main/CMakeLists.txt @@ -18,14 +18,9 @@ if(CONFIG_LIBC_NEWLIB) endif() if(CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS) - list(APPEND srcs "test_misaligned_mem_performance.c") + list(APPEND srcs "test_misaligned_access.c") endif() idf_component_register(SRCS "${srcs}" PRIV_REQUIRES unity vfs cmock driver esp_timer spi_flash test_utils pthread esp_psram WHOLE_ARCHIVE) - -if(CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS) - set_source_files_properties(test_misaligned_mem_performance.c - PROPERTIES COMPILE_FLAGS "-Wno-incompatible-pointer-types -Wno-strict-prototypes") -endif() diff --git a/components/newlib/test_apps/newlib/main/test_misaligned_access.c b/components/newlib/test_apps/newlib/main/test_misaligned_access.c index 0ee1f0f7b3f..6c39986a8c0 100644 --- a/components/newlib/test_apps/newlib/main/test_misaligned_access.c +++ b/components/newlib/test_apps/newlib/main/test_misaligned_access.c @@ -130,7 +130,7 @@ TEST_CASE("mem functions in IRAM", "[misaligned_mem]") TEST_ASSERT_TRUE(fn_in_ram(strncmp)); } -#if CONFIG_ESP_SYSTEM_MEMPROT_PMP +#if CONFIG_IDF_TARGET_ARCH_RISCV TEST_CASE("access across different PMP regions", "[misaligned_mem]") { /* diff --git a/components/newlib/test_apps/newlib/main/test_misaligned_mem_performance.c b/components/newlib/test_apps/newlib/main/test_misaligned_mem_performance.c deleted file mode 100644 index ebff7da4ebb..00000000000 --- a/components/newlib/test_apps/newlib/main/test_misaligned_mem_performance.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include -#include -#include "esp_heap_caps.h" -#include "hal/cpu_ll.h" -#include "unity.h" - -#define MAX_MEMTEST_SIZE 4096 - -uint32_t test_function_dest_src_size(void (*foo)(), bool pass_size) -{ - uint32_t ccount1, ccount2; - char* test_des = heap_caps_aligned_alloc(32, MAX_MEMTEST_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - char* test_src = heap_caps_aligned_alloc(32, MAX_MEMTEST_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - - TEST_ASSERT_NOT_NULL(test_des); - TEST_ASSERT_NOT_NULL(test_src); - - /* Prepare arrays for X-cmp functions to make the algorithm go through whole buffers. */ - memset(test_src, 'a', MAX_MEMTEST_SIZE); - test_src[MAX_MEMTEST_SIZE - 1] = 0; - memset(test_des, 'a', MAX_MEMTEST_SIZE); - test_des[MAX_MEMTEST_SIZE - 1] = 'b'; - test_des[MAX_MEMTEST_SIZE - 1] = 0; - - ccount1 = esp_cpu_get_cycle_count(); - if (pass_size) { - foo(test_des + 1, test_src + 2, MAX_MEMTEST_SIZE - 2); - } else { - foo(test_des + 1, test_src + 2); - } - ccount2 = esp_cpu_get_cycle_count(); - - heap_caps_free(test_des); - heap_caps_free(test_src); - - return ccount2 - ccount1; -} - -TEST_CASE("memcpy", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(memcpy, true); - /* esp32c2: 4128 cycles instead 28676. */ - TEST_ASSERT_LESS_THAN(10000, ccount); -} - -TEST_CASE("memcmp", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(memcmp, true); - /* esp32c2: 14259 cycles instead 49147. */ - TEST_ASSERT_LESS_THAN(20000, ccount); -} - -TEST_CASE("memmove", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(memmove, true); - /* esp32c2: 8086 cycles instead 33896. */ - TEST_ASSERT_LESS_THAN(15000, ccount); -} - -TEST_CASE("memmove - overlapping", "[misaligned_mem]") -{ - uint32_t ccount1, ccount2; - char* buf = heap_caps_aligned_alloc(32, MAX_MEMTEST_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - - TEST_ASSERT_NOT_NULL(buf); - - ccount1 = esp_cpu_get_cycle_count(); - memmove(buf + 5, buf + 2, MAX_MEMTEST_SIZE - 5); - ccount2 = esp_cpu_get_cycle_count(); - - heap_caps_free(buf); - - /* esp32c2: 11503 cycles instead 45024. */ - TEST_ASSERT_LESS_THAN(20000, ccount2 - ccount1); -} - -TEST_CASE("strcpy", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(strcpy, false); - /* esp32c2: 17313 cycles instead 32771. */ - TEST_ASSERT_LESS_THAN(22000, ccount); -} - -TEST_CASE("strcmp", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(strcmp, false); - /* esp32c2: 13191 cycles instead 32775. */ - TEST_ASSERT_LESS_THAN(20000, ccount); -} - -TEST_CASE("strncpy", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(strncpy, true); - /* esp32c2: 21475 cycles instead 36859. */ - TEST_ASSERT_LESS_THAN(25000, ccount); -} - -TEST_CASE("strncmp", "[misaligned_mem]") -{ - uint32_t ccount = test_function_dest_src_size(strncmp, true); - /* esp32c2: 24369 cycles instead 49141. */ - TEST_ASSERT_LESS_THAN(30000, ccount); -} diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 3c14de47fbc..96d7a98f0d6 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -263,6 +263,10 @@ config SOC_CPU_IDRAM_SPLIT_USING_PMP bool default y +config SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE + bool + default y + config SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK bool default y diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 81bc6fae65e..3976848ae2d 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -106,6 +106,8 @@ #define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 // bytes #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 +// DIG-694: misaligned access across PMP regions must be spaced at least by two instructions +#define SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE 1 /*-------------------------- ECC CAPS --------------------------*/ #define SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK 1 // C2 ECC peripheral has a bug in ECC point verification, if value of K is zero the verification fails diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 48929546719..11e0e7014d8 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -351,6 +351,10 @@ config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE hex default 0x80000000 +config SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE + bool + default y + config SOC_DS_SIGNATURE_MAX_BIT_LEN int default 3072 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index aef54ff245f..57860acd94e 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -137,6 +137,8 @@ #define SOC_CPU_BREAKPOINTS_NUM 8 #define SOC_CPU_WATCHPOINTS_NUM 8 #define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 // bytes +// DIG-694: misaligned access across PMP regions must be spaced at least by two instructions +#define SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE 1 /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 0134da89cb9..d0f2123b364 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -431,6 +431,10 @@ config SOC_CPU_PMP_REGION_GRANULARITY int default 4 +config SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE + bool + default y + config SOC_DS_SIGNATURE_MAX_BIT_LEN int default 3072 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 1f6b558c5ae..4ad3d1e693a 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -158,6 +158,8 @@ #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 #define SOC_CPU_PMP_REGION_GRANULARITY 4 +// DIG-694: misaligned access across PMP regions must be spaced at least by two instructions +#define SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE 1 // TODO: IDF-5360 (Copy from esp32c3, need check) /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 159e408b275..b8d9ffcd608 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -427,6 +427,10 @@ config SOC_CPU_PMP_REGION_GRANULARITY int default 4 +config SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE + bool + default y + config SOC_MMU_PAGE_SIZE_CONFIGURABLE bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 334a3543777..311cb8c2730 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -174,6 +174,8 @@ #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 #define SOC_CPU_PMP_REGION_GRANULARITY 4 +// DIG-694: misaligned access across PMP regions must be spaced at least by two instructions +#define SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE 1 /*-------------------------- MMU CAPS ----------------------------------------*/ #define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1) diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index e763e63460f..04c204ae7fb 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -255,6 +255,10 @@ config SOC_CPU_PMP_REGION_GRANULARITY int default 4 +config SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE + bool + default y + config SOC_MMU_PERIPH_NUM int default 1 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 53983e8a498..d630b35ea12 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -159,6 +159,8 @@ #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 #define SOC_CPU_PMP_REGION_GRANULARITY 4 +// DIG-694: misaligned access across PMP regions must be spaced at least by two instructions +#define SOC_CPU_MISALIGNED_ACCESS_ON_PMP_MISMATCH_ISSUE 1 /*-------------------------- MMU CAPS ----------------------------------------*/ // #define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1)