From 339fcbf14d9e10f38b392c5c8bd82e427a138b31 Mon Sep 17 00:00:00 2001 From: Martin Vychodil Date: Wed, 22 Dec 2021 07:25:59 +0100 Subject: [PATCH] System/Security: Memprot API unified (ESP32S3) Unified Memory protection API for all PMS-aware chips - ESP32S3 port --- .gitlab/ci/target-test.yml | 6 + components/esp_common/src/esp_err_to_name.c | 3 + .../esp_hw_support/include/esp_memprot.h | 18 +- .../esp_hw_support/include/esp_memprot_err.h | 3 +- .../esp_private/esp_memprot_internal.h | 48 +- .../include/soc/esp32c3/soc_memprot_types.h | 2 +- .../include/soc/esp32h2/soc_memprot_types.h | 4 +- .../include/soc/esp32s2/soc_memprot_types.h | 2 +- .../include/soc/esp32s3/soc_memprot_types.h | 113 +- .../port/esp32c3/CMakeLists.txt | 9 +- .../esp_hw_support/port/esp32c3/esp_memprot.c | 122 +- .../port/esp32h2/CMakeLists.txt | 9 +- .../esp_hw_support/port/esp32h2/esp_memprot.c | 10 +- .../port/esp32s3/CMakeLists.txt | 4 + .../esp_hw_support/port/esp32s3/esp_memprot.c | 1121 +++++++- components/esp_system/Kconfig | 2 +- components/esp_system/ld/esp32s3/memory.ld.in | 9 +- .../esp_system/ld/esp32s3/sections.ld.in | 23 +- .../esp_system/port/arch/riscv/panic_arch.c | 18 +- .../hal/esp32s3/include/hal/memprot_ll.h | 2255 ++++++++++++----- components/hal/include/hal/memprot_types.h | 21 +- .../soc/esp32c3/include/soc/memprot_defs.h | 8 - .../soc/esp32s3/include/soc/memprot_defs.h | 51 + components/soc/esp32s3/include/soc/soc.h | 3 +- tools/ci/check_copyright_ignore.txt | 1 - tools/test_apps/system/memprot/CMakeLists.txt | 7 +- tools/test_apps/system/memprot/README.md | 4 +- tools/test_apps/system/memprot/app_test.py | 31 +- .../system/memprot/main/CMakeLists.txt | 3 + .../memprot/main/esp32c3/test_memprot_main.c | 70 +- .../memprot/main/esp32s3/test_memprot_main.c | 691 +++++ .../system/memprot/main/esp32s3/test_panic.c | 78 + 32 files changed, 3875 insertions(+), 874 deletions(-) create mode 100644 components/soc/esp32s3/include/soc/memprot_defs.h create mode 100644 tools/test_apps/system/memprot/main/esp32s3/test_memprot_main.c create mode 100644 tools/test_apps/system/memprot/main/esp32s3/test_panic.c diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index d22a2b563c..9d1cdbed10 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -687,6 +687,12 @@ test_app_test_005: - ESP32C3 - Example_GENERIC +test_app_test_006: + extends: .test_app_esp32s3_template + tags: + - ESP32S3 + - Example_GENERIC + test_app_test_esp32_generic: extends: .test_app_esp32_template tags: diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index 10151ac2c6..eb3e810e16 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -799,6 +799,9 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_MEMPROT_AREA_INVALID ERR_TBL_IT(ESP_ERR_MEMPROT_AREA_INVALID), /* 53255 0xd007 */ +# endif +# ifdef ESP_ERR_MEMPROT_CPUID_INVALID + ERR_TBL_IT(ESP_ERR_MEMPROT_CPUID_INVALID), /* 53256 0xd008 */ # endif // components/tcp_transport/include/esp_transport.h # ifdef ESP_ERR_TCP_TRANSPORT_BASE diff --git a/components/esp_hw_support/include/esp_memprot.h b/components/esp_hw_support/include/esp_memprot.h index a6bc289145..02daf9c649 100644 --- a/components/esp_hw_support/include/esp_memprot.h +++ b/components/esp_hw_support/include/esp_memprot.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,9 @@ #pragma once +#include "sdkconfig.h" +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST + #include #include #include "esp_err.h" @@ -22,6 +25,7 @@ extern "C" { #endif +#define DEFAULT_CPU_NUM -1 #define ESP_MEMPROT_ERR_CHECK(retval, fnc) if ((retval=fnc) != ESP_OK) { return retval; } /** @@ -47,7 +51,7 @@ typedef struct { * ESP_ERR_INVALID_ARG on passing invalid pointer * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core); +esp_err_t esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, const int core); /** * @brief Checks whether any of the PMS settings is locked @@ -100,7 +104,7 @@ esp_err_t esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr); * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_INVALID_ARG on invalid fault_addr pointer */ -esp_err_t esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core); +esp_err_t esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, const int core); /** * @brief Returns PMS World identifier of the code causing the violation interrupt @@ -116,7 +120,7 @@ esp_err_t esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **faul * ESP_ERR_INVALID_ARG on passing invalid pointer(s) * ESP_ERR_MEMPROT_WORLD_INVALID on invalid World identifier fetched from the register */ -esp_err_t esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core); +esp_err_t esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, const int core); /** * @brief Returns an operation type which caused the violation interrupt @@ -132,7 +136,7 @@ esp_err_t esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_ * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_INVALID_ARG on invalid oper pointer */ -esp_err_t esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core); +esp_err_t esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, const int core); /** * @brief Checks whether given memory type supports byte-enables info @@ -158,7 +162,7 @@ bool esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type); * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_INVALID_ARGUMENT on invalid byte_en pointer */ -esp_err_t esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core); +esp_err_t esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, const int core); /** * @brief Convenient routine for setting the PMS defaults @@ -192,3 +196,5 @@ esp_err_t esp_mprot_dump_configuration(char **dump_info_string); #ifdef __cplusplus } #endif + +#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST diff --git a/components/esp_hw_support/include/esp_memprot_err.h b/components/esp_hw_support/include/esp_memprot_err.h index 5556d2c889..ac58a30bf6 100644 --- a/components/esp_hw_support/include/esp_memprot_err.h +++ b/components/esp_hw_support/include/esp_memprot_err.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ extern "C" { #define ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID (ESP_ERR_MEMPROT_BASE + 5) /**< Required unified-management block is not valid */ #define ESP_ERR_MEMPROT_WORLD_INVALID (ESP_ERR_MEMPROT_BASE + 6) /**< Required World identifier is not valid */ #define ESP_ERR_MEMPROT_AREA_INVALID (ESP_ERR_MEMPROT_BASE + 7) /**< Required Area identifier is not valid */ +#define ESP_ERR_MEMPROT_CPUID_INVALID (ESP_ERR_MEMPROT_BASE + 8) /**< Required CPU/Core identifier is not valid */ #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/esp_private/esp_memprot_internal.h b/components/esp_hw_support/include/esp_private/esp_memprot_internal.h index 214f1dd68f..f7a7349fb2 100644 --- a/components/esp_hw_support/include/esp_private/esp_memprot_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_memprot_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,7 @@ const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type); * @param mem_type memory type * @param line_type split address type * @param line_addr target address from a memory range relevant to given line_addr + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type @@ -55,7 +56,7 @@ const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type); * ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE on splitting line out of given memory-type range * ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED on splitting line not aligned to PMS-required boundaries */ -esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr); +esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr, const int core); /** * @brief Gets PMS splitting address for given split_addr type @@ -65,13 +66,14 @@ esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mpr * @param mem_type memory type * @param line_type Split line type (see esp_mprot_split_addr_t enum) * @param[out] line_addr Split line address from the configuration register + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_INVALID_ARG on line_addr is pointer * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID on invalid line_type */ -esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr); +esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr, const int core); /** * @brief Returns default main I/D splitting address for given Memory type @@ -90,69 +92,75 @@ esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, * Locks can be unlocked only by digital system reset * * @param mem_type memory type + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type); +esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type, const int core); /** * @brief Gets a lock status for the splitting address configuration of given Memory type * * @param mem_type memory type * @param[out] locked mem_type related lock status + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_INVALID_ARGUMENT on invalid locked pointer * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked); +esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core); /** * @brief Sets a lock for PMS Area settings of required Memory type * Locks can be unlocked only by digital system reset * * @param mem_type memory type + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type); +esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type, const int core); /** * @brief Gets a lock status for PMS Area settings of required Memory type * * @param mem_type memory type * @param[out] locked mem_type related lock status + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_INVALID_ARGUMENT on invalid locked pointer */ -esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked); +esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core); /** * @brief Sets permissions for given PMS Area * * @param area_type PMS area type * @param flags combination of MEMPROT_OP_* defines + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags); +esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags, const int core); /** * @brief Gets current permissions for given PMS Area * * @param area_type PMS area type * @param[out] flags combination of MEMPROT_OP_* defines + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_INVALID_ARG on invalid flags pointer */ -esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags); +esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags, const int core); /** * @brief Sets a lock for PMS interrupt monitor settings of required Memory type @@ -160,34 +168,50 @@ esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t * Locks can be unlocked only by digital system reset * * @param mem_type memory type (see esp_mprot_mem_t enum) + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type); +esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type, const int core); /** * @brief Gets a lock status for PMS interrupt monitor settings of required Memory type * * @param mem_type memory type * @param[out] locked mem_type related lock status + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type * ESP_ERR_INVALID_ARG on invalid locked pointer */ -esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked); +esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core); /** * @brief Enable PMS violation interrupt monitoring of required Memory type * * @param mem_type memory type * @param enable enable/disable violation interrupt monitoring + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems * * @return ESP_OK on success * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type */ -esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable); +esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable, const int core); + +/** + * @brief Gets PMS violation-monitoring-enabled flag for required Memory type + * + * @param mem_type memory type + * @param[out] enabled violation interrupt monitoring enable flag + * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on invalid enabled pointer + * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type + */ +esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool* enabled, const int core); #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h b/components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h index 318c610961..9afb6402f5 100644 --- a/components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h +++ b/components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h b/components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h index 3048088eba..9b84d1471d 100644 --- a/components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h +++ b/components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,7 +54,7 @@ typedef struct { uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */ } esp_memp_config_t; -#define ESP_MEMPROT_DEFAULT_CONFIG() {\ +#define ESP_MEMPROT_DEFAULT_CONFIG() { \ .invoke_panic_handler = true, \ .lock_feature = true, \ .split_addr = NULL, \ diff --git a/components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h b/components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h index f17e214313..61f5f89071 100644 --- a/components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h +++ b/components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h b/components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h index 06dde33ffa..6a800eeb12 100644 --- a/components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h +++ b/components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +12,8 @@ #include #include +#include "soc/soc.h" +#include "freertos/FreeRTOSConfig.h" #ifdef __cplusplus extern "C" { @@ -22,8 +24,12 @@ extern "C" { */ typedef enum { MEMPROT_TYPE_NONE = 0x00000000, + MEMPROT_TYPE_IRAM0_SRAM = 0x00000001, + MEMPROT_TYPE_DRAM0_SRAM = 0x00000002, + MEMPROT_TYPE_IRAM0_RTCFAST = 0x00000004, MEMPROT_TYPE_ALL = 0x7FFFFFFF, - MEMPROT_TYPE_INVALID = 0x80000000 + MEMPROT_TYPE_INVALID = 0x80000000, + MEMPROT_TYPE_IRAM0_ANY = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_IRAM0_RTCFAST } esp_mprot_mem_t; /** @@ -31,8 +37,14 @@ typedef enum { */ typedef enum { MEMPROT_SPLIT_ADDR_NONE = 0x00000000, + MEMPROT_SPLIT_ADDR_IRAM0_DRAM0 = 0x00000001, + MEMPROT_SPLIT_ADDR_IRAM0_LINE_0 = 0x00000002, + MEMPROT_SPLIT_ADDR_IRAM0_LINE_1 = 0x00000004, + MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0 = 0x00000008, + MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1 = 0x00000010, MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF, - MEMPROT_SPLIT_ADDR_INVALID = 0x80000000 + MEMPROT_SPLIT_ADDR_INVALID = 0x80000000, + MEMPROT_SPLIT_ADDR_MAIN = MEMPROT_SPLIT_ADDR_IRAM0_DRAM0 } esp_mprot_split_addr_t; /** @@ -40,6 +52,16 @@ typedef enum { */ typedef enum { MEMPROT_PMS_AREA_NONE = 0x00000000, + MEMPROT_PMS_AREA_IRAM0_0 = 0x00000001, + MEMPROT_PMS_AREA_IRAM0_1 = 0x00000002, + MEMPROT_PMS_AREA_IRAM0_2 = 0x00000004, + MEMPROT_PMS_AREA_IRAM0_3 = 0x00000008, + MEMPROT_PMS_AREA_DRAM0_0 = 0x00000010, + MEMPROT_PMS_AREA_DRAM0_1 = 0x00000020, + MEMPROT_PMS_AREA_DRAM0_2 = 0x00000040, + MEMPROT_PMS_AREA_DRAM0_3 = 0x00000080, + MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO = 0x00000100, + MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI = 0x00000200, MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF, MEMPROT_PMS_AREA_INVALID = 0x80000000 } esp_mprot_pms_area_t; @@ -48,20 +70,35 @@ typedef enum { * @brief Memory protection configuration */ typedef struct { - bool invoke_panic_handler; /*!< Register PMS violation interrupt for panic-handling */ - bool lock_feature; /*!< Lock all PMS settings */ - void *split_addr; /*!< Main I/D splitting address */ - uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */ - int target_cpu[]; /*!< Array of CPU/core IDs required to receive given PMS protection */ + bool invoke_panic_handler; /*!< Register PMS violation interrupt for panic-handling */ + bool lock_feature; /*!< Lock all PMS settings */ + void *split_addr; /*!< Main I/D splitting address */ + uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */ + size_t target_cpu_count; /*!< Real CPU/core count (max 2) */ + int target_cpu[portNUM_PROCESSORS]; /*!< Array of CPU/core IDs required to receive given PMS protection */ } esp_memp_config_t; +#if portNUM_PROCESSORS > 1 #define ESP_MEMPROT_DEFAULT_CONFIG() { \ .invoke_panic_handler = true, \ .lock_feature = true, \ .split_addr = NULL, \ - .mem_type_mask = MEMPROT_TYPE_ALL,\ - .target_cpu[] = {PRO_CPU_NUM, APP_CPU_NUM} \ + /* .mem_type_mask = MEMPROT_TYPE_ALL, \ - unless IDF-5208 gets merged */ \ + .mem_type_mask = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_DRAM0_SRAM, \ + .target_cpu_count = portNUM_PROCESSORS, \ + .target_cpu = {PRO_CPU_NUM, APP_CPU_NUM} \ } +#else +#define ESP_MEMPROT_DEFAULT_CONFIG() { \ + .invoke_panic_handler = true, \ + .lock_feature = true, \ + .split_addr = NULL, \ + /* .mem_type_mask = MEMPROT_TYPE_ALL, \ - unless IDF-5208 gets merged */ \ + .mem_type_mask = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_DRAM0_SRAM, \ + .target_cpu_count = portNUM_PROCESSORS, \ + .target_cpu = {PRO_CPU_NUM} \ +} +#endif /** * @brief Converts Memory protection type to string @@ -72,11 +109,19 @@ static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_ty { switch (mem_type) { case MEMPROT_TYPE_NONE: - return "MEMPROT_TYPE_NONE"; + return "NONE"; + case MEMPROT_TYPE_IRAM0_SRAM: + return "IRAM0_SRAM"; + case MEMPROT_TYPE_DRAM0_SRAM: + return "DRAM0_SRAM"; + case MEMPROT_TYPE_IRAM0_RTCFAST: + return "IRAM0_RTCFAST"; + case MEMPROT_TYPE_IRAM0_ANY: + return "IRAM0_ANY"; case MEMPROT_TYPE_ALL: - return "MEMPROT_TYPE_ALL"; + return "ALL"; default: - return "MEMPROT_TYPE_INVALID"; + return "INVALID"; } } @@ -89,11 +134,21 @@ static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr { switch (line_type) { case MEMPROT_SPLIT_ADDR_NONE: - return "MEMPROT_SPLIT_ADDR_NONE"; + return "SPLIT_ADDR_NONE"; + case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0: + return "SPLIT_ADDR_IRAM0_DRAM0"; + case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0: + return "SPLIT_ADDR_IRAM0_LINE_0"; + case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1: + return "SPLIT_ADDR_IRAM0_LINE_1"; + case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0: + return "SPLIT_ADDR_DRAM0_DMA_LINE_0"; + case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1: + return "SPLIT_ADDR_DRAM0_DMA_LINE_1"; case MEMPROT_SPLIT_ADDR_ALL: - return "MEMPROT_SPLIT_ADDR_ALL"; + return "SPLIT_ADDR_ALL"; default: - return "MEMPROT_SPLIT_ADDR_INVALID"; + return "SPLIT_ADDR_INVALID"; } } @@ -106,11 +161,31 @@ static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t a { switch (area_type) { case MEMPROT_PMS_AREA_NONE: - return "MEMPROT_PMS_AREA_NONE"; + return "PMS_AREA_NONE"; + case MEMPROT_PMS_AREA_IRAM0_0: + return "PMS_AREA_IRAM0_0"; + case MEMPROT_PMS_AREA_IRAM0_1: + return "PMS_AREA_IRAM0_1"; + case MEMPROT_PMS_AREA_IRAM0_2: + return "PMS_AREA_IRAM0_2"; + case MEMPROT_PMS_AREA_IRAM0_3: + return "PMS_AREA_IRAM0_3"; + case MEMPROT_PMS_AREA_DRAM0_0: + return "PMS_AREA_DRAM0_0"; + case MEMPROT_PMS_AREA_DRAM0_1: + return "PMS_AREA_DRAM0_1"; + case MEMPROT_PMS_AREA_DRAM0_2: + return "PMS_AREA_DRAM0_2"; + case MEMPROT_PMS_AREA_DRAM0_3: + return "PMS_AREA_DRAM0_3"; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO: + return "PMS_AREA_IRAM0_RTCFAST_LO"; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI: + return "PMS_AREA_IRAM0_RTCFAST_HI"; case MEMPROT_PMS_AREA_ALL: - return "MEMPROT_PMS_AREA_ALL"; + return "PMS_AREA_ALL"; default: - return "MEMPROT_PMS_AREA_INVALID"; + return "PMS_AREA_INVALID"; } } diff --git a/components/esp_hw_support/port/esp32c3/CMakeLists.txt b/components/esp_hw_support/port/esp32c3/CMakeLists.txt index a748f01ed0..d489fa43dd 100644 --- a/components/esp_hw_support/port/esp32c3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c3/CMakeLists.txt @@ -11,9 +11,12 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "../async_memcpy_impl_gdma.c" "esp_hmac.c" "esp_crypto_lock.c" - "esp_ds.c" - "esp_memprot.c" - "../esp_memprot_conv.c") + "esp_ds.c") + + if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE) + list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c") + endif() + endif() add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") diff --git a/components/esp_hw_support/port/esp32c3/esp_memprot.c b/components/esp_hw_support/port/esp32c3/esp_memprot.c index 762d661706..1566c100a0 100644 --- a/components/esp_hw_support/port/esp32c3/esp_memprot.c +++ b/components/esp_hw_support/port/esp32c3/esp_memprot.c @@ -36,7 +36,7 @@ static void *esp_memprot_rtcfast_get_min_split_addr(void) return &_rtc_text_end; } -esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr) +esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr, const int core __attribute__((unused))) { switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: @@ -72,7 +72,7 @@ esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mpr } } -esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr) +esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr, const int core __attribute__((unused))) { if (line_addr == NULL) { return ESP_ERR_INVALID_ARG; @@ -142,7 +142,7 @@ esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, return ESP_OK; } -esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type) +esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: @@ -160,7 +160,7 @@ esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type) return ESP_OK; } -esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked) +esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core __attribute__((unused))) { if (locked == NULL) { return ESP_ERR_INVALID_ARG; @@ -181,7 +181,7 @@ esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *lo return ESP_OK; } -esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type) +esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: @@ -201,7 +201,7 @@ esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type) return ESP_OK; } -esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked) +esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core __attribute__((unused))) { if (locked == NULL) { return ESP_ERR_INVALID_ARG; @@ -224,7 +224,7 @@ esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked) return ESP_OK; } -esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags) +esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags, const int core __attribute__((unused))) { bool r = flags & MEMPROT_OP_READ; bool w = flags & MEMPROT_OP_WRITE; @@ -268,7 +268,7 @@ esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uin return ESP_OK; } -esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags) +esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags, const int core __attribute__((unused))) { if (flags == NULL) { return ESP_ERR_INVALID_ARG; @@ -327,7 +327,7 @@ esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t return ESP_OK; } -esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type) +esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: @@ -346,7 +346,7 @@ esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type) return ESP_OK; } -esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked) +esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core __attribute__((unused))) { if (locked == NULL) { return ESP_ERR_INVALID_ARG; @@ -369,7 +369,7 @@ esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locke return ESP_OK; } -esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable) +esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable, const int core __attribute__((unused))) { switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: @@ -388,7 +388,7 @@ esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool en return ESP_OK; } -esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled) +esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled, const int core __attribute__((unused))) { if (enabled == NULL) { return ESP_ERR_INVALID_ARG; @@ -411,7 +411,7 @@ esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: @@ -463,19 +463,19 @@ esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked) bool lock_on = false; esp_err_t res; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) *locked |= lock_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) *locked |= lock_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) *locked |= lock_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) *locked |= lock_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) *locked |= lock_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on)); + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)); *locked |= lock_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on)); + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on, DEFAULT_CPU_NUM)); *locked |= lock_on; return ESP_OK; @@ -490,17 +490,17 @@ esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled) bool ena_on = false; esp_err_t res; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on, DEFAULT_CPU_NUM)) *enabled |= ena_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on, DEFAULT_CPU_NUM)) *enabled |= ena_on; - ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on)) + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on, DEFAULT_CPU_NUM)) *enabled |= ena_on; return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, const int core __attribute__((unused))) { if (fault_addr == NULL) { return ESP_ERR_INVALID_ARG; @@ -523,7 +523,7 @@ esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, v return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, const int core __attribute__((unused))) { if (world == NULL) { return ESP_ERR_INVALID_ARG; @@ -553,7 +553,7 @@ esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, const int core __attribute__((unused))) { if (oper == NULL) { return ESP_ERR_INVALID_ARG; @@ -592,7 +592,7 @@ bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type) return mem_type == MEMPROT_TYPE_DRAM0_SRAM; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, const int core __attribute__((unused))) { if (byte_en == NULL) { return ESP_ERR_INVALID_ARG; @@ -661,13 +661,13 @@ esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config) //disable protection (must be unlocked) if (use_iram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false, DEFAULT_CPU_NUM)) } if (use_dram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false, DEFAULT_CPU_NUM)) } if (use_rtcfast) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false, DEFAULT_CPU_NUM)) } //panic handling @@ -689,64 +689,64 @@ esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config) ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_SRAM, &line_addr)) } - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_1, line_addr)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_0, line_addr)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_DRAM0, line_addr)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)))) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)))) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_1, line_addr, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_0, line_addr, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_DRAM0, line_addr, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)), DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)), DEFAULT_CPU_NUM)) //set permissions if (use_iram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, MEMPROT_OP_READ | MEMPROT_OP_EXEC)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_EXEC)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_EXEC)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, MEMPROT_OP_NONE)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, MEMPROT_OP_NONE, DEFAULT_CPU_NUM)) } if (use_dram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, MEMPROT_OP_NONE )) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_WRITE)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_WRITE)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, MEMPROT_OP_READ | MEMPROT_OP_WRITE)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, MEMPROT_OP_NONE, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) } if (use_rtcfast) { //RTCFAST split-line cannot be set manually - always use default void *rtc_fast_line; ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, &rtc_fast_line)); - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, MEMPROT_SPLIT_ADDR_MAIN, rtc_fast_line)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, MEMPROT_OP_READ | MEMPROT_OP_EXEC)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, MEMPROT_OP_READ | MEMPROT_OP_WRITE)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, MEMPROT_SPLIT_ADDR_MAIN, rtc_fast_line, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) } //reenable the protection if (use_iram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, true)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, true, DEFAULT_CPU_NUM)) } if (use_dram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, true)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, true, DEFAULT_CPU_NUM)) } if (use_rtcfast) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, true)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, true, DEFAULT_CPU_NUM)) } //lock if required if (memp_config->lock_feature) { if (use_iram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_SRAM)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM)) } if (use_dram0) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_DRAM0_SRAM)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM)) } if (use_rtcfast) { - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_RTCFAST)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST)) - ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_RTCFAST, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, DEFAULT_CPU_NUM)) } } diff --git a/components/esp_hw_support/port/esp32h2/CMakeLists.txt b/components/esp_hw_support/port/esp32h2/CMakeLists.txt index a748f01ed0..d489fa43dd 100644 --- a/components/esp_hw_support/port/esp32h2/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h2/CMakeLists.txt @@ -11,9 +11,12 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "../async_memcpy_impl_gdma.c" "esp_hmac.c" "esp_crypto_lock.c" - "esp_ds.c" - "esp_memprot.c" - "../esp_memprot_conv.c") + "esp_ds.c") + + if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE) + list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c") + endif() + endif() add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") diff --git a/components/esp_hw_support/port/esp32h2/esp_memprot.c b/components/esp_hw_support/port/esp32h2/esp_memprot.c index df6f58e79e..508ed8c36c 100644 --- a/components/esp_hw_support/port/esp32h2/esp_memprot.c +++ b/components/esp_hw_support/port/esp32h2/esp_memprot.c @@ -121,7 +121,7 @@ esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { return ESP_OK; } @@ -160,7 +160,7 @@ esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled) return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, const int core __attribute__((unused))) { if (fault_addr == NULL) { return ESP_ERR_INVALID_ARG; @@ -171,7 +171,7 @@ esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, v return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, const int core __attribute__((unused))) { if (world == NULL) { return ESP_ERR_INVALID_ARG; @@ -182,7 +182,7 @@ esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, const int core __attribute__((unused))) { if (oper == NULL) { return ESP_ERR_INVALID_ARG; @@ -198,7 +198,7 @@ bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type) return false; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, const int core __attribute__((unused))) { if (byte_en == NULL) { return ESP_ERR_INVALID_ARG; diff --git a/components/esp_hw_support/port/esp32s3/CMakeLists.txt b/components/esp_hw_support/port/esp32s3/CMakeLists.txt index 5e7926f7f0..d093c60b9d 100644 --- a/components/esp_hw_support/port/esp32s3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32s3/CMakeLists.txt @@ -16,6 +16,10 @@ if(NOT BOOTLOADER_BUILD) "esp_hmac.c" "esp_ds.c" "esp_crypto_lock.c") + + if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE) + list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c") + endif() endif() add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") diff --git a/components/esp_hw_support/port/esp32s3/esp_memprot.c b/components/esp_hw_support/port/esp32s3/esp_memprot.c index df6f58e79e..a60589ec01 100644 --- a/components/esp_hw_support/port/esp32s3/esp_memprot.c +++ b/components/esp_hw_support/port/esp32s3/esp_memprot.c @@ -1,31 +1,179 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "sdkconfig.h" +#include "freertos/FreeRTOSConfig.h" #include "soc/periph_defs.h" #include "esp_intr_alloc.h" +#include "hal/memprot_ll.h" +#include "esp32s3/rom/ets_sys.h" +#include "esp_cpu.h" #include "esp_fault.h" #include "esp_attr.h" -#include "esp_memprot_err.h" #include "hal/memprot_types.h" #include "esp_private/esp_memprot_internal.h" #include "esp_memprot.h" -esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr) +extern int _iram_text_start; +extern int _iram_text_end; +extern int _rtc_text_end; + +////////////////////////////////////////////////////////////////////////////// +// internal helpers + +#if portNUM_PROCESSORS > 1 +static const int s_chip_cpu[] = {PRO_CPU_NUM, APP_CPU_NUM}; +#else +static const int s_chip_cpu[] = {PRO_CPU_NUM}; +#endif + +static esp_err_t esp_mprot_cpuid_valid(const int core) { + for (size_t x = 0; x < portNUM_PROCESSORS; x++) { + if (core == s_chip_cpu[x]) { + return ESP_OK; + } + } + + return ESP_ERR_MEMPROT_CPUID_INVALID; +} + +static void *esp_memprot_iram0_get_def_split_addr(void) +{ + return (void *)(uint32_t)&_iram_text_end; +} + +static void *esp_memprot_dram0_get_def_split_addr(void) +{ + return (void *)MAP_IRAM_TO_DRAM((uint32_t)&_iram_text_end); +} + +static void *esp_memprot_rtcfast_get_min_split_addr(void) +{ + return (void *)(uint32_t)&_rtc_text_end; +} + +//register MEMPROT-relevant interrupts in the global matrix (to deploy panic handling) +//mapped to ETS_MEMACCESS_ERR_INUM (shared with cache-access interrupts) +static esp_err_t esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type, const int core) +{ + ESP_INTR_DISABLE(ETS_MEMACCESS_ERR_INUM); + + esp_err_t err; + uint32_t intr_src_num = ETS_MAX_INTR_SOURCE; + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_intr_source_num(core, &intr_src_num))) + esp_rom_route_intr_matrix(core, intr_src_num, ETS_MEMACCESS_ERR_INUM); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_intr_source_num(core, &intr_src_num))) + esp_rom_route_intr_matrix(core, intr_src_num, ETS_MEMACCESS_ERR_INUM); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_intr_source_num(core, &intr_src_num))) + esp_rom_route_intr_matrix(core, intr_src_num, ETS_MEMACCESS_ERR_INUM); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + ESP_INTR_ENABLE(ETS_MEMACCESS_ERR_INUM); + return ESP_OK; } -esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr) +////////////////////////////////////////////////////////////////////////////// +// PMS configuration APIs (set/get/lock) +// IRAM/DRAM settings are shared by both CPUs, RTCFAST settings are separate for each core + +esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr, const int core __attribute__((unused))) +{ + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + switch (line_type) { + case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0: + return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_main_I_D(line_addr)); + case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0: + return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_0(line_addr)); + case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1: + return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_1(line_addr)); + default: + return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID; + } break; + case MEMPROT_TYPE_DRAM0_SRAM: + switch (line_type) { + case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0: + return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_0(line_addr)); + case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1: + return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_1(line_addr)); + default: + return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID; + } break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + if (line_type == MEMPROT_SPLIT_ADDR_MAIN) { /* so far only WORLD_0 is supported */ + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_set_rtcfast_split_line(core, line_addr, MEMP_LL_WORLD_0))) + return ESP_OK; + } else { + return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID; + } + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } +} + +esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr, const int core __attribute__((unused))) { if (line_addr == NULL) { return ESP_ERR_INVALID_ARG; } - *line_addr = NULL; + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + switch (line_type) { + case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0: + *line_addr = memprot_ll_get_iram0_split_line_main_I_D(); + break; + case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0: + *line_addr = memprot_ll_get_iram0_split_line_I_0(); + break; + case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1: + *line_addr = memprot_ll_get_iram0_split_line_I_1(); + break; + default: + return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID; + } break; + case MEMPROT_TYPE_DRAM0_SRAM: + switch (line_type) { + case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0: + *line_addr = memprot_ll_get_dram0_split_line_D_0(); + break; + case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1: + *line_addr = memprot_ll_get_dram0_split_line_D_1(); + break; + default: + return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID; + } break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + if (line_type == MEMPROT_SPLIT_ADDR_MAIN) { /* so far only WORLD_0 is supported */ + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(core, MEMP_LL_WORLD_0, *line_addr))) + } else { + return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID; + } + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } @@ -36,95 +184,318 @@ esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, return ESP_ERR_INVALID_ARG; } - *def_split_addr = NULL; + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + *def_split_addr = esp_memprot_iram0_get_def_split_addr(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + *def_split_addr = esp_memprot_dram0_get_def_split_addr(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + *def_split_addr = esp_memprot_rtcfast_get_min_split_addr(); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } -esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type) +esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + case MEMPROT_TYPE_DRAM0_SRAM: + memprot_ll_set_iram0_dram0_split_line_lock(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: { //caution: RTCFAST shares the lock with other PIF PMS constraints! + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_set_pif_constraint_lock(core))) + } break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + return ESP_OK; } -esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked) +esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core __attribute__((unused))) { if (locked == NULL) { return ESP_ERR_INVALID_ARG; } - *locked = false; + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + case MEMPROT_TYPE_DRAM0_SRAM: + *locked = memprot_ll_get_iram0_dram0_split_line_lock(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: { + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_get_pif_constraint_lock(core, locked))) + } break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } -esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type) +esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type, const int core __attribute__((unused))) { + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + memprot_ll_iram0_set_pms_lock(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + memprot_ll_dram0_set_pms_lock(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: { //caution: RTCFAST shares the lock with other PIF PMS constraints! + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_set_pif_constraint_lock(core))) + } break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + return ESP_OK; } -esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked) +esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core __attribute__((unused))) { if (locked == NULL) { return ESP_ERR_INVALID_ARG; } - *locked = false; + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + *locked = memprot_ll_iram0_get_pms_lock(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + *locked = memprot_ll_dram0_get_pms_lock(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: { + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_get_pif_constraint_lock(core, locked))) + } break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } -esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags) +esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags, const int core __attribute__((unused))) { + esp_err_t err; + bool r = flags & MEMPROT_OP_READ; + bool w = flags & MEMPROT_OP_WRITE; + bool x = flags & MEMPROT_OP_EXEC; + + switch (area_type) { + case MEMPROT_PMS_AREA_IRAM0_0: + memprot_ll_iram0_set_pms_area_0(r, w, x); + break; + case MEMPROT_PMS_AREA_IRAM0_1: + memprot_ll_iram0_set_pms_area_1(r, w, x); + break; + case MEMPROT_PMS_AREA_IRAM0_2: + memprot_ll_iram0_set_pms_area_2(r, w, x); + break; + case MEMPROT_PMS_AREA_IRAM0_3: + memprot_ll_iram0_set_pms_area_3(r, w, x); + break; + case MEMPROT_PMS_AREA_DRAM0_0: + memprot_ll_dram0_set_pms_area_0(r, w); + break; + case MEMPROT_PMS_AREA_DRAM0_1: + memprot_ll_dram0_set_pms_area_1(r, w); + break; + case MEMPROT_PMS_AREA_DRAM0_2: + memprot_ll_dram0_set_pms_area_2(r, w); + break; + case MEMPROT_PMS_AREA_DRAM0_3: + memprot_ll_dram0_set_pms_area_3(r, w); + break; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_set_pms_area(core, r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW))) + break; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_set_pms_area(core, r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH))) + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + return ESP_OK; } -esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags) +esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags, const int core __attribute__((unused))) { if (flags == NULL) { return ESP_ERR_INVALID_ARG; } - *flags = MEMPROT_OP_NONE; + esp_err_t err; + bool r = false; + bool w = false; + bool x = false; + + switch (area_type) { + case MEMPROT_PMS_AREA_IRAM0_0: + memprot_ll_iram0_get_pms_area_0(&r, &w, &x); + break; + case MEMPROT_PMS_AREA_IRAM0_1: + memprot_ll_iram0_get_pms_area_1(&r, &w, &x); + break; + case MEMPROT_PMS_AREA_IRAM0_2: + memprot_ll_iram0_get_pms_area_2(&r, &w, &x); + break; + case MEMPROT_PMS_AREA_IRAM0_3: + memprot_ll_iram0_get_pms_area_3(&r, &w, &x); + break; + case MEMPROT_PMS_AREA_DRAM0_0: + memprot_ll_dram0_get_pms_area_0(&r, &w); + break; + case MEMPROT_PMS_AREA_DRAM0_1: + memprot_ll_dram0_get_pms_area_1(&r, &w); + break; + case MEMPROT_PMS_AREA_DRAM0_2: + memprot_ll_dram0_get_pms_area_2(&r, &w); + break; + case MEMPROT_PMS_AREA_DRAM0_3: + memprot_ll_dram0_get_pms_area_3(&r, &w); + break; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(core, &r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW))) + break; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(core, &r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + *flags = 0; + if (r) { + *flags |= MEMPROT_OP_READ; + } + if (w) { + *flags |= MEMPROT_OP_WRITE; + } + if (x) { + *flags |= MEMPROT_OP_EXEC; + } return ESP_OK; } -esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type) +esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type, const int core) { + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_set_monitor_lock(core))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_set_monitor_lock(core))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_set_monitor_lock(core))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + return ESP_OK; } -esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked) +esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked, const int core) { if (locked == NULL) { return ESP_ERR_INVALID_ARG; } - *locked = false; + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_lock(core, locked))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_lock(core, locked))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_lock(core, locked))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } -esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable) +esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable, const int core) { + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_set_monitor_en(core, enable))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_set_monitor_en(core, enable))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_set_monitor_en(core, enable))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + return ESP_OK; } -esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled) +esp_err_t esp_mprot_get_monitor_en(esp_mprot_mem_t mem_type, bool *enabled, const int core) { if (enabled == NULL) { return ESP_ERR_INVALID_ARG; } - *enabled = false; + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_en(core, enabled))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_en(core, enabled))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_en(core, enabled))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused))) -{ - return ESP_OK; -} +////////////////////////////////////////////////////////////////////////////// +// PMS-violation interrupt handling APIs (IRAM section - called from panic-handler) esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr) { @@ -132,8 +503,84 @@ esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_mem return ESP_ERR_INVALID_ARG; } - active_memp_intr->mem_type = MEMPROT_TYPE_NONE; - active_memp_intr->core = -1; + esp_mprot_mem_t mt; + int c; + + do { + uint32_t intr_on = 0; + esp_err_t err; + + mt = MEMPROT_TYPE_IRAM0_SRAM; + c = PRO_CPU_NUM; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_status_intr(c, &intr_on))) + if (intr_on) { + break; + } + + c = APP_CPU_NUM; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_status_intr(c, &intr_on))) + if (intr_on) { + break; + } + + mt = MEMPROT_TYPE_DRAM0_SRAM; + c = PRO_CPU_NUM; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_status_intr(c, &intr_on))) + if (intr_on) { + break; + } + + c = APP_CPU_NUM; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_status_intr(c, &intr_on))) + if (intr_on) { + break; + } + + mt = MEMPROT_TYPE_IRAM0_RTCFAST; + c = PRO_CPU_NUM; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_status_intr(c, &intr_on))) + if (intr_on) { + break; + } + + c = APP_CPU_NUM; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_status_intr(c, &intr_on))) + if (intr_on) { + break; + } + + mt = MEMPROT_TYPE_NONE; + c = -1; + + } while (0); + + active_memp_intr->mem_type = mt; + active_memp_intr->core = c; + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(esp_mprot_mem_t mem_type, const int core) +{ + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_set_monitor_intrclr(core))) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_reset_monitor_intrclr(core))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_set_monitor_intrclr(core))) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_reset_monitor_intrclr(core))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_set_monitor_intrclr(core))) + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_reset_monitor_intrclr(core))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } return ESP_OK; } @@ -144,7 +591,33 @@ esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked) return ESP_ERR_INVALID_ARG; } - *locked = false; + bool lock_on = false; + + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, DEFAULT_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on, PRO_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on, APP_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, PRO_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on, APP_CPU_NUM)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, PRO_CPU_NUM)); + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on, APP_CPU_NUM)); + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on, PRO_CPU_NUM)); + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on, APP_CPU_NUM)); + *locked |= lock_on; return ESP_OK; } @@ -155,61 +628,633 @@ esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled) return ESP_ERR_INVALID_ARG; } - *enabled = false; + bool ena_on = false; + + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on, PRO_CPU_NUM)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on, APP_CPU_NUM)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on, PRO_CPU_NUM)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on, APP_CPU_NUM)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on, PRO_CPU_NUM)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on, APP_CPU_NUM)) + *enabled |= ena_on; return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, const int core) { if (fault_addr == NULL) { return ESP_ERR_INVALID_ARG; } - *fault_addr = NULL; + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + void *fault_addr_temp = NULL; + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_status_fault_addr(core, &fault_addr_temp))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_status_fault_addr(core, &fault_addr_temp))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_status_fault_addr(core, &fault_addr_temp))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + *fault_addr = fault_addr_temp; return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, const int core) { if (world == NULL) { return ESP_ERR_INVALID_ARG; } - *world = MEMPROT_PMS_WORLD_NONE; + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + uint32_t regval = MEMPROT_PMS_WORLD_INVALID; + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_status_fault_world(core, ®val))) + break; + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_status_fault_world(core, ®val))) + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_status_fault_world(core, ®val))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + if (regval == MEMPROT_PMS_WORLD_INVALID) { + return ESP_ERR_MEMPROT_WORLD_INVALID; + } + + *world = esp_mprot_ll_world_to_hl_world(regval); return ESP_OK; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, const int core) { if (oper == NULL) { return ESP_ERR_INVALID_ARG; } - *oper = MEMPROT_OP_NONE; + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + uint32_t operation = MEMPROT_OP_NONE; + uint32_t regval = 0xFFFFFFFF; + + //check 1: LoadStore, 2: R/W + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: { + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_status_fault_loadstore(core, ®val))) + if (regval == 0) { + operation = MEMPROT_OP_EXEC; + } else { + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_iram0_get_monitor_status_fault_wr(core, ®val))) + operation = regval == 0 ? MEMPROT_OP_READ : MEMPROT_OP_WRITE; + } + } break; + case MEMPROT_TYPE_IRAM0_RTCFAST: { + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_status_fault_loadstore(core, ®val))) + if (regval == 0) { + operation = MEMPROT_OP_EXEC; + } else { + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_monitor_status_fault_wr(core, ®val))) + operation = regval == 0 ? MEMPROT_OP_READ : MEMPROT_OP_WRITE; + } + } break; + case MEMPROT_TYPE_DRAM0_SRAM: { + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_status_fault_wr(core, ®val))) + operation = regval == 0 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ; + } break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + *oper = operation; return ESP_OK; } bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type) { - return false; + return mem_type == MEMPROT_TYPE_DRAM0_SRAM; } -esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused))) +esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, const int core) { if (byte_en == NULL) { return ESP_ERR_INVALID_ARG; } - *byte_en = 0; + esp_err_t err; + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_cpuid_valid(core)) + + uint32_t byteen = 0xFFFFFFFF; + + //NOTE: more memory types coming in future updates, hence using switch + switch (mem_type) { + case MEMPROT_TYPE_DRAM0_SRAM: + ESP_MEMPROT_ERR_CHECK(err, esp_mprot_ll_err_to_esp_err(memprot_ll_dram0_get_monitor_status_fault_byte_en(core, &byteen))) + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + *byte_en = byteen; return ESP_OK; } +////////////////////////////////////////////////////////////////////////////// +// convenient "public" APIs esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config) { + //debugger connected: + // 1.check the signal repeatedly to avoid possible glitching attempt + // 2.leave the Memprot unset to allow debug operations + + if (esp_cpu_in_ocd_debug_mode()) { + ESP_FAULT_ASSERT(esp_cpu_in_ocd_debug_mode()); + return ESP_OK; + } + + //sanity checks + if (memp_config == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (memp_config->mem_type_mask == MEMPROT_TYPE_NONE) { + return ESP_ERR_NO_MEM; + } + if (memp_config->target_cpu_count < 1 || memp_config->target_cpu_count > portNUM_PROCESSORS) { + return ESP_ERR_MEMPROT_CPUID_INVALID; + } + + esp_err_t ret = ESP_OK; + size_t core_count = memp_config->target_cpu_count; + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_cpuid_valid(memp_config->target_cpu[x])) + } + + bool use_iram0 = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_SRAM; + bool use_dram0 = memp_config->mem_type_mask & MEMPROT_TYPE_DRAM0_SRAM; + bool use_rtcfast = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_RTCFAST; + + //disable protection (must be unlocked) + if (use_iram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false, memp_config->target_cpu[x])) + } + } + if (use_dram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false, memp_config->target_cpu[x])) + } + } + if (use_rtcfast) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false, memp_config->target_cpu[x])) + } + } + + //panic handling + if (memp_config->invoke_panic_handler) { + if (use_iram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_SRAM, memp_config->target_cpu[x])) + } + } + if (use_dram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_DRAM0_SRAM, memp_config->target_cpu[x])) + } + } + if (use_rtcfast) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_RTCFAST, memp_config->target_cpu[x])) + } + } + } + + //set split lines (must-have for all mem_types). This version sets only the main I/D which is then shared for all PMS regions + void *line_addr __attribute__((unused)) = NULL; + if (use_iram0 || use_dram0) { + line_addr = memp_config->split_addr; + if (line_addr == NULL) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_SRAM, &line_addr)) + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_1, line_addr, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_0, line_addr, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_DRAM0, line_addr, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)), DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)), DEFAULT_CPU_NUM)) + } + + //set permissions + if (use_iram0) { + ret = ESP_OK; + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_EXEC, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, MEMPROT_OP_NONE, DEFAULT_CPU_NUM)) + } + if (use_dram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, MEMPROT_OP_READ, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, MEMPROT_OP_READ | MEMPROT_OP_WRITE, DEFAULT_CPU_NUM)) + } + + void *rtc_fast_line __attribute__((unused)) = NULL; + if (use_rtcfast) { + //RTCFAST split-line cannot be set manually - always use default + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, &rtc_fast_line)); + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, MEMPROT_SPLIT_ADDR_MAIN, rtc_fast_line, memp_config->target_cpu[x])) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, MEMPROT_OP_READ | MEMPROT_OP_EXEC, memp_config->target_cpu[x])) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, MEMPROT_OP_READ | MEMPROT_OP_WRITE, memp_config->target_cpu[x])) + } + } + + //reenable the protection + if (use_iram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, memp_config->target_cpu[x])) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, true, memp_config->target_cpu[x])) + } + } + + if (use_dram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, memp_config->target_cpu[x])) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, true, memp_config->target_cpu[x])) + } + } + if (use_rtcfast) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, memp_config->target_cpu[x])) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, true, memp_config->target_cpu[x])) + } + } + + //lock if required + if (memp_config->lock_feature) { + if (use_iram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM)) + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, memp_config->target_cpu[x])) + } + } + if (use_dram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM)) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM)) + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, memp_config->target_cpu[x])) + } + } + if (use_rtcfast) { + //split address and area permissions are locked by the same PMS register + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST, memp_config->target_cpu[x])) + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, memp_config->target_cpu[x])) + } + } + } + + //sanity check (RTC FAST tbd within IDF-5208) + if (use_iram0 || use_dram0) { + + uint32_t check_val; + + //IRAM0 split lines + memprot_ll_prepare_iram0_split_line_regval((const uint32_t) line_addr, &check_val); + + if (memprot_ll_get_iram0_split_line_main_I_D_regval() != check_val) { + esp_rom_printf( + "Fatal error: Main I/D split line configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + check_val, memprot_ll_get_iram0_split_line_main_I_D_regval()); + abort(); + } + if (memprot_ll_get_iram0_split_line_main_I_0_regval() != check_val) { + esp_rom_printf( + "Fatal error: IRAM0 I_0 split line configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + check_val, memprot_ll_get_iram0_split_line_main_I_0_regval()); + abort(); + } + if (memprot_ll_get_iram0_split_line_main_I_1_regval() != check_val) { + esp_rom_printf( + "Fatal error: IRAM0 I_1 split line configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + check_val, memprot_ll_get_iram0_split_line_main_I_1_regval()); + abort(); + } + + //DRAM0 split lines + memprot_ll_prepare_dram0_split_line_regval(MAP_IRAM_TO_DRAM((const uint32_t) line_addr), &check_val); + + if (memprot_ll_get_dram0_split_line_main_D_0_regval() != check_val) { + esp_rom_printf( + "Fatal error: DRAM0 D_0 split line configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + check_val, memprot_ll_get_dram0_split_line_main_D_0_regval()); + abort(); + } + if (memprot_ll_get_dram0_split_line_main_D_1_regval() != check_val) { + esp_rom_printf( + "Fatal error: DRAM0 D_1 split line configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + check_val, memprot_ll_get_dram0_split_line_main_D_1_regval()); + abort(); + } + + //IRAM0 perms + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_IRAM0_0, &check_val, DEFAULT_CPU_NUM)) + if (check_val != (MEMPROT_OP_READ | MEMPROT_OP_EXEC)) { + esp_rom_printf("Fatal error: IRAM0 PMS AREA_0 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ | MEMPROT_OP_EXEC, check_val); + abort(); + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_IRAM0_1, &check_val, DEFAULT_CPU_NUM)) + if (check_val != (MEMPROT_OP_READ | MEMPROT_OP_EXEC)) { + esp_rom_printf("Fatal error: IRAM0 PMS AREA_1 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ | MEMPROT_OP_EXEC, check_val); + abort(); + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_IRAM0_2, &check_val, DEFAULT_CPU_NUM)) + if (check_val != (MEMPROT_OP_READ | MEMPROT_OP_EXEC)) { + esp_rom_printf("Fatal error: IRAM0 PMS AREA_2 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ | MEMPROT_OP_EXEC, check_val); + abort(); + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_IRAM0_3, &check_val, DEFAULT_CPU_NUM)) + if (check_val != MEMPROT_OP_NONE) { + esp_rom_printf("Fatal error: IRAM0 PMS AREA_3 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_NONE, check_val); + abort(); + } + + //DRAM0 perms + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_DRAM0_0, &check_val, DEFAULT_CPU_NUM)) + if (check_val != MEMPROT_OP_READ) { + esp_rom_printf("Fatal error: DRAM0 PMS AREA_0 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ, check_val); + abort(); + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_DRAM0_1, &check_val, DEFAULT_CPU_NUM)) + if (check_val != (MEMPROT_OP_READ | MEMPROT_OP_WRITE)) { + esp_rom_printf("Fatal error: DRAM0 PMS AREA_1 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ | MEMPROT_OP_WRITE, check_val); + abort(); + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_DRAM0_2, &check_val, DEFAULT_CPU_NUM)) + if (check_val != (MEMPROT_OP_READ | MEMPROT_OP_WRITE)) { + esp_rom_printf("Fatal error: DRAM0 PMS AREA_2 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ | MEMPROT_OP_WRITE, check_val); + abort(); + } + + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_area(MEMPROT_PMS_AREA_DRAM0_3, &check_val, DEFAULT_CPU_NUM)) + if (check_val != (MEMPROT_OP_READ | MEMPROT_OP_WRITE)) { + esp_rom_printf("Fatal error: DRAM0 PMS AREA_3 configuration corrupted (expected 0x%08X, stored 0x%08X)\n", + MEMPROT_OP_READ | MEMPROT_OP_WRITE, check_val); + abort(); + } + + //memory protection enabled + bool enabled; + if (use_iram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &enabled, + memp_config->target_cpu[x])) + if (!enabled) { + esp_rom_printf( + "Fatal error: IRAM0 PMS configuration corrupted (memory protection not enabled on core %d)\n", + memp_config->target_cpu[x]); + abort(); + } + } + } + if (use_dram0) { + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &enabled, + memp_config->target_cpu[x])) + if (!enabled) { + esp_rom_printf( + "Fatal error: DRAM0 PMS configuration corrupted (memory protection not enabled on core %d)\n", + memp_config->target_cpu[x]); + abort(); + } + } + } + + //locks + if (memp_config->lock_feature) { + + bool locked; + + if (use_iram0) { + ESP_MEMPROT_ERR_CHECK(ret, + esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &locked, DEFAULT_CPU_NUM)) + if (!locked) { + esp_rom_printf( + "Fatal error: IRAM0 PMS configuration corrupted (memory protection not locked - split address lock)\n"); + abort(); + } + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &locked, DEFAULT_CPU_NUM)) + if (!locked) { + esp_rom_printf( + "Fatal error: IRAM0 PMS configuration corrupted (memory protection not locked - global PMS lock)\n"); + abort(); + } + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &locked, + memp_config->target_cpu[x])) + if (!locked) { + esp_rom_printf( + "Fatal error: IRAM0 PMS configuration corrupted (memory protection not locked - monitor lock on core %d)\n", + memp_config->target_cpu[x]); + abort(); + } + } + } + + if (use_dram0) { + ESP_MEMPROT_ERR_CHECK(ret, + esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &locked, DEFAULT_CPU_NUM)) + if (!locked) { + esp_rom_printf( + "Fatal error: DRAM0 PMS configuration corrupted (memory protection not locked - split address lock)\n"); + abort(); + } + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &locked, DEFAULT_CPU_NUM)) + if (!locked) { + esp_rom_printf( + "Fatal error: DRAM0 PMS configuration corrupted (memory protection not locked - global PMS lock)\n"); + abort(); + } + for (size_t x = 0; x < core_count; x++) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &locked, + memp_config->target_cpu[x])) + if (!locked) { + esp_rom_printf( + "Fatal error: DRAM0 PMS configuration corrupted (memory protection not locked - monitor lock on core %d)\n", + memp_config->target_cpu[x]); + abort(); + } + } + } + } + } + + return ret; +} + +esp_err_t esp_mprot_dump_configuration(char **dump_info_string) +{ + if (dump_info_string == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *dump_info_string = (char *)calloc(1, 2048); + + if (*dump_info_string == NULL) { + return ESP_ERR_NO_MEM; + } + + sprintf(*dump_info_string, + "Memory sections:\n" + " _iram_text_start: 0x%08X\n _iram_text_end: 0x%08X\n", + (uint32_t)&_iram_text_start, (uint32_t)&_iram_text_end); + + uint32_t offset = strlen(*dump_info_string); + + bool line_lock = memprot_ll_get_iram0_dram0_split_line_lock(); + uint32_t line_ID = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D(); + uint32_t line_I0 = (uint32_t)memprot_ll_get_iram0_split_line_I_0(); + uint32_t line_I1 = (uint32_t)memprot_ll_get_iram0_split_line_I_1(); + uint32_t line_D0 = (uint32_t)memprot_ll_get_dram0_split_line_D_0(); + uint32_t line_D1 = (uint32_t)memprot_ll_get_dram0_split_line_D_1(); + uint32_t line_ID_cat = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D_cat(); + uint32_t line_I0_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_0_cat(); + uint32_t line_I1_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_1_cat(); + uint32_t line_D0_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_0_cat(); + uint32_t line_D1_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_1_cat(); + + sprintf((*dump_info_string + offset), + "Split line settings (lock=%u):\n" + " IRAM0:\n line ID (main): 0x%08X (cat=0x%08X)\n line I0: 0x%08X (cat=0x%08X)\n line I1: 0x%08X (cat=0x%08X)\n" + " DRAM0:\n line D0: 0x%08X (cat=0x%08X)\n line D1: 0x%08X (cat=0x%08X)\n", + line_lock, line_ID, line_ID_cat, line_I0, line_I0_cat, line_I1, line_I1_cat, line_D0, line_D0_cat, line_D1, line_D1_cat); + + offset = strlen(*dump_info_string); + + void *line_RTC = NULL; + esp_err_t err = esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(PRO_CPU_NUM, MEMP_LL_WORLD_0, &line_RTC)); + if (err != ESP_OK) { + sprintf((*dump_info_string + offset), " RTCFAST:\n line main: N/A (world=0) - %s\n", esp_err_to_name(err)); + } else { + sprintf((*dump_info_string + offset), " RTCFAST:\n line main: 0x%08X (world=0)\n", (uint32_t)line_RTC); + } + offset = strlen(*dump_info_string); + + bool ar0i, ar1i, ar2i, ar3i; + bool aw0i, aw1i, aw2i, aw3i; + bool ax0i, ax1i, ax2i, ax3i; + bool ar0d, ar1d, ar2d, ar3d; + bool aw0d, aw1d, aw2d, aw3d; + + bool pms_lock_i = memprot_ll_iram0_get_pms_lock(); + memprot_ll_iram0_get_pms_area_0(&ar0i, &aw0i, &ax0i); + memprot_ll_iram0_get_pms_area_1(&ar1i, &aw1i, &ax1i); + memprot_ll_iram0_get_pms_area_2(&ar2i, &aw2i, &ax2i); + memprot_ll_iram0_get_pms_area_3(&ar3i, &aw3i, &ax3i); + + bool pms_lock_d = memprot_ll_dram0_get_pms_lock(); + memprot_ll_dram0_get_pms_area_0(&ar0d, &aw0d); + memprot_ll_dram0_get_pms_area_1(&ar1d, &aw1d); + memprot_ll_dram0_get_pms_area_2(&ar2d, &aw2d); + memprot_ll_dram0_get_pms_area_3(&ar3d, &aw3d); + + bool rtc_line_lock_0, rtc_line_lock_1; + memprot_ll_get_pif_constraint_lock(PRO_CPU_NUM, &rtc_line_lock_0); + memprot_ll_get_pif_constraint_lock(APP_CPU_NUM, &rtc_line_lock_1); + + sprintf((*dump_info_string + offset), + "PMS area settings:\n" + " IRAM0 (lock=%u):\n area 0: r=%u,w=%u,x=%u\n area 1: r=%u,w=%u,x=%u\n area 2: r=%u,w=%u,x=%u\n area 3: r=%u,w=%u,x=%u\n" + " DRAM0 (lock=%u):\n area 0: r=%u,w=%u\n area 1: r=%u,w=%u\n area 2: r=%u,w=%u\n area 3: r=%u,w=%u\n" + " RTCFAST (PRO_CPU, lock=%u):\n", + pms_lock_i, ar0i, aw0i, ax0i, ar1i, aw1i, ax1i, ar2i, aw2i, ax2i, ar3i, aw3i, ax3i, + pms_lock_d, ar0d, aw0d, ar1d, aw1d, ar2d, aw2d, ar3d, aw3d, rtc_line_lock_0); + + offset = strlen(*dump_info_string); + + bool arl0rtc, awl0rtc, axl0rtc; + bool arh0rtc, awh0rtc, axh0rtc; + + err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(PRO_CPU_NUM, &arl0rtc, &awl0rtc, &axl0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW)); + if (err != ESP_OK) { + sprintf((*dump_info_string + offset), " area low: N/A - %s\n", esp_err_to_name(err)); + } else { + sprintf((*dump_info_string + offset), " area low: r=%u,w=%u,x=%u\n", arl0rtc, awl0rtc, axl0rtc); + } + + offset = strlen(*dump_info_string); + + err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(PRO_CPU_NUM, &arh0rtc, &awh0rtc, &axh0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH)); + if (err != ESP_OK) { + sprintf((*dump_info_string + offset), " area high: N/A - %s\n", esp_err_to_name(err)); + } else { + sprintf((*dump_info_string + offset), " area high: r=%u,w=%u,x=%u\n", arh0rtc, awh0rtc, axh0rtc); + } + + offset = strlen(*dump_info_string); + + sprintf((*dump_info_string + offset), " RTCFAST (APP_CPU, lock=%u):\n", rtc_line_lock_1); + + offset = strlen(*dump_info_string); + + err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(APP_CPU_NUM, &arl0rtc, &awl0rtc, &axl0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW)); + if (err != ESP_OK) { + sprintf((*dump_info_string + offset), " area low: N/A - %s\n", esp_err_to_name(err)); + } else { + sprintf((*dump_info_string + offset), " area low: r=%u,w=%u,x=%u\n", arl0rtc, awl0rtc, axl0rtc); + } + + offset = strlen(*dump_info_string); + + err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(APP_CPU_NUM, &arh0rtc, &awh0rtc, &axh0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH)); + if (err != ESP_OK) { + sprintf((*dump_info_string + offset), " area high: N/A - %s\n", esp_err_to_name(err)); + } else { + sprintf((*dump_info_string + offset), " area high: r=%u,w=%u,x=%u\n", arh0rtc, awh0rtc, axh0rtc); + } + + offset = strlen(*dump_info_string); + return ESP_OK; } diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index fd547009e9..56d0def619 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -133,7 +133,7 @@ menu "ESP System Settings" bool default y if IDF_TARGET_ESP32S2 default y if IDF_TARGET_ESP32C3 - default y if IDF_TARGET_ESP32H2 + default y if IDF_TARGET_ESP32S3 config ESP_SYSTEM_MEMPROT_FEATURE bool "Enable memory protection" diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index 1b1464abd4..4607b371d1 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -100,11 +100,6 @@ MEMORY */ rtc_iram_seg(RWX) : org = 0x600fe000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC - /** - * RTC fast memory (same block as above), viewed from data bus - */ - rtc_data_seg(RW) : org = 0x600fe000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC - /** * RTC slow memory (data accessible). Persists over deep sleep. * Start of RTC slow memory is reserved for ULP co-processor code + data, if enabled. @@ -134,6 +129,10 @@ _heap_end = 0x40000000; _data_seg_org = ORIGIN(rtc_data_seg); + +/* RTC fast memory shares the same range for both data and instructions */ +REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); + #if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM REGION_ALIAS("rtc_data_location", rtc_data_seg ); #else diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index b1885ee3ac..3c9a482c06 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -18,27 +18,22 @@ SECTIONS .rtc.text : { . = ALIGN(4); + _rtc_fast_start = ABSOLUTE(.); _rtc_text_start = ABSOLUTE(.); *(.rtc.entry.text) mapping[rtc_text] *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + *(.rtc_text_end_test) + + /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(4); + _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg - /** - * This section is required to skip rtc.text area because rtc_iram_seg and - * rtc_data_seg are reflect the same address space on different buses. - */ - .rtc.dummy : - { - _rtc_dummy_start = ABSOLUTE(.); - _rtc_fast_start = ABSOLUTE(.); - . = SIZEOF(.rtc.text); - _rtc_dummy_end = ABSOLUTE(.); - } > rtc_data_seg - /** * This section located in RTC FAST Memory area. * It holds data marked with RTC_FAST_ATTR attribute. @@ -402,11 +397,11 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and 256B alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; . = ALIGN(_esp_memprot_align_size); - /* iram_end_test section exists for use by memprot unit tests only */ - *(.iram_end_test) _iram_text_end = ABSOLUTE(.); } > iram0_0_seg diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index 89d8d98094..edaac9115f 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -161,7 +161,7 @@ static esp_memp_intr_source_t s_memp_intr = {MEMPROT_TYPE_INVALID, -1}; #define PRINT_MEMPROT_ERROR(err) \ panic_print_str("N/A (error "); \ panic_print_str(esp_err_to_name(err)); \ - panic_print_str(")"); + panic_print_str(")") static inline void print_memprot_err_details(const void *frame __attribute__((unused))) { @@ -176,40 +176,40 @@ static inline void print_memprot_err_details(const void *frame __attribute__((un panic_print_str("\r\n faulting address: "); void *faulting_addr; - esp_err_t res = esp_mprot_get_violate_addr(s_memp_intr.mem_type, &faulting_addr, &s_memp_intr.core); + esp_err_t res = esp_mprot_get_violate_addr(s_memp_intr.mem_type, &faulting_addr, s_memp_intr.core); if (res == ESP_OK) { panic_print_str("0x"); panic_print_hex((int)faulting_addr); } else { - PRINT_MEMPROT_ERROR(res) + PRINT_MEMPROT_ERROR(res); } panic_print_str( "\r\n world: "); esp_mprot_pms_world_t world; - res = esp_mprot_get_violate_world(s_memp_intr.mem_type, &world, &s_memp_intr.core); + res = esp_mprot_get_violate_world(s_memp_intr.mem_type, &world, s_memp_intr.core); if (res == ESP_OK) { panic_print_str(esp_mprot_pms_world_to_str(world)); } else { - PRINT_MEMPROT_ERROR(res) + PRINT_MEMPROT_ERROR(res); } panic_print_str( "\r\n operation type: "); uint32_t operation; - res = esp_mprot_get_violate_operation(s_memp_intr.mem_type, &operation, &s_memp_intr.core); + res = esp_mprot_get_violate_operation(s_memp_intr.mem_type, &operation, s_memp_intr.core); if (res == ESP_OK) { panic_print_str(esp_mprot_oper_type_to_str(operation)); } else { - PRINT_MEMPROT_ERROR(res) + PRINT_MEMPROT_ERROR(res); } if (esp_mprot_has_byte_enables(s_memp_intr.mem_type)) { panic_print_str("\r\n byte-enables: " ); uint32_t byte_enables; - res = esp_mprot_get_violate_byte_enables(s_memp_intr.mem_type, &byte_enables, &s_memp_intr.core); + res = esp_mprot_get_violate_byte_enables(s_memp_intr.mem_type, &byte_enables, s_memp_intr.core); if (res == ESP_OK) { panic_print_hex(byte_enables); } else { - PRINT_MEMPROT_ERROR(res) + PRINT_MEMPROT_ERROR(res); } } diff --git a/components/hal/esp32s3/include/hal/memprot_ll.h b/components/hal/esp32s3/include/hal/memprot_ll.h index 41410cc80f..ad8297864a 100644 --- a/components/hal/esp32s3/include/hal/memprot_ll.h +++ b/components/hal/esp32s3/include/hal/memprot_ll.h @@ -1,655 +1,1630 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once +#include "soc/ext_mem_defs.h" +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" + +/* Uncomment to enable MPS debug assertions on false register writes. + * It irregularly happens the PMS registers cannot be written which causes unpredictable malfunction of the Memprot feature + * Once the issue is found & resolved, the assertions can be removed + */ +//#define PMS_DEBUG_ASSERTIONS + +#ifdef PMS_DEBUG_ASSERTIONS #include "hal/assert.h" +#endif #ifdef __cplusplus extern "C" { #endif -// not implemented for esp32s3 yet -#if 0 -/** - * === IRAM0 ==== - */ + //highest address of each Level slot in the SRAM's 3rd memory region (I/D access, 416kB) +//quick resolver of split-address category bits +static const intptr_t sram_rg3_level_hlimits[] = { + 0x4037FFFF, //level 2 (32KB) + 0x4038FFFF, //level 3 (64KB) + 0x4039FFFF, //level 4 (64KB) + 0x403A0000, //level 5 (64KB) + 0x403B0000, //level 6 (64KB) + 0x403C0000, //level 7 (64KB) + 0x403D0000 //level 8 (64KB) +}; -#define IRAM0_TOTAL_UNI_BLOCKS 4 -#define IRAM0_UNI_BLOCK_0 0 -#define IRAM0_UNI_BLOCK_1 1 -#define IRAM0_UNI_BLOCK_2 2 -#define IRAM0_UNI_BLOCK_3 3 - -#define IRAM0_SPL_BLOCK_BASE 0x40000000 - -//unified management (SRAM blocks 0-3) -#define IRAM0_UNI_BLOCK_0_LOW 0x40020000 -#define IRAM0_UNI_BLOCK_0_HIGH 0x40021FFF -#define IRAM0_UNI_BLOCK_1_LOW 0x40022000 -#define IRAM0_UNI_BLOCK_1_HIGH 0x40023FFF -#define IRAM0_UNI_BLOCK_2_LOW 0x40024000 -#define IRAM0_UNI_BLOCK_2_HIGH 0x40025FFF -#define IRAM0_UNI_BLOCK_3_LOW 0x40026000 -#define IRAM0_UNI_BLOCK_3_HIGH 0x40027FFF - -//split management (SRAM blocks 4-21) -#define IRAM0_SPL_BLOCK_LOW 0x40028000 //block 4 low -#define IRAM0_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high -#define IRAM0_SPLTADDR_MIN 0x40030000 //block 6 low - minimum splitting address - -//IRAM0 interrupt status bitmasks -#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //(bits 21:6 in the reg, as well as in real address) -#define IRAM0_INTR_ST_FAULTADDR_HI 0x40000000 //(high nonsignificant bits 31:22 of the faulting address - constant) -#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 -#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 - - -static inline uint32_t esp_memprot_iram0_get_intr_source_num(void) +/* ****************************************************************************************************** + * *** COMMON *** + * ******************************************************************************************************/ +static inline void memprot_ll_set_iram0_dram0_split_line_lock(void) { - return ETS_PMS_PRO_IRAM0_ILG_INTR_SOURCE; -} - -static inline void esp_memprot_iram0_intr_ena(bool enable) -{ - if ( enable ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN ); - } -} - -static inline uint32_t esp_memprot_iram0_get_ena_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_4_REG); -} - -static inline uint32_t esp_memprot_iram0_get_fault_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_5_REG); -} - -static inline void esp_memprot_iram0_get_fault_status(uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) -{ - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - - uint32_t fault_addr = (status_bits & IRAM0_INTR_ST_FAULTADDR_M); - *faulting_address = (uint32_t *)(fault_addr | IRAM0_INTR_ST_FAULTADDR_HI); - - *op_type = (uint32_t)status_bits & IRAM0_INTR_ST_OP_RW_BIT; - *op_subtype = (uint32_t)status_bits & IRAM0_INTR_ST_OP_TYPE_BIT; -} - -static inline bool esp_memprot_iram0_is_assoc_intr(void) -{ - return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR) > 0; -} - -static inline void esp_memprot_iram0_clear_intr(void) -{ - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); -} - -static inline uint32_t esp_memprot_iram0_get_intr_ena_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); -} - -static inline uint32_t esp_memprot_iram0_get_intr_on_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR); -} - -static inline uint32_t esp_memprot_iram0_get_intr_clr_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); -} - -//resets automatically on CPU restart -static inline void esp_memprot_iram0_set_lock(void) -{ - DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); -} - -static inline uint32_t esp_memprot_iram0_get_lock_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_0_REG); -} - -static inline uint32_t esp_memprot_iram0_get_lock_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); -} - -//block 0-3 -static inline void esp_memprot_iram0_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) -{ - HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS); - - uint32_t write_bit, read_bit, exec_bit; - switch ( block ) { - case IRAM0_UNI_BLOCK_0: - write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; - read_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_R; - exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_F; - break; - case IRAM0_UNI_BLOCK_1: - write_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_W; - read_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_R; - exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_F; - break; - case IRAM0_UNI_BLOCK_2: - write_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_W; - read_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_R; - exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_F; - break; - case IRAM0_UNI_BLOCK_3: - write_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_W; - read_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_R; - exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; - break; - default: - abort(); - } - - if ( write_perm ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, write_bit ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, write_bit ); - } - - if ( read_perm ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, read_bit ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, read_bit ); - } - - if ( exec_perm ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, exec_bit ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_IRAM0_1_REG, exec_bit ); - } -} - -static inline uint32_t esp_memprot_iram0_get_uni_block_read_bit(uint32_t block) -{ - HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case IRAM0_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R ); - case IRAM0_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R ); - case IRAM0_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R ); - case IRAM0_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R ); - default: - abort(); - } -} - -static inline uint32_t esp_memprot_iram0_get_uni_block_write_bit(uint32_t block) -{ - HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case IRAM0_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W ); - case IRAM0_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W ); - case IRAM0_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W ); - case IRAM0_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W ); - default: - abort(); - } -} - -static inline uint32_t esp_memprot_iram0_get_uni_block_exec_bit(uint32_t block) -{ - HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case IRAM0_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F ); - case IRAM0_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F ); - case IRAM0_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F ); - case IRAM0_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F ); - default: - abort(); - } -} - -static inline void esp_memprot_iram0_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) -{ - HAL_ASSERT(block < IRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case IRAM0_UNI_BLOCK_0: - *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; - *read_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_R; - *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_F; - break; - case IRAM0_UNI_BLOCK_1: - *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_W; - *read_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_R; - *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_1_F; - break; - case IRAM0_UNI_BLOCK_2: - *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_W; - *read_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_R; - *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_2_F; - break; - case IRAM0_UNI_BLOCK_3: - *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_W; - *read_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_R; - *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; - break; - default: - abort(); - } -} - -static inline uint32_t esp_memprot_iram0_get_perm_uni_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG); -} - -static inline uint32_t esp_memprot_iram0_get_perm_split_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG); -} - -static inline void esp_memprot_iram0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) -{ - uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr <= IRAM0_SPL_BLOCK_HIGH); - - //find possible split.address in low region blocks - int uni_blocks_low = -1; - if ( addr >= IRAM0_UNI_BLOCK_0_LOW ) { - uni_blocks_low++; - } - if ( addr >= IRAM0_UNI_BLOCK_1_LOW ) { - uni_blocks_low++; - } - if ( addr >= IRAM0_UNI_BLOCK_2_LOW ) { - uni_blocks_low++; - } - if ( addr >= IRAM0_UNI_BLOCK_3_LOW ) { - uni_blocks_low++; - } - - //unified mgmt settings per block (bits W/R/X: [11:9] bl3, [8:6] bl2, [5:3] bl1, [2:0] bl0) - uint32_t write_bit, read_bit, exec_bit; - uint32_t uni_block_perm = 0; - - for ( size_t x = 0; x < IRAM0_TOTAL_UNI_BLOCKS; x++ ) { - esp_memprot_iram0_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit); - if ( x <= uni_blocks_low ) { - if (lw) { - uni_block_perm |= write_bit; - } - if (lr) { - uni_block_perm |= read_bit; - } - if (lx) { - uni_block_perm |= exec_bit; - } - } else { - if (hw) { - uni_block_perm |= write_bit; - } - if (hr) { - uni_block_perm |= read_bit; - } - if (hx) { - uni_block_perm |= exec_bit; - } - } - } - - //if splt.ddr not set yet, do required normalization to make the addr writeble into splt.mgmt cfg register - uint32_t reg_split_addr = 0; - - if ( addr >= IRAM0_SPL_BLOCK_LOW ) { - - //split Address must be WORD aligned - reg_split_addr = addr >> 2; - HAL_ASSERT(addr == (reg_split_addr << 2)); - - //use only 17 signf.bits as the cropped parts are constant for whole section (bits [16:0]) - reg_split_addr = (reg_split_addr << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_M; - } - - //prepare high & low permission mask (bits: [22:20] high range, [19:17] low range) - uint32_t permission_mask = 0; - if ( lw ) { - permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_L_W; - } - if ( lr ) { - permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_L_R; - } - if ( lx ) { - permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_L_F; - } - if ( hw ) { - permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_H_W; - } - if ( hr ) { - permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_H_R; - } - if ( hx ) { - permission_mask |= DPORT_PMS_PRO_IRAM0_SRAM_4_H_F; - } - - //write both cfg. registers - DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_1_REG, uni_block_perm ); - DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_2_REG, reg_split_addr | permission_mask ); -} - -static inline void esp_memprot_iram0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) -{ - *lw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W ); - *lr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R ); - *lx = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_F ); - *hw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_W ); - *hr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_R ); - *hx = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F ); -} - -/** - * === DRAM0 ==== - */ - -#define DRAM0_TOTAL_UNI_BLOCKS 4 -#define DRAM0_UNI_BLOCK_0 0 -#define DRAM0_UNI_BLOCK_1 1 -#define DRAM0_UNI_BLOCK_2 2 -#define DRAM0_UNI_BLOCK_3 3 - -#define DRAM0_SPL_BLOCK_BASE 0x3FFB0000 - -//unified management (SRAM blocks 0-3) -#define DRAM0_UNI_BLOCK_0_LOW 0x3FFB0000 -#define DRAM0_UNI_BLOCK_0_HIGH 0x3FFB1FFF -#define DRAM0_UNI_BLOCK_1_LOW 0x3FFB2000 -#define DRAM0_UNI_BLOCK_1_HIGH 0x3FFB3FFF -#define DRAM0_UNI_BLOCK_2_LOW 0x3FFB4000 -#define DRAM0_UNI_BLOCK_2_HIGH 0x3FFB5FFF -#define DRAM0_UNI_BLOCK_3_LOW 0x3FFB6000 -#define DRAM0_UNI_BLOCK_3_HIGH 0x3FFB7FFF - -//split management (SRAM blocks 4-21) -#define DRAM0_SPL_BLOCK_LOW 0x3FFB8000 //block 4 low -#define DRAM0_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high -#define DRAM0_SPLTADDR_MIN 0x3FFC0000 //block 6 low - minimum splitting address - -//DRAM0 interrupt status bitmasks -#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) -#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) -#define DRAM0_INTR_ST_FAULTADDR_HI 0x3FF00000 //(high nonsignificant bits 31:22 of the faulting address - constant) -#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 -#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 - - -static inline uint32_t esp_memprot_dram0_get_intr_source_num(void) -{ - return ETS_PMS_PRO_DRAM0_ILG_INTR_SOURCE; -} - -static inline void esp_memprot_dram0_intr_ena(bool enable) -{ - if ( enable ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN ); - } -} - -static inline bool esp_memprot_dram0_is_assoc_intr(void) -{ - return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR) > 0; -} - -static inline void esp_memprot_dram0_clear_intr(void) -{ - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); -} - -static inline uint32_t esp_memprot_dram0_get_intr_ena_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); -} - -static inline uint32_t esp_memprot_dram0_get_intr_on_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR); -} - -static inline uint32_t esp_memprot_dram0_get_intr_clr_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); -} - -static inline uint32_t esp_memprot_dram0_get_lock_bit(void) -{ - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); -} - -static inline void esp_memprot_dram0_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) -{ - HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case DRAM0_UNI_BLOCK_0: - *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_W; - *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_R; - break; - case DRAM0_UNI_BLOCK_1: - *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_1_W; - *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_1_R; - break; - case DRAM0_UNI_BLOCK_2: - *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_2_W; - *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_2_R; - break; - case DRAM0_UNI_BLOCK_3: - *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_W; - *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_R; - break; - default: - abort(); - } -} - -static inline void esp_memprot_dram0_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) -{ - HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS); - - uint32_t write_bit, read_bit; - esp_memprot_dram0_get_uni_block_sgnf_bits(block, &write_bit, &read_bit); - - if ( write_perm ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, write_bit ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, write_bit ); - } - - if ( read_perm ) { - DPORT_SET_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, read_bit ); - } else { - DPORT_CLEAR_PERI_REG_MASK( DPORT_PMS_PRO_DRAM0_1_REG, read_bit ); - } -} - -static inline uint32_t esp_memprot_dram0_get_uni_block_read_bit(uint32_t block) -{ - HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case DRAM0_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R ); - case DRAM0_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R ); - case DRAM0_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R ); - case DRAM0_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R ); - default: - abort(); - } -} - -static inline uint32_t esp_memprot_dram0_get_uni_block_write_bit(uint32_t block) -{ - HAL_ASSERT(block < DRAM0_TOTAL_UNI_BLOCKS); - - switch ( block ) { - case DRAM0_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W ); - case DRAM0_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W ); - case DRAM0_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W ); - case DRAM0_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W ); - default: - abort(); - } -} - -static inline uint32_t esp_memprot_dram0_get_lock_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG); -} - -//lock resets automatically on CPU restart -static inline void esp_memprot_dram0_set_lock(void) -{ - DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); -} - -static inline uint32_t esp_memprot_dram0_get_perm_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG); -} - -static inline uint32_t esp_memprot_dram0_get_ena_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_3_REG); -} - -static inline uint32_t esp_memprot_dram0_get_fault_reg(void) -{ - return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_4_REG); -} - -static inline void esp_memprot_dram0_get_fault_status(uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) -{ - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - - uint32_t fault_addr = (status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S; - *faulting_address = (uint32_t *)(fault_addr | DRAM0_INTR_ST_FAULTADDR_HI); - - *op_type = (uint32_t)status_bits & DRAM0_INTR_ST_OP_RW_BIT; - *op_subtype = (uint32_t)status_bits & DRAM0_INTR_ST_OP_ATOMIC_BIT; -} - -static inline void esp_memprot_dram0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) -{ - uint32_t addr = (uint32_t)split_addr; - - //low boundary check provided by LD script. see comment in esp_memprot_iram0_set_prot() - HAL_ASSERT(addr <= DRAM0_SPL_BLOCK_HIGH); - - //set low region - int uni_blocks_low = -1; - if ( addr >= DRAM0_UNI_BLOCK_0_LOW ) { - uni_blocks_low++; - } - if ( addr >= DRAM0_UNI_BLOCK_1_LOW ) { - uni_blocks_low++; - } - if ( addr >= DRAM0_UNI_BLOCK_2_LOW ) { - uni_blocks_low++; - } - if ( addr >= DRAM0_UNI_BLOCK_3_LOW ) { - uni_blocks_low++; - } - - //set unified mgmt region - uint32_t write_bit, read_bit, uni_block_perm = 0; - for ( size_t x = 0; x < DRAM0_TOTAL_UNI_BLOCKS; x++ ) { - esp_memprot_dram0_get_uni_block_sgnf_bits(x, &write_bit, &read_bit); - if ( x <= uni_blocks_low ) { - if (lw) { - uni_block_perm |= write_bit; - } - if (lr) { - uni_block_perm |= read_bit; - } - } else { - if (hw) { - uni_block_perm |= write_bit; - } - if (hr) { - uni_block_perm |= read_bit; - } - } - } - - //check split address is WORD aligned - uint32_t reg_split_addr = addr >> 2; - HAL_ASSERT(addr == (reg_split_addr << 2)); - - //shift aligned split address to proper bit offset - reg_split_addr = (reg_split_addr << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_M; - - //prepare high & low permission mask - uint32_t permission_mask = 0; - if (lw) { - permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_L_W; - } - if (lr) { - permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_L_R; - } - if (hw) { - permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_H_W; - } - if (hr) { - permission_mask |= DPORT_PMS_PRO_DRAM0_SRAM_4_H_R; - } - - //write configuration to DPORT_PMS_PRO_DRAM0_1_REG - DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG, reg_split_addr | permission_mask | uni_block_perm); -} - -static inline void esp_memprot_dram0_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) -{ - *lw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W ); - *lr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R ); - *hw = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_W ); - *hr = DPORT_REG_GET_FIELD( DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R ); -} - + REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG) == 1) && "Value not stored to required register"); #endif +} + +static inline bool memprot_ll_get_iram0_dram0_split_line_lock(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG) == 1; +} + +static inline void *memprot_ll_get_split_addr_from_reg(const uint32_t regval, const uint32_t base) +{ + constrain_reg_fields_t reg_val; + reg_val.val = regval; + + uint32_t off = reg_val.splitaddr << I_D_SPLIT_LINE_SHIFT; + uint32_t level_off = 0; + + do { + if (reg_val.cat0 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + level_off += I_D_SRAM_SEGMENT_SIZE/2; + if (reg_val.cat1 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + level_off += I_D_SRAM_SEGMENT_SIZE; + if (reg_val.cat2 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + level_off += I_D_SRAM_SEGMENT_SIZE; + if (reg_val.cat3 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + level_off += I_D_SRAM_SEGMENT_SIZE; + if (reg_val.cat4 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + level_off += I_D_SRAM_SEGMENT_SIZE; + if (reg_val.cat5 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + level_off += I_D_SRAM_SEGMENT_SIZE; + if (reg_val.cat6 == MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA) break; + return NULL; //wrong configuration + } while(0); + + return (void *)(base + level_off + off); +} + +/* ****************************************************************************************************** + * *** IRAM0 *** + * ******************************************************************************************************/ +static inline memprot_ll_err_t memprot_ll_iram0_get_intr_source_num(const int core, uint32_t* src_num) +{ + switch (core) { + case PRO_CPU_NUM: + *src_num = ETS_CORE0_IRAM0_PMS_INTR_SOURCE; + break; + case APP_CPU_NUM: + *src_num = ETS_CORE1_IRAM0_PMS_INTR_SOURCE; + break; + default: + return MEMP_LL_FAIL; + } + + return MEMP_LL_OK; +} + +/////////////////////////////////// +// IRAM0 - SPLIT LINES +static inline uint32_t memprot_ll_get_iram0_split_line_main_I_D_regval(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG); +} + +static inline uint32_t memprot_ll_get_iram0_split_line_main_I_0_regval(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG); +} + +static inline uint32_t memprot_ll_get_iram0_split_line_main_I_1_regval(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG); +} + +static inline void memprot_ll_prepare_iram0_split_line_regval(const uint32_t addr, uint32_t* regval) +{ + //set category bits for given split line + uint32_t cat[7] = {[0 ... 6]=MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_ABOVE_SA}; + for (size_t x=0; x<7; x++) { + if (addr <= sram_rg3_level_hlimits[x]) { + cat[x] = MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA; + break; + } else { + cat[x] = MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_BELOW_SA; + } + } + + //resolve split address' significant bits + uint32_t conf_add = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V); + + //write values to required configuration-register + constrain_reg_fields_t cfg_reg_val = { + .cat0 = cat[0], + .cat1 = cat[1], + .cat2 = cat[2], + .cat3 = cat[3], + .cat4 = cat[4], + .cat5 = cat[5], + .cat6 = cat[6], + .splitaddr = conf_add, + .reserved = 0 + }; + + *regval = cfg_reg_val.val; +} + +// all the split lines registers have the same layout +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line(const void *line_addr, const uint32_t sensitive_reg) +{ + uint32_t addr = (uint32_t)line_addr; + + //sanity check + MEMP_LL_CHECK_IRAM_ADDR_IN_RANGE(addr) + MEMP_LL_CHECK_SPLIT_ADDR_ALIGNED(addr) + + uint32_t regval; + memprot_ll_prepare_iram0_split_line_regval(addr, ®val); + + REG_WRITE(sensitive_reg, regval); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(sensitive_reg) == regval) && "Value not stored to required register"); +#endif + + return MEMP_LL_OK; +} + +// set the main I/D splitting address - can be defined within either IRAM0 or DRAM0 range (IRAM0 preferred as the Memprot API stereotype) +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr) +{ + return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG); +} + +// set auxiliary split lines (IRAM0 range address required) +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_0(const void *line_addr) +{ + return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG); +} + +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_1(const void *line_addr) +{ + return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG); +} + +// get configured category bits +static inline uint32_t memprot_ll_get_iram0_split_line_main_I_D_cat(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG) & 0x3FFF; +} + +static inline uint32_t memprot_ll_get_iram0_split_line_I_0_cat(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG) & 0x3FFF; +} + +static inline uint32_t memprot_ll_get_iram0_split_line_I_1_cat(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG) & 0x3FFF; +} + +// get configured splitting address (IRAM0-based) +static inline void *memprot_ll_get_iram0_split_line_main_I_D(void) +{ + return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG), SOC_DIRAM_IRAM_LOW); +} + +static inline void *memprot_ll_get_iram0_split_line_I_0(void) +{ + return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG), SOC_DIRAM_IRAM_LOW); +} + +static inline void *memprot_ll_get_iram0_split_line_I_1(void) +{ + return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG), SOC_DIRAM_IRAM_LOW); +} + +/////////////////////////////////// +// IRAM0 - PMS CONFIGURATION + +// lock +static inline void memprot_ll_iram0_set_pms_lock(void) +{ + REG_WRITE(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG) == 1) && "Value not stored to required register"); +#endif +} + +static inline bool memprot_ll_iram0_get_pms_lock(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG) == 1; +} + +// permission settings +static inline uint32_t memprot_ll_iram0_set_permissions(const bool r, const bool w, const bool x) +{ + uint32_t permissions = 0; + if (r) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R; + } + if (w) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W; + } + if (x) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F; + } + + return permissions; +} + +static inline void memprot_ll_iram0_set_pms_area_0(const bool r, const bool w, const bool x) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0, memprot_ll_iram0_set_permissions(r, w, x)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0); + HAL_ASSERT((expected == memprot_ll_iram0_set_permissions(r, w, x)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_iram0_set_pms_area_1(const bool r, const bool w, const bool x) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1, memprot_ll_iram0_set_permissions(r, w, x)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1); + HAL_ASSERT((expected == memprot_ll_iram0_set_permissions(r, w, x)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_iram0_set_pms_area_2(const bool r, const bool w, const bool x) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2, memprot_ll_iram0_set_permissions(r, w, x)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2); + HAL_ASSERT((expected == memprot_ll_iram0_set_permissions(r, w, x)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_iram0_set_pms_area_3(const bool r, const bool w, const bool x) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3, memprot_ll_iram0_set_permissions(r, w, x)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3); + HAL_ASSERT((expected == memprot_ll_iram0_set_permissions(r, w, x)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_iram0_get_permissions(const uint32_t perms, bool *r, bool *w, bool *x) +{ + *r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R; + *w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W; + *x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F; +} + +static inline void memprot_ll_iram0_get_pms_area_0(bool *r, bool *w, bool *x) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0); + memprot_ll_iram0_get_permissions(permissions, r, w, x); +} + +static inline void memprot_ll_iram0_get_pms_area_1(bool *r, bool *w, bool *x) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1); + memprot_ll_iram0_get_permissions(permissions, r, w, x); +} + +static inline void memprot_ll_iram0_get_pms_area_2(bool *r, bool *w, bool *x) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2); + memprot_ll_iram0_get_permissions(permissions, r, w, x); +} + +static inline void memprot_ll_iram0_get_pms_area_3(bool *r, bool *w, bool *x) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3); + memprot_ll_iram0_get_permissions(permissions, r, w, x); +} + + +/////////////////////////////////// +// IRAM0 - MONITOR + +// lock +static inline memprot_ll_err_t memprot_ll_iram0_set_monitor_lock(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_lock(const int core, bool* locked) +{ + switch (core) { + case PRO_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG) == 1; + break; + case APP_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_0_REG) == 1; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +// interrupt enable/clear +static inline memprot_ll_err_t memprot_ll_iram0_set_monitor_en(const int core, const bool enable) +{ + switch (core) { + case PRO_CPU_NUM: + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN) > 0) && "Value not stored to required register"); +#endif + } else { + REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN) == 0) && "Value not stored to required register"); +#endif + } + break; + case APP_CPU_NUM: + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_EN) > 0) && "Value not stored to required register"); +#endif + } else { + REG_CLR_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_EN) == 0) && "Value not stored to required register"); +#endif + } + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_en(const int core, bool* enabled) +{ + switch (core) { + case PRO_CPU_NUM: + *enabled = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN) == 1; + break; + case APP_CPU_NUM: + *enabled = REG_GET_FIELD(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_EN) == 1; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_set_monitor_intrclr(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_SET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_reset_monitor_intrclr(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR) == 0) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_CLR_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_CLR) == 0) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_intrclr(const int core, bool* cleared) +{ + switch (core) { + case PRO_CPU_NUM: + *cleared = REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0; + break; + case APP_CPU_NUM: + *cleared = REG_GET_BIT(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_enable_register(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG); + break; + case APP_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_1_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +// permission violation status +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_status_intr(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_INTR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_status_fault_wr(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_status_fault_loadstore(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_status_fault_world(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_status_fault_addr(const int core, void** addr) +{ + uint32_t reg_off; + + switch (core) { + case PRO_CPU_NUM: + reg_off = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR); + break; + case APP_CPU_NUM: + reg_off = REG_GET_FIELD(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + *addr = (void*)(reg_off > 0 ? (reg_off << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0); + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_iram0_get_monitor_status_register(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG); + break; + case APP_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + + +/* ****************************************************************************************************** + * *** RTC_FAST *** + */ + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_intr_source_num(const int core, uint32_t* src_num) +{ + switch (core) { + case PRO_CPU_NUM: + *src_num = ETS_CORE0_PIF_PMS_INTR_SOURCE; + break; + case APP_CPU_NUM: + *src_num = ETS_CORE1_PIF_PMS_INTR_SOURCE; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +//shared PIF PMS lock +//!!!: use after ALL the constraints have been set +static inline memprot_ll_err_t memprot_ll_set_pif_constraint_lock(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_get_pif_constraint_lock(const int core, bool* locked) +{ + switch (core) { + case PRO_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG) == 1; + break; + case APP_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_0_REG) == 1; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_splitaddr_register(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG); + break; + case APP_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_9_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +/* ******************************** + * IRAM0 RTCFAST - SPLIT LINES + */ + +static inline memprot_ll_err_t memprot_ll_set_rtcfast_split_line(const int core, const void *line_addr, const memprot_ll_world_t world) +{ + uint32_t addr = (uint32_t)line_addr; + + if (addr < SOC_RTC_IRAM_LOW || addr >= SOC_RTC_IRAM_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE; + } + + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } + + if (core != PRO_CPU_NUM && core != APP_CPU_NUM) { + return MEMP_LL_ERR_CORE_INVALID; + } + + uint32_t mask; + uint32_t val; + + switch (world) { + case MEMP_LL_WORLD_0: + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M; + val = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V; + break; + case MEMP_LL_WORLD_1: + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M; + val = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_V : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_V; + break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + uint32_t reg = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_9_REG; + + CLEAR_PERI_REG_MASK(reg, mask); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((GET_PERI_REG_MASK(reg, mask) == 0) && "Value not stored to required register"); +#endif + REG_SET_BITS(reg, mask, (addr >> 2) & val); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_READ(reg) & mask; + HAL_ASSERT((expected == ((addr >> 2) & val)) && "Value not stored to required register"); +#endif + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_get_rtcfast_split_line(const int core, const memprot_ll_world_t world, void **line_addr) +{ + if (core != PRO_CPU_NUM && core != APP_CPU_NUM) { + return MEMP_LL_ERR_CORE_INVALID; + } + + uint32_t mask; + uint32_t shift; + + switch (world) { + case MEMP_LL_WORLD_0: + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M; + shift = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_S : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_S; + break; + case MEMP_LL_WORLD_1: + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M; + shift = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_S : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_S; + break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + uint32_t reg_addr = REG_READ(core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_9_REG); + + *line_addr = (void *)((((reg_addr & mask) >> shift) << 2) + SOC_RTC_IRAM_LOW); + + return MEMP_LL_OK; +} + +/////////////////////////////////// +// RTC_FAST - PMS CONFIGURATION + +// permission settings +static inline uint32_t memprot_ll_rtcfast_set_permissions(const bool r, const bool w, const bool x) +{ + uint32_t permissions = 0; + if (r) { + permissions |= SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R; + } + if (w) { + permissions |= SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W; + } + if (x) { + permissions |= SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F; + } + + return permissions; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_set_pms_area(const int core, const bool r, const bool w, const bool x, const memprot_ll_world_t world, const memprot_ll_area_t area) +{ + if (core != PRO_CPU_NUM && core != APP_CPU_NUM) { + return MEMP_LL_ERR_CORE_INVALID; + } + + uint32_t bits; + uint32_t mask; + + switch (world) { + case MEMP_LL_WORLD_0: { + switch (area) { + case MEMP_LL_AREA_LOW: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << (core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_S : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_S); + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_M; + break; + case MEMP_LL_AREA_HIGH: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << (core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_S : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_S); + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_M; + break; + default: + return MEMP_LL_ERR_AREA_INVALID; + } + } break; + case MEMP_LL_WORLD_1: { + switch (area) { + case MEMP_LL_AREA_LOW: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << (core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_S : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_S); + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_M; + break; + case MEMP_LL_AREA_HIGH: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << (core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_S : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_S); + mask = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_M : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_M; + break; + default: + return MEMP_LL_ERR_AREA_INVALID; + } + } break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + uint32_t reg = core == PRO_CPU_NUM ? SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG : SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_10_REG; + + CLEAR_PERI_REG_MASK(reg, mask); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((GET_PERI_REG_MASK(reg, mask) == 0) && "Value not stored to required register"); +#endif + REG_SET_BITS(reg, bits, mask); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_READ(reg) & mask; + HAL_ASSERT((expected == bits) && "Value not stored to required register"); +#endif + + return MEMP_LL_OK; +} + +static inline void memprot_ll_rtcfast_get_permissions(const uint32_t perms, bool *r, bool *w, bool *x) +{ + *r = perms & SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R; + *w = perms & SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W; + *x = perms & SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_pms_area(const int core, bool *r, bool *w, bool *x, const memprot_ll_world_t world, const memprot_ll_area_t area) +{ + if (core != PRO_CPU_NUM && core != APP_CPU_NUM) { + return MEMP_LL_ERR_CORE_INVALID; + } + + uint32_t permissions = 0; + + switch (world) { + case MEMP_LL_WORLD_0: { + switch (area) { + case MEMP_LL_AREA_LOW: + if (core == PRO_CPU_NUM) { + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L); + } else { + permissions = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L); + } + break; + case MEMP_LL_AREA_HIGH: + if (core == PRO_CPU_NUM) { + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H); + } else { + permissions = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H); + } + break; + default: + return MEMP_LL_ERR_AREA_INVALID; + } + } break; + case MEMP_LL_WORLD_1: { + switch (area) { + case MEMP_LL_AREA_LOW: + if (core == PRO_CPU_NUM) { + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L); + } else { + permissions = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L); + } + break; + case MEMP_LL_AREA_HIGH: + if (core == PRO_CPU_NUM) { + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H); + } else { + permissions = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H); + } + break; + default: + return MEMP_LL_ERR_AREA_INVALID; + } + } break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + memprot_ll_rtcfast_get_permissions(permissions, r, w, x); + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_permission_register(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG); + break; + case APP_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_1_PIF_PMS_CONSTRAIN_10_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +/////////////////////////////////// +// RTC_FAST - MONITOR + +// lock +static inline memprot_ll_err_t memprot_ll_rtcfast_set_monitor_lock(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_1_PIF_PMS_MONITOR_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_1_PIF_PMS_MONITOR_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_lock(const int core, bool* locked) +{ + switch (core) { + case PRO_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG) == 1; + break; + case APP_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_1_PIF_PMS_MONITOR_0_REG) == 1; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +// interrupt enable/clear +static inline memprot_ll_err_t memprot_ll_rtcfast_set_monitor_en(const int core, const bool enable) +{ + switch (core) { + case PRO_CPU_NUM: + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN) > 0) && "Value not stored to required register"); +#endif + } else { + REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN) == 0) && "Value not stored to required register"); +#endif + } + break; + case APP_CPU_NUM: + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_EN) > 0) && "Value not stored to required register"); +#endif + } else { + REG_CLR_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_EN) == 0) && "Value not stored to required register"); +#endif + } + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_en(const int core, bool* enabled) +{ + switch (core) { + case PRO_CPU_NUM: + *enabled = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN) > 0; + break; + case APP_CPU_NUM: + *enabled = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_EN) > 0; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_intrclr(const int core, bool* cleared) +{ + switch (core) { + case PRO_CPU_NUM: + *cleared = REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR) > 0; + break; + case APP_CPU_NUM: + *cleared = REG_GET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_CLR) > 0; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_set_monitor_intrclr(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR) > 0) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_SET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_CLR) > 0) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_reset_monitor_intrclr(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR) == 0) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_CLR_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_CLR) == 0) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_register(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG); + break; + case APP_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_1_PIF_PMS_MONITOR_1_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +// permission violation status +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_status_intr(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_INTR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_status_fault_addr(const int core, void** addr) +{ + switch (core) { + case PRO_CPU_NUM: + *addr = (void*)REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_3_REG); + break; + case APP_CPU_NUM: + *addr = (void*)REG_READ(SENSITIVE_CORE_1_PIF_PMS_MONITOR_3_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_status_fault_world(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_status_fault_loadstore(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_monitor_status_fault_wr(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + + +/* ****************************************************************************************************** + * *** DRAM0 *** + * ******************************************************************************************************/ + +static inline memprot_ll_err_t memprot_ll_dram0_get_intr_source_num(const int core, uint32_t* src_num) +{ + switch (core) { + case PRO_CPU_NUM: + *src_num = ETS_CORE0_DRAM0_PMS_INTR_SOURCE; + break; + case APP_CPU_NUM: + *src_num = ETS_CORE1_DRAM0_PMS_INTR_SOURCE; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +/////////////////////////////////// +// DRAM0 - SPLIT LINES +static inline uint32_t memprot_ll_get_dram0_split_line_main_D_0_regval(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG); +} + +static inline uint32_t memprot_ll_get_dram0_split_line_main_D_1_regval(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG); +} + +static inline void memprot_ll_prepare_dram0_split_line_regval(const uint32_t addr, uint32_t* regval) +{ + //set category bits for given split line + uint32_t cat[7] = {[0 ... 6]=MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_ABOVE_SA}; + for (size_t x=0; x<7; x++) { + if (addr <= MAP_IRAM_TO_DRAM(sram_rg3_level_hlimits[x])) { + cat[x] = MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA; + break; + } else { + cat[x] = MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_BELOW_SA; + } + } + + //resolve split address' significant bits + uint32_t conf_add = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_DRAM0_DMA_SRAM_LINE_0_SPLITADDR_V); + + //write values to required configuration-register + constrain_reg_fields_t cfg_reg_val = { + .cat0 = cat[0], + .cat1 = cat[1], + .cat2 = cat[2], + .cat3 = cat[3], + .cat4 = cat[4], + .cat5 = cat[5], + .cat6 = cat[6], + .splitaddr = conf_add, + .reserved = 0 + }; + + + *regval = cfg_reg_val.val; +} + +static inline memprot_ll_err_t memprot_ll_set_dram0_split_line(const void *line_addr, const uint32_t sensitive_reg) +{ + uint32_t addr = (uint32_t)line_addr; + + //sanity check + MEMP_LL_CHECK_DRAM_ADDR_IN_RANGE(addr) + MEMP_LL_CHECK_SPLIT_ADDR_ALIGNED(addr) + + uint32_t regval; + memprot_ll_prepare_dram0_split_line_regval(addr, ®val); + + REG_WRITE(sensitive_reg, regval); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(sensitive_reg) == regval) && "Value not stored to required register"); +#endif + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_0(const void *line_addr) +{ + return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG); +} + +static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_1(const void *line_addr) +{ + return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG); +} + +static inline void *memprot_ll_get_dram0_split_line_D_0(void) +{ + return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG), SOC_DIRAM_DRAM_LOW); +} + +static inline void *memprot_ll_get_dram0_split_line_D_1(void) +{ + return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG), SOC_DIRAM_DRAM_LOW); +} + +static inline uint32_t memprot_ll_get_dram0_split_line_D_0_cat(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG) & 0x3FFF; +} + +static inline uint32_t memprot_ll_get_dram0_split_line_D_1_cat(void) +{ + return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG) & 0x3FFF; +} + +/////////////////////////////////// +// DRAM0 - PMS CONFIGURATION + +// lock +static inline void memprot_ll_dram0_set_pms_lock(void) +{ + REG_WRITE(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG) == 1) && "Value not stored to required register"); +#endif +} + +static inline bool memprot_ll_dram0_get_pms_lock(void) +{ + return REG_READ(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG) == 1; +} + +// permission settings +static inline uint32_t memprot_ll_dram0_set_permissions(const bool r, const bool w) +{ + uint32_t permissions = 0; + if (r) { + permissions |= SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R; + } + if (w) { + permissions |= SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W; + } + + return permissions; +} + +static inline void memprot_ll_dram0_set_pms_area_0(const bool r, const bool w) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0, memprot_ll_dram0_set_permissions(r, w)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0); + HAL_ASSERT((expected == memprot_ll_dram0_set_permissions(r, w)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_dram0_set_pms_area_1(const bool r, const bool w) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1, memprot_ll_dram0_set_permissions(r, w)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1); + HAL_ASSERT((expected == memprot_ll_dram0_set_permissions(r, w)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_dram0_set_pms_area_2(const bool r, const bool w) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2, memprot_ll_dram0_set_permissions(r, w)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2); + HAL_ASSERT((expected == memprot_ll_dram0_set_permissions(r, w)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_dram0_set_pms_area_3(const bool r, const bool w) +{ + REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3, memprot_ll_dram0_set_permissions(r, w)); +#ifdef PMS_DEBUG_ASSERTIONS + uint32_t expected = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3); + HAL_ASSERT((expected == memprot_ll_dram0_set_permissions(r, w)) && "Value not stored to required register"); +#endif +} + +static inline void memprot_ll_dram0_get_permissions(const uint32_t perms, bool *r, bool *w ) +{ + *r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R; + *w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W; +} + +static inline void memprot_ll_dram0_get_pms_area_0(bool *r, bool *w) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0); + memprot_ll_dram0_get_permissions(permissions, r, w); +} + +static inline void memprot_ll_dram0_get_pms_area_1(bool *r, bool *w) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1); + memprot_ll_dram0_get_permissions(permissions, r, w); +} + +static inline void memprot_ll_dram0_get_pms_area_2(bool *r, bool *w) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2); + memprot_ll_dram0_get_permissions(permissions, r, w); +} + +static inline void memprot_ll_dram0_get_pms_area_3(bool *r, bool *w) +{ + uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3); + memprot_ll_dram0_get_permissions(permissions, r, w); +} + + +/////////////////////////////////// +// DRAM0 - MONITOR + +// lock +static inline memprot_ll_err_t memprot_ll_dram0_set_monitor_lock(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_WRITE(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_0_REG, 1); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_READ(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_0_REG) == 1) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_lock(const int core, bool* locked) +{ + switch (core) { + case PRO_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG) == 1; + break; + case APP_CPU_NUM: + *locked = REG_READ(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_0_REG) == 1; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +// interrupt enable/clear +static inline memprot_ll_err_t memprot_ll_dram0_set_monitor_en(const int core, const bool enable) +{ + switch (core) { + case PRO_CPU_NUM: + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0) && "Value not stored to required register"); +#endif + } else { + REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN) == 0) && "Value not stored to required register"); +#endif + } + break; + case APP_CPU_NUM: + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0) && "Value not stored to required register"); +#endif + } else { + REG_CLR_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_EN); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_EN) == 0) && "Value not stored to required register"); +#endif + } + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_en(const int core, bool* enabled) +{ + switch (core) { + case PRO_CPU_NUM: + *enabled = REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0; + break; + case APP_CPU_NUM: + *enabled = REG_GET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_set_monitor_intrclr(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_SET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_reset_monitor_intrclr(const int core) +{ + switch (core) { + case PRO_CPU_NUM: + REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR) == 0) && "Value not stored to required register"); +#endif + break; + case APP_CPU_NUM: + REG_CLR_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_CLR); +#ifdef PMS_DEBUG_ASSERTIONS + HAL_ASSERT((REG_GET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_CLR) == 0) && "Value not stored to required register"); +#endif + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_intrclr(const int core, bool* cleared) +{ + switch (core) { + case PRO_CPU_NUM: + *cleared = REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0; + break; + case APP_CPU_NUM: + *cleared = REG_GET_BIT(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0; + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_enable_register(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG); + break; + case APP_CPU_NUM: + *regval = REG_READ(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_1_REG); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +// permission violation status +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_status_intr(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_INTR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_status_fault_world(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_status_fault_addr(const int core, void** addr) +{ + uint32_t reg_off; + + switch (core) { + case PRO_CPU_NUM: + reg_off = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR); + break; + case APP_CPU_NUM: + reg_off = REG_GET_FIELD(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + *addr = (void*)(reg_off > 0 ? (reg_off << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0); + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_status_fault_wr(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_dram0_get_monitor_status_fault_byte_en(const int core, uint32_t* regval) +{ + switch (core) { + case PRO_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN); + break; + case APP_CPU_NUM: + *regval = REG_GET_FIELD(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN); + break; + default: + return MEMP_LL_ERR_CORE_INVALID; + } + + return MEMP_LL_OK; +} #ifdef __cplusplus } diff --git a/components/hal/include/hal/memprot_types.h b/components/hal/include/hal/memprot_types.h index 15e3c3959a..e76c0300e6 100644 --- a/components/hal/include/hal/memprot_types.h +++ b/components/hal/include/hal/memprot_types.h @@ -6,6 +6,9 @@ #pragma once +#include "soc/soc.h" +#include "soc/memprot_defs.h" + #ifdef __cplusplus extern "C" { #endif @@ -16,13 +19,14 @@ extern "C" { */ typedef enum { MEMP_LL_OK = 0, - MEMP_LL_FAIL = 1, MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE = 2, MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2, /* temporary duplicate for S2 builds */ MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED = 3, MEMP_LL_ERR_UNI_BLOCK_INVALID = 4, MEMP_LL_ERR_AREA_INVALID = 5, - MEMP_LL_ERR_WORLD_INVALID = 6 + MEMP_LL_ERR_WORLD_INVALID = 6, + MEMP_LL_ERR_CORE_INVALID = 7, + MEMP_LL_FAIL = -1, } memprot_ll_err_t; /** @@ -45,6 +49,19 @@ typedef enum { MEMP_LL_AREA_HIGH = 2 } memprot_ll_area_t; +//auxiliary macros & defines +#define SOC_I_D_OFFSET (SOC_DIRAM_IRAM_LOW - SOC_DIRAM_DRAM_LOW) +#define MAP_DRAM_TO_IRAM(addr) (addr + SOC_I_D_OFFSET) +#define MAP_IRAM_TO_DRAM(addr) (addr - SOC_I_D_OFFSET) + +#define MEMP_LL_CHECK_IRAM_ADDR_IN_RANGE(x) if (x < SOC_DIRAM_IRAM_LOW || x >= SOC_DIRAM_IRAM_HIGH) { return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE; } +#define MEMP_LL_CHECK_DRAM_ADDR_IN_RANGE(x) if (x < SOC_DIRAM_DRAM_LOW || x >= SOC_DIRAM_DRAM_HIGH) { return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE; } +#define MEMP_LL_CHECK_SPLIT_ADDR_ALIGNED(x) if (x % I_D_SPLIT_LINE_ALIGN != 0) { return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; } + +#define MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_BELOW_SA 0x0 //0b00 +#define MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_EQUAL_SA 0x2 //0b10 +#define MEMP_LL_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_BITS_ABOVE_SA 0x3 //0b11 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c3/include/soc/memprot_defs.h b/components/soc/esp32c3/include/soc/memprot_defs.h index b08e1f83b4..fe4f20e3bd 100644 --- a/components/soc/esp32c3/include/soc/memprot_defs.h +++ b/components/soc/esp32c3/include/soc/memprot_defs.h @@ -35,14 +35,6 @@ typedef union { #define DRAM_SRAM_START 0x3FC7C000 -#ifndef MAP_DRAM_TO_IRAM -#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + SOC_IRAM_LOW) -#endif - -#ifndef MAP_IRAM_TO_DRAM -#define MAP_IRAM_TO_DRAM(addr) (addr - SOC_IRAM_LOW + DRAM_SRAM_START) -#endif - //IRAM0 //16kB (ICACHE) diff --git a/components/soc/esp32s3/include/soc/memprot_defs.h b/components/soc/esp32s3/include/soc/memprot_defs.h new file mode 100644 index 0000000000..b9c705ad06 --- /dev/null +++ b/components/soc/esp32s3/include/soc/memprot_defs.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/sensitive_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { + struct { + uint32_t cat0 : 2; + uint32_t cat1 : 2; + uint32_t cat2 : 2; + uint32_t cat3 : 2; + uint32_t cat4 : 2; + uint32_t cat5 : 2; + uint32_t cat6 : 2; + uint32_t splitaddr : 8; + uint32_t reserved : 10; + }; + uint32_t val; +} constrain_reg_fields_t; + +#define I_D_SRAM_SEGMENT_SIZE 0x10000 +#define I_D_SPLIT_LINE_ALIGN 0x100 +#define I_D_SPLIT_LINE_SHIFT 0x8 +#define I_D_FAULT_ADDR_SHIFT 0x2 + +//IRAM0 +#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R 0x1 +#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W 0x2 +#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F 0x4 + +//DRAM0 +#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R 0x1 +#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W 0x2 + +//RTC FAST +#define SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W 0x1 +#define SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R 0x2 +#define SENSITIVE_CORE_X_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F 0x4 + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32s3/include/soc/soc.h b/components/soc/esp32s3/include/soc/soc.h index bc94faf5f6..1b4ac4f696 100644 --- a/components/soc/esp32s3/include/soc/soc.h +++ b/components/soc/esp32s3/include/soc/soc.h @@ -266,7 +266,8 @@ #define ETS_TG0_T1_INUM 10 /**< use edge interrupt*/ #define ETS_FRC1_INUM 22 #define ETS_T1_WDT_INUM 24 -#define ETS_CACHEERR_INUM 25 +#define ETS_MEMACCESS_ERR_INUM 25 +#define ETS_CACHEERR_INUM ETS_MEMACCESS_ERR_INUM #define ETS_IPC_ISR_INUM 28 //CPU0 Interrupt number used in ROM, should be cancelled in SDK diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 31b2b09633..92d76bd9c3 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -822,7 +822,6 @@ components/hal/esp32s2/include/hal/trace_ll.h components/hal/esp32s2/include/hal/usb_ll.h components/hal/esp32s2/touch_sensor_hal.c components/hal/esp32s3/include/hal/aes_ll.h -components/hal/esp32s3/include/hal/memprot_ll.h components/hal/esp32s3/include/hal/mpu_ll.h components/hal/esp32s3/include/hal/rwdt_ll.h components/hal/esp32s3/include/hal/sha_ll.h diff --git a/tools/test_apps/system/memprot/CMakeLists.txt b/tools/test_apps/system/memprot/CMakeLists.txt index 1e073a791d..d6516a0ca3 100644 --- a/tools/test_apps/system/memprot/CMakeLists.txt +++ b/tools/test_apps/system/memprot/CMakeLists.txt @@ -1,9 +1,12 @@ cmake_minimum_required(VERSION 3.16) -if((IDF_TARGET STREQUAL "esp32s2") OR (IDF_TARGET STREQUAL "esp32c3")) +if((IDF_TARGET STREQUAL "esp32s2") OR (IDF_TARGET STREQUAL "esp32c3") OR (IDF_TARGET STREQUAL "esp32s3")) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_memprot) - target_link_libraries(${project_elf} PRIVATE "-Wl,--wrap=esp_panic_handler") + target_link_libraries(${project_elf} PRIVATE + "-Wl,--wrap=esp_panic_handler" + "-Wl,--wrap=esp_panic_handler_reconfigure_wdts" + "-Wl,--wrap=soc_hal_stall_core") endif() diff --git a/tools/test_apps/system/memprot/README.md b/tools/test_apps/system/memprot/README.md index 735329420b..60d039cddc 100644 --- a/tools/test_apps/system/memprot/README.md +++ b/tools/test_apps/system/memprot/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C3 | ESP32-S2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | diff --git a/tools/test_apps/system/memprot/app_test.py b/tools/test_apps/system/memprot/app_test.py index 1530dc4219..7d7590e9b1 100644 --- a/tools/test_apps/system/memprot/app_test.py +++ b/tools/test_apps/system/memprot/app_test.py @@ -16,11 +16,31 @@ MEM_TEST_S2 = [ MEM_TEST_C3 = [ ['IRAM0_SRAM', 'WRX'], ['DRAM0_SRAM', 'WR'], - ['IRAM0_RTCFAST', 'WRX'], + ['IRAM0_RTCFAST', 'WRX'] +] + +MEM_TEST_S3_MULTI = [ + # instruction execute test temporarily disabled + # ['IRAM0_SRAM (core 0)', 'WRX'], + ['IRAM0_SRAM (core 0)', 'WR'], + ['DRAM0_SRAM (core 0)', 'WR'], + # instruction execute test temporarily disabled + # ['IRAM0_SRAM (core 1)', 'WRX'], + ['IRAM0_SRAM (core 1)', 'WR'], + ['DRAM0_SRAM (core 1)', 'WR'] + # temporarily disabled unless IDF-5208 gets merged + # ['IRAM0_RTCFAST', 'WR'], +] + +MEM_TEST_S3_UNI = [ + ['IRAM0_SRAM (core 0)', 'WRX'], + ['DRAM0_SRAM (core 0)', 'WR'] + # temporarily disabled unless IDF-5208 gets merged + # ['IRAM0_RTCFAST', 'WR'], ] -@ttfw_idf.idf_custom_test(env_tag='Example_GENERIC', target=['esp32c3', 'esp32s2'], group='test-apps') +@ttfw_idf.idf_custom_test(env_tag='Example_GENERIC', target=['esp32c3', 'esp32s2', 'esp32s3'], group='test-apps') def test_memprot(env, extra_data): dut = env.get_dut('memprot', 'tools/test_apps/system/memprot') @@ -29,10 +49,17 @@ def test_memprot(env, extra_data): mem_test_cfg = [] current_target = dut.app.get_sdkconfig()['CONFIG_IDF_TARGET'].replace('"','').lower() + try: + unicore = dut.app.get_sdkconfig()['CONFIG_FREERTOS_UNICORE'] + except KeyError: + unicore = 'n' + if current_target == 'esp32c3': mem_test_cfg = MEM_TEST_C3 elif current_target == 'esp32s2': mem_test_cfg = MEM_TEST_S2 + elif current_target == 'esp32s3': + mem_test_cfg = MEM_TEST_S3_UNI if unicore == 'y' else MEM_TEST_S3_MULTI Utility.console_log('Test cfg: ' + current_target) diff --git a/tools/test_apps/system/memprot/main/CMakeLists.txt b/tools/test_apps/system/memprot/main/CMakeLists.txt index 3b4a00a98b..7a4baca5a7 100644 --- a/tools/test_apps/system/memprot/main/CMakeLists.txt +++ b/tools/test_apps/system/memprot/main/CMakeLists.txt @@ -4,4 +4,7 @@ if( IDF_TARGET STREQUAL "esp32s2" ) elseif( IDF_TARGET STREQUAL "esp32c3" ) idf_component_register(SRCS "esp32c3/test_memprot_main.c" "esp32c3/test_panic.c" "esp32c3/return_from_panic.S" INCLUDE_DIRS "") +elseif( IDF_TARGET STREQUAL "esp32s3" ) + idf_component_register(SRCS "esp32s3/test_memprot_main.c" "esp32s3/test_panic.c" + INCLUDE_DIRS "") endif() diff --git a/tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c b/tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c index ab05cfedc7..ba1429cb57 100644 --- a/tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c +++ b/tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -115,7 +115,7 @@ static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_me esp_rom_printf("FAULT ["); void *addr; - esp_err_t err = esp_mprot_get_violate_addr(mem_type, &addr, NULL); + esp_err_t err = esp_mprot_get_violate_addr(mem_type, &addr, DEFAULT_CPU_NUM); if (err == ESP_OK) { esp_rom_printf("fault addr: 0x%08X,", (uint32_t)addr); } else { @@ -123,7 +123,7 @@ static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_me } esp_mprot_pms_world_t world; - err = esp_mprot_get_violate_world(mem_type, &world, NULL); + err = esp_mprot_get_violate_world(mem_type, &world, DEFAULT_CPU_NUM); if (err == ESP_OK) { esp_rom_printf(" world: %s,", esp_mprot_pms_world_to_str(world)); } else { @@ -131,7 +131,7 @@ static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_me } uint32_t oper; - err = esp_mprot_get_violate_operation(mem_type, &oper, NULL); + err = esp_mprot_get_violate_operation(mem_type, &oper, DEFAULT_CPU_NUM); if (err == ESP_OK) { esp_rom_printf(" operation: %s", esp_mprot_oper_type_to_str(oper)); } else { @@ -141,7 +141,7 @@ static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_me // DRAM/DMA fault: check byte-enables if (mem_type == MEMPROT_TYPE_DRAM0_SRAM) { uint32_t byteen; - err = esp_mprot_get_violate_byte_enables(mem_type, &byteen, NULL); + err = esp_mprot_get_violate_byte_enables(mem_type, &byteen, DEFAULT_CPU_NUM); if (err == ESP_OK) { esp_rom_printf(", byte en: 0x%08X", byteen); } else { @@ -173,15 +173,15 @@ static void test_mprot_check_test_result(esp_mprot_mem_t mem_type, bool expected static void test_mprot_clear_all_interrupts(void) { - esp_err_t err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL); + esp_err_t err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err)); } - err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL); + err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err)); } - err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL); + err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err)); } @@ -206,7 +206,7 @@ static void test_mprot_get_permissions(bool low, esp_mprot_mem_t mem_type, bool } uint32_t flags; - esp_err_t err = esp_mprot_get_pms_area(area, &flags); + esp_err_t err = esp_mprot_get_pms_area(area, &flags, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_get_pms_area() failed (%s) - test_mprot_get_permissions\n", esp_err_to_name(err)); return; @@ -240,17 +240,17 @@ static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool switch (mem_type) { case MEMPROT_TYPE_IRAM0_SRAM: { if (low) { - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } } else { - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } } @@ -258,17 +258,17 @@ static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool break; case MEMPROT_TYPE_DRAM0_SRAM: { if (low) { - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } } else { - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } } @@ -276,11 +276,11 @@ static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool break; case MEMPROT_TYPE_IRAM0_RTCFAST: { if (low) { - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } } else { - if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, flags)) != ESP_OK) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, flags, DEFAULT_CPU_NUM)) != ESP_OK) { break; } } @@ -311,7 +311,7 @@ static void test_mprot_read(esp_mprot_mem_t mem_type) const uint32_t test_val = 100; //temporarily allow WRITE for setting the test values - esp_err_t err = esp_mprot_set_monitor_en(mem_type, false); + esp_err_t err = esp_mprot_set_monitor_en(mem_type, false, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); return; @@ -329,7 +329,7 @@ static void test_mprot_read(esp_mprot_mem_t mem_type) test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL); //reenable monitoring - err = esp_mprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, true, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); return; @@ -337,7 +337,7 @@ static void test_mprot_read(esp_mprot_mem_t mem_type) //perform READ test in low region esp_rom_printf("%s read low: ", esp_mprot_mem_type_to_str(mem_type)); - err = esp_mprot_monitor_clear_intr(mem_type, NULL); + err = esp_mprot_monitor_clear_intr(mem_type, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); return; @@ -354,7 +354,7 @@ static void test_mprot_read(esp_mprot_mem_t mem_type) //perform READ in high region esp_rom_printf("%s read high: ", esp_mprot_mem_type_to_str(mem_type)); - err = esp_mprot_monitor_clear_intr(mem_type, NULL); + err = esp_mprot_monitor_clear_intr(mem_type, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); return; @@ -381,7 +381,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type) test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL); //ensure READ enabled - esp_err_t err = esp_mprot_set_monitor_en(mem_type, false); + esp_err_t err = esp_mprot_set_monitor_en(mem_type, false, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); return; @@ -390,7 +390,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type) test_mprot_set_permissions(true, mem_type, true, write_perm_low, is_exec_mem ? &exec_perm_low : NULL); test_mprot_set_permissions(false, mem_type, true, write_perm_high, is_exec_mem ? &exec_perm_high : NULL); - err = esp_mprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, true, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); return; @@ -402,7 +402,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type) //perform WRITE in low region esp_rom_printf("%s write low: ", esp_mprot_mem_type_to_str(mem_type)); - err = esp_mprot_monitor_clear_intr(mem_type, NULL); + err = esp_mprot_monitor_clear_intr(mem_type, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); return; @@ -421,7 +421,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type) //perform WRITE in high region esp_rom_printf("%s write high: ", esp_mprot_mem_type_to_str(mem_type)); - err = esp_mprot_monitor_clear_intr(mem_type, NULL); + err = esp_mprot_monitor_clear_intr(mem_type, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); return; @@ -439,7 +439,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type) } //restore original permissions - err = esp_mprot_set_monitor_en(mem_type, false); + err = esp_mprot_set_monitor_en(mem_type, false, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); return; @@ -448,7 +448,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type) test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL); test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL); - err = esp_mprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, true, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); return; @@ -469,14 +469,14 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type) //temporarily enable READ/WRITE test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low); test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high); - esp_err_t err = esp_mprot_set_monitor_en(mem_type, false); + esp_err_t err = esp_mprot_set_monitor_en(mem_type, false, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); return; } test_mprot_set_permissions(true, mem_type, true, true, &exec_perm_low); test_mprot_set_permissions(false, mem_type, true, true, &exec_perm_high); - err = esp_mprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, true, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); return; @@ -496,7 +496,7 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type) //LOW REGION: clear the intr flag & try to execute the code injected esp_rom_printf("%s exec low: ", esp_mprot_mem_type_to_str(mem_type)); - err = esp_mprot_monitor_clear_intr(mem_type, NULL); + err = esp_mprot_monitor_clear_intr(mem_type, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); return; @@ -522,7 +522,7 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type) //HIGH REGION: clear the intr-on flag & try to execute the code injected esp_rom_printf("%s exec high: ", esp_mprot_mem_type_to_str(mem_type)); - err = esp_mprot_monitor_clear_intr(mem_type, NULL); + err = esp_mprot_monitor_clear_intr(mem_type, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); return; @@ -546,14 +546,14 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type) } //restore original permissions - err = esp_mprot_set_monitor_en(mem_type, false); + err = esp_mprot_set_monitor_en(mem_type, false, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); return; } test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low); test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high); - err = esp_mprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, true, DEFAULT_CPU_NUM); if (err != ESP_OK) { esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); return; diff --git a/tools/test_apps/system/memprot/main/esp32s3/test_memprot_main.c b/tools/test_apps/system/memprot/main/esp32s3/test_memprot_main.c new file mode 100644 index 0000000000..09068fe58b --- /dev/null +++ b/tools/test_apps/system/memprot/main/esp32s3/test_memprot_main.c @@ -0,0 +1,691 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "hal/memprot_types.h" +#include "soc/memprot_defs.h" +#include "esp_private/esp_memprot_internal.h" +#include "esp_memprot.h" +#include "esp_rom_sys.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +/** + * ESP32S3 MEMORY PROTECTION MODULE TEST + * ===================================== + * + * In order to safely test all the memprot features, this test application uses memprot default settings + * plus proprietary testing buffers: + * - s_iram_test_buffer (.iram_end_test, 1kB) - all IRAM/DRAM low region operations, test-only section + * - s_dram_test_buffer (.dram0.data, 1kB) - all IRAM/DRAM high region operations, standard section + * - s_rtc_text_test_buffer (.rtc_text_end_test, 1kB) - all RTCFAST low region operations, test-only section + * - s_rtc_data_test_buffer (.rtc.data, 1kB) - all RTCFAST high region operations, standard section + * Testing addresses are set to the middle of the testing buffers: + * - test_ptr_low = (s_iram_test_buffer | s_rtc_text_test_buffer) + 0x200 + * - test_ptr_high = (s_dram_test_buffer | s_rtc_data_test_buffer) + 0x200 + * Each operation is tested at both low & high region addresses. + * Each test result checked against expected status of PMS violation interrupt status and + * against expected value stored in the memory tested (where applicable) + * + * Testing scheme is depicted below: + * + * DRam0/DMA IRam0 + * ----------------------------------------------- + * | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 | + * | DRam0_PMS_0 | + * | | + * | | + * | - - - - - - - s_iram_test_buffer - - - - - -| IRam0_line1_Split_addr + * DRam0_DMA_line0_Split_addr | -- test_ptr_low -- | = + * = =============================================== IRam0_line0_Split_addr + * DRam0_DMA_line1_Split_addr | | = + * | - - - - - - - s_dram_test_buffer - - - - - --| IRam0_DRam0_Split_addr (main I/D) + * | -- test_ptr_high -- | + * | - - - - - - - - - - - - - - - - - - - - - - | + * | | + * | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | + * | IRam0_PMS_3 | + * | | + * | ... | + * | | + * =============================================== SOC_RTC_IRAM_LOW (0x50000000) + * | -- test_ptr_low -- | + * | - - - - - - s_rtc_text_test_buffer - - - - -| RtcFast_Split_addr (_rtc_text_end) + * | -- .rtc.dummy -- | (UNUSED - PADDING) + * 8 kB | - - - - - - - - - - - - - - - - - - - - - - | [_rtc_dummy_end = _rtc_force_fast_start] + * | -- .rtc.force_fast -- | (NOT USED IN THIS TEST) + * | - - - - - - s_rtc_data_test_buffer - - - - -| [_rtc_force_fast_end = _rtc_data_start] + * | -- test_ptr_high -- | + * | - - - - - - - - - - - - - - - - - - - - - - | + * =============================================== SOC_RTC_IRAM_HIGH (0x50001FFF) + * | | + * ----------------------------------------------- + */ + + +/* !!!IMPORTANT!!! + * a0 needs to be saved/restored manually (not clobbered) to avoid return address corruption + * caused by ASM block handling + */ +#define CODE_EXEC(code_buf, param, res) \ + asm volatile ( \ + "mov a3, a0\n\t" \ + "movi a2," #param "\n\t" \ + "callx0 %1\n\t" \ + "mov %0,a2\n\t" \ + "mov a0, a3\n\t" \ + : "=r"(res) \ + : "r"(code_buf) \ + : "a2", "a3" ); + +/* Binary code for the following asm: + * + .type _testfunc,@function + .global _testfunc + .align 4 + + _testfunc: + slli a2, a2, 1 + ret.n + */ +static uint8_t s_fnc_buff[] = {0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00}; +typedef int (*fnc_ptr)(int); + +//testing buffers +#define SRAM_TEST_BUFFER_SIZE 0x400 +#define SRAM_TEST_OFFSET 0x200 + +static uint8_t __attribute__((section(".iram_end_test"))) s_iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0}; +static uint8_t __attribute__((section(".rtc_text_end_test"))) s_rtc_text_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0}; +static uint8_t RTC_DATA_ATTR s_rtc_data_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0}; +static uint8_t s_dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0}; + +//auxiliary defines +#define LOW_REGION true +#define HIGH_REGION false +#define READ_ENA true +#define READ_DIS false +#define WRITE_ENA true +#define WRITE_DIS false +#define EXEC_ENA true +#define EXEC_DIS false + +volatile bool g_override_illegal_instruction; + + +static void *test_mprot_addr_low(esp_mprot_mem_t mem_type) +{ + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + return (void *)((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET); + case MEMPROT_TYPE_DRAM0_SRAM: + return (void *)MAP_IRAM_TO_DRAM((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET); + case MEMPROT_TYPE_IRAM0_RTCFAST: + return (void *)((uint32_t)s_rtc_text_test_buffer + SRAM_TEST_OFFSET); + default: + abort(); + } +} + +static void *test_mprot_addr_high(esp_mprot_mem_t mem_type) +{ + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + return (void *)MAP_DRAM_TO_IRAM((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET); + case MEMPROT_TYPE_DRAM0_SRAM: + return (void *)((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET); + case MEMPROT_TYPE_IRAM0_RTCFAST: + return (void *)((uint32_t)s_rtc_data_test_buffer + SRAM_TEST_OFFSET); + default: + abort(); + } +} + +static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_mem_t mem_type, const int core) +{ + esp_rom_printf("FAULT ["); + + esp_rom_printf("core 0 dram0: 0x%08X, core 1 dram0: 0x%08X, ", REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG), REG_READ(SENSITIVE_CORE_1_DRAM0_PMS_MONITOR_2_REG)); + esp_rom_printf("core 0 iram0: 0x%08X, core 1 iram0: 0x%08X, ", REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG), REG_READ(SENSITIVE_CORE_1_IRAM0_PMS_MONITOR_2_REG)); + + void *addr; + esp_err_t err = esp_mprot_get_violate_addr(mem_type, &addr, core); + if (err == ESP_OK) { + esp_rom_printf("fault addr: 0x%08X,", (uint32_t)addr); + } else { + esp_rom_printf("fault addr: N/A (%s),", esp_err_to_name(err)); + } + + esp_mprot_pms_world_t world; + err = esp_mprot_get_violate_world(mem_type, &world, core); + if (err == ESP_OK) { + esp_rom_printf(" world: %s,", esp_mprot_pms_world_to_str(world)); + } else { + esp_rom_printf(" world: N/A (%s),", esp_err_to_name(err)); + } + + uint32_t oper; + err = esp_mprot_get_violate_operation(mem_type, &oper, core); + if (err == ESP_OK) { + esp_rom_printf(" operation: %s", esp_mprot_oper_type_to_str(oper)); + } else { + esp_rom_printf(" operation: N/A (%s)", esp_err_to_name(err)); + } + + // DRAM/DMA fault: check byte-enables + if (mem_type == MEMPROT_TYPE_DRAM0_SRAM) { + uint32_t byteen; + err = esp_mprot_get_violate_byte_enables(mem_type, &byteen, core); + if (err == ESP_OK) { + esp_rom_printf(", byte en: 0x%08X", byteen); + } else { + esp_rom_printf(", byte en: N/A (%s)", esp_err_to_name(err)); + } + } + + esp_rom_printf( "]\n" ); +} + +static void test_mprot_check_test_result(esp_mprot_mem_t mem_type, bool expected_status) +{ + esp_memp_intr_source_t memp_intr; + esp_err_t err = esp_mprot_get_active_intr(&memp_intr); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_get_active_intr() failed (%s) - test_mprot_check_test_result\n", esp_err_to_name(err)); + return; + } + + bool intr_on = memp_intr.mem_type == mem_type && memp_intr.core > -1; + bool test_result = expected_status ? !intr_on : intr_on; + + if (test_result) { + esp_rom_printf("OK\n"); + } else { + test_mprot_dump_status_register(mem_type, memp_intr.core); + } +} + +static void test_mprot_get_permissions(bool low, esp_mprot_mem_t mem_type, bool *read, bool *write, bool *exec, const int core) +{ + esp_mprot_pms_area_t area; + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + area = low ? MEMPROT_PMS_AREA_IRAM0_2 : MEMPROT_PMS_AREA_IRAM0_3; + break; + case MEMPROT_TYPE_DRAM0_SRAM: + area = low ? MEMPROT_PMS_AREA_DRAM0_0 : MEMPROT_PMS_AREA_DRAM0_1; + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + area = low ? MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO : MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI; + break; + default: + abort(); + } + + uint32_t flags; + esp_err_t err = esp_mprot_get_pms_area(area, &flags, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_get_pms_area() failed (%s) - test_mprot_get_permissions\n", esp_err_to_name(err)); + return; + } + + if (read) { + *read = flags & MEMPROT_OP_READ; + } + if (write) { + *write = flags & MEMPROT_OP_WRITE; + } + if (exec) { + *exec = flags & MEMPROT_OP_EXEC; + } +} + +static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool read, bool write, bool *exec, const int core) +{ + esp_err_t err; + uint32_t flags = 0; + if (read) { + flags |= MEMPROT_OP_READ; + } + if (write) { + flags |= MEMPROT_OP_WRITE; + } + if (exec && *exec) { + flags |= MEMPROT_OP_EXEC; + } + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: { + if (low) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, flags, core)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, flags, core)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, flags, core)) != ESP_OK) { + break; + } + } else { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, flags, core)) != ESP_OK) { + break; + } + } + } + break; + case MEMPROT_TYPE_DRAM0_SRAM: { + if (low) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, flags, core)) != ESP_OK) { + break; + } + } else { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, flags, core)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, flags, core)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, flags, core)) != ESP_OK) { + break; + } + } + } + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: { + if (low) { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, flags, core)) != ESP_OK) { + break; + } + } else { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, flags, core)) != ESP_OK) { + break; + } + } + } + break; + default: + abort(); + } + + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_pms_area() failed (%s) - test_mprot_set_permissions\n", esp_err_to_name(err)); + } +} + +static void test_mprot_read(esp_mprot_mem_t mem_type, const int core) +{ + esp_err_t err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed on core %d (%s) - test_mprot_read\n", core, esp_err_to_name(err)); + return; + } + + //get current permission settings + bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high; + bool is_exec_mem = mem_type & MEMPROT_TYPE_IRAM0_ANY; + test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, is_exec_mem ? &exec_perm_low : NULL, core); + test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL, core); + + //get testing pointers for low & high regions + uint32_t *ptr_low = test_mprot_addr_low(mem_type); + uint32_t *ptr_high = test_mprot_addr_high(mem_type); + const uint32_t test_val = 100; + + //temporarily allow WRITE for setting the test values + err = esp_mprot_set_monitor_en(mem_type, false, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); + return; + } + + test_mprot_set_permissions(LOW_REGION, mem_type, read_perm_low, WRITE_ENA, is_exec_mem ? &exec_perm_low : NULL, core); + test_mprot_set_permissions(HIGH_REGION, mem_type, read_perm_high, WRITE_ENA, is_exec_mem ? &exec_perm_high : NULL, core); + + //store testing values to appropriate memory + *ptr_low = test_val; + *ptr_high = test_val + 1; + + //restore current PMS settings + test_mprot_set_permissions(LOW_REGION, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL, core); + test_mprot_set_permissions(HIGH_REGION, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL, core); + + //reenable monitoring + err = esp_mprot_set_monitor_en(mem_type, true, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); + return; + } + + //perform READ test in low region + esp_rom_printf("%s (core %d) read low: ", esp_mprot_mem_type_to_str(mem_type), core); + err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err)); + return; + } + + volatile uint32_t val = *ptr_low; + + if (read_perm_low && val != test_val) { + esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val ); + test_mprot_dump_status_register(mem_type, core); + } else { + test_mprot_check_test_result(mem_type, read_perm_low); + } + + //perform READ in high region + esp_rom_printf("%s (core %d) read high: ", esp_mprot_mem_type_to_str(mem_type), core); + err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed on core %d (%s) - test_mprot_read\n", core, esp_err_to_name(err)); + return; + } + + val = *ptr_high; + + if (read_perm_high && val != (test_val + 1)) { + esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val); + test_mprot_dump_status_register(mem_type, core); + } else { + test_mprot_check_test_result(mem_type, read_perm_high); + } + + esp_mprot_monitor_clear_intr(mem_type, core); + //test_mprot_dump_status_register(mem_type, core); +} + +static void test_mprot_write(esp_mprot_mem_t mem_type, const int core) +{ + esp_err_t err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed on core %d (%s) - test_mprot_write\n", core, esp_err_to_name(err)); + return; + } + + //get current READ & WRITE permission settings + bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high; + bool is_exec_mem = mem_type & MEMPROT_TYPE_IRAM0_ANY; + test_mprot_get_permissions(LOW_REGION, mem_type, &read_perm_low, &write_perm_low, is_exec_mem ? &exec_perm_low : NULL, core); + test_mprot_get_permissions(HIGH_REGION, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL, core); + + //ensure READ enabled + err = esp_mprot_set_monitor_en(mem_type, false, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); + return; + } + + test_mprot_set_permissions(LOW_REGION, mem_type, READ_ENA, write_perm_low, is_exec_mem ? &exec_perm_low : NULL, core); + test_mprot_set_permissions(HIGH_REGION, mem_type, READ_ENA, write_perm_high, is_exec_mem ? &exec_perm_high : NULL, core); + + err = esp_mprot_set_monitor_en(mem_type, true, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); + return; + } + + volatile uint32_t *ptr_low = test_mprot_addr_low(mem_type); + volatile uint32_t *ptr_high = test_mprot_addr_high(mem_type); + const uint32_t test_val = 10; + + //perform WRITE in low region + esp_rom_printf("%s (core %d) write low: ", esp_mprot_mem_type_to_str(mem_type), core); + err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed on core %d (%s) - test_mprot_write\n", core, esp_err_to_name(err)); + return; + } + + volatile uint32_t val = 0; + *ptr_low = test_val; + val = *ptr_low; + + if (write_perm_low && val != test_val) { + esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val); + test_mprot_dump_status_register(mem_type, core); + } else { + test_mprot_check_test_result(mem_type, write_perm_low); + } + + //perform WRITE in high region + esp_rom_printf("%s (core %d) write high: ", esp_mprot_mem_type_to_str(mem_type), core); + err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed on core %d (%s) - test_mprot_write\n", core, esp_err_to_name(err)); + return; + } + + val = 0; + *ptr_high = test_val + 1; + val = *ptr_high; + + if (val != (test_val + 1) && write_perm_high) { + esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val); + test_mprot_dump_status_register(mem_type, core); + } else { + test_mprot_check_test_result(mem_type, write_perm_high); + } + + //restore original permissions + err = esp_mprot_set_monitor_en(mem_type, false, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); + return; + } + + test_mprot_set_permissions(LOW_REGION, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL, core); + test_mprot_set_permissions(HIGH_REGION, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL, core); + + err = esp_mprot_set_monitor_en(mem_type, true, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err)); + return; + } + + esp_mprot_monitor_clear_intr(mem_type, core); +} + +static void test_mprot_exec(esp_mprot_mem_t mem_type, const int core) +{ + if (!(mem_type & MEMPROT_TYPE_IRAM0_ANY)) { + esp_rom_printf("Error: EXEC test available only for IRAM access.\n" ); + return; + } + + esp_err_t err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed on core %d (%s) - test_mprot_exec\n", core, esp_err_to_name(err)); + return; + } + + err = esp_mprot_set_monitor_en(mem_type, false, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); + return; + } + + //get require mem_type permissions + bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high; + test_mprot_get_permissions(LOW_REGION, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low, core); + test_mprot_get_permissions(HIGH_REGION, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high, core); + + void *fnc_ptr_low = NULL; + void *fnc_ptr_high = NULL; + + if (mem_type == MEMPROT_TYPE_IRAM0_SRAM) { + //temporarily enable WRITE for DBUS + test_mprot_set_permissions(LOW_REGION, MEMPROT_TYPE_DRAM0_SRAM, READ_ENA, WRITE_ENA, NULL, core); + + //get testing pointers for low & high regions using DBUS FOR CODE INJECTION! + fnc_ptr_low = test_mprot_addr_low(MEMPROT_TYPE_DRAM0_SRAM); + fnc_ptr_high = test_mprot_addr_high(MEMPROT_TYPE_DRAM0_SRAM); + + //inject the code to both low & high segments + memcpy(fnc_ptr_low, (const void *) s_fnc_buff, sizeof(s_fnc_buff)); + memcpy(fnc_ptr_high, (const void *) s_fnc_buff, sizeof(s_fnc_buff)); + + fnc_ptr_low = (void *) MAP_DRAM_TO_IRAM(fnc_ptr_low); + fnc_ptr_high = (void *) MAP_DRAM_TO_IRAM(fnc_ptr_high); + + //reenable DBUS protection + test_mprot_set_permissions(LOW_REGION, MEMPROT_TYPE_DRAM0_SRAM, READ_ENA, WRITE_DIS, NULL, core); + } else if (mem_type == MEMPROT_TYPE_IRAM0_RTCFAST) { + //enable WRITE for low region + test_mprot_set_permissions(LOW_REGION, MEMPROT_TYPE_IRAM0_RTCFAST, read_perm_low, WRITE_ENA, &exec_perm_low, core); + + fnc_ptr_low = test_mprot_addr_low(MEMPROT_TYPE_IRAM0_RTCFAST); + fnc_ptr_high = test_mprot_addr_high(MEMPROT_TYPE_IRAM0_RTCFAST); + + //inject the code to both low & high segments + memcpy(fnc_ptr_low, (const void *) s_fnc_buff, sizeof(s_fnc_buff)); + memcpy(fnc_ptr_high, (const void *) s_fnc_buff, sizeof(s_fnc_buff)); + + //reenable original protection + test_mprot_set_permissions(LOW_REGION, MEMPROT_TYPE_IRAM0_RTCFAST, read_perm_low, write_perm_low, &exec_perm_low, core); + } else { + assert(0); + } + + uint32_t res = 0; + + //LOW REGION: clear the intr flag & try to execute the code injected + esp_rom_printf("%s (core %d) exec low: ", esp_mprot_mem_type_to_str(mem_type), core); + err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); + return; + } + + err = esp_mprot_set_monitor_en(mem_type, true, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); + return; + } + + fnc_ptr fnc = (fnc_ptr)fnc_ptr_low; + + g_override_illegal_instruction = true; + CODE_EXEC(fnc, 5, res) + g_override_illegal_instruction = false; + + //check results + bool fnc_call_ok = res == 10; + if (fnc_call_ok) { + test_mprot_check_test_result(mem_type, exec_perm_low); + } else { + if (!exec_perm_low) { + test_mprot_check_test_result(mem_type, false); + } else { + esp_rom_printf(" FAULT [injected code not executed]\n"); + } + } + + //HIGH REGION: clear the intr-on flag & try to execute the code injected + esp_rom_printf("%s (core %d) exec high: ", esp_mprot_mem_type_to_str(mem_type), core); + err = esp_mprot_monitor_clear_intr(mem_type, core); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err)); + return; + } + + fnc = (fnc_ptr)fnc_ptr_high; + + g_override_illegal_instruction = true; + CODE_EXEC(fnc, 6, res) + g_override_illegal_instruction = false; + + fnc_call_ok = res == 12; + if (fnc_call_ok) { + test_mprot_check_test_result(mem_type, exec_perm_high); + } else { + if (!exec_perm_high) { + test_mprot_check_test_result(mem_type, false); + } else { + esp_rom_printf(" FAULT [injected code not executed]\n"); + } + } + + esp_mprot_monitor_clear_intr(mem_type, core); +} + +// testing per-CPU tasks +esp_memp_config_t memp_cfg = { + .invoke_panic_handler = false, + .lock_feature = false, + .split_addr = NULL, + .mem_type_mask = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_DRAM0_SRAM, +#if portNUM_PROCESSORS > 1 + .target_cpu_count = 2, + .target_cpu = {PRO_CPU_NUM, APP_CPU_NUM} +#else + .target_cpu_count = 1, + .target_cpu = {PRO_CPU_NUM} +#endif +}; + +typedef struct { + int core; + SemaphoreHandle_t sem; +} test_ctx_t; + +static void task_on_CPU(void *arg) +{ + test_ctx_t *ctx = (test_ctx_t *)arg; + + if (memp_cfg.mem_type_mask & MEMPROT_TYPE_IRAM0_SRAM) { + test_mprot_read(MEMPROT_TYPE_IRAM0_SRAM, ctx->core); + test_mprot_write(MEMPROT_TYPE_IRAM0_SRAM, ctx->core); + /* temporarily disabled */ + //test_mprot_exec(MEMPROT_TYPE_IRAM0_SRAM, ctx->core); + } + + if (memp_cfg.mem_type_mask & MEMPROT_TYPE_DRAM0_SRAM) { + test_mprot_read(MEMPROT_TYPE_DRAM0_SRAM, ctx->core); + test_mprot_write(MEMPROT_TYPE_DRAM0_SRAM, ctx->core); + } + + if (memp_cfg.mem_type_mask & MEMPROT_TYPE_IRAM0_RTCFAST) { + test_mprot_read(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core); + test_mprot_write(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core); + test_mprot_exec(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core); + } + + xSemaphoreGive(ctx->sem); + + vTaskDelete(NULL); +} + +/* ******************************************************************************************** + * main test runner + */ +void app_main(void) +{ + esp_err_t err = esp_mprot_set_prot(&memp_cfg); + if (err != ESP_OK) { + esp_rom_printf("Error: esp_mprot_set_prot() failed (%s) - app_main\n", esp_err_to_name(err)); + return; + } + + //test each core separate + test_ctx_t ctx = { + .sem = xSemaphoreCreateBinary(), + .core = PRO_CPU_NUM + }; + + xTaskCreatePinnedToCore(task_on_CPU, "task_PRO_CPU", 4096, &ctx, 3, NULL, PRO_CPU_NUM); + xSemaphoreTake(ctx.sem, portMAX_DELAY); + + //multicore setup + if (portNUM_PROCESSORS > 1) { + ctx.core = APP_CPU_NUM; + xTaskCreatePinnedToCore(task_on_CPU, "task_APP_CPU", 4096, &ctx, 3, NULL, APP_CPU_NUM); + xSemaphoreTake(ctx.sem, portMAX_DELAY); + } +} diff --git a/tools/test_apps/system/memprot/main/esp32s3/test_panic.c b/tools/test_apps/system/memprot/main/esp32s3/test_panic.c new file mode 100644 index 0000000000..4e48e4e358 --- /dev/null +++ b/tools/test_apps/system/memprot/main/esp32s3/test_panic.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "freertos/xtensa_context.h" +#include "esp_private/panic_internal.h" +#include "hal/wdt_hal.h" + +extern void esp_panic_handler(panic_info_t *info); +extern volatile bool g_override_illegal_instruction; + +void __real_esp_panic_handler(panic_info_t *info); +void __real_esp_panic_handler_reconfigure_wdts(void); +void __real_soc_hal_stall_core(int core); + +static void disable_all_wdts(void) +{ + wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; +#if SOC_TIMER_GROUPS >= 2 + wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1}; +#endif + + //Todo: Refactor to use Interrupt or Task Watchdog API, and a system level WDT context + //Task WDT is the Main Watchdog Timer of Timer Group 0 + wdt_hal_write_protect_disable(&wdt0_context); + wdt_hal_disable(&wdt0_context); + wdt_hal_write_protect_enable(&wdt0_context); + +#if SOC_TIMER_GROUPS >= 2 + //Interupt WDT is the Main Watchdog Timer of Timer Group 1 + wdt_hal_write_protect_disable(&wdt1_context); + wdt_hal_disable(&wdt1_context); + wdt_hal_write_protect_enable(&wdt1_context); +#endif +} + +/* Memprot test specific IllegalInstruction exception handler: + * when testing the protection against a code execution, sample code + * is being injected into various memory regions which produces + * EXCCAUSE_ILLEGAL on execution attempt. Such a result is expected + * but it causes system reboot in the standard panic handler. + * The following variant of panic handling simply returns back to the + * next instruction and continues normal execution. + * + * NOTE: if EXCCAUSE_ILLEGAL comes from a different source than the testing code + * the behavior is undefined + * */ +void __wrap_esp_panic_handler(panic_info_t *info) +{ + XtExcFrame *frm = (XtExcFrame *)info->frame; + if ( frm->exccause == EXCCAUSE_ILLEGAL && g_override_illegal_instruction == true ) { + frm->pc = frm->a0; + return; + } else { + __real_esp_panic_handler(info); + } +} + +void __wrap_esp_panic_handler_reconfigure_wdts(void) +{ + if ( g_override_illegal_instruction == true ) { + disable_all_wdts(); + return; + } else { + __real_esp_panic_handler_reconfigure_wdts(); + } +} + +void __wrap_soc_hal_stall_core(int core) +{ + if ( g_override_illegal_instruction == true ) { + return; + } else { + __real_soc_hal_stall_core(core); + } +}