diff --git a/components/esp_common/CMakeLists.txt b/components/esp_common/CMakeLists.txt index 38668dfcac..de5978bd46 100644 --- a/components/esp_common/CMakeLists.txt +++ b/components/esp_common/CMakeLists.txt @@ -33,7 +33,8 @@ set(optional_reqs ulp esp_netif soc esp-tls - esp_https_ota) + esp_https_ota + esp_hw_support) idf_build_get_property(build_components BUILD_COMPONENTS) foreach(req ${optional_reqs}) diff --git a/components/esp_common/include/esp_err.h b/components/esp_common/include/esp_err.h index d31bb9a075..f317f8a09f 100644 --- a/components/esp_common/include/esp_err.h +++ b/components/esp_common/include/esp_err.h @@ -1,16 +1,9 @@ -// Copyright 2015-2016 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 +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ -// 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. #pragma once #include @@ -46,6 +39,7 @@ typedef int esp_err_t; #define ESP_ERR_MESH_BASE 0x4000 /*!< Starting number of MESH error codes */ #define ESP_ERR_FLASH_BASE 0x6000 /*!< Starting number of flash error codes */ #define ESP_ERR_HW_CRYPTO_BASE 0xc000 /*!< Starting number of HW cryptography module error codes */ +#define ESP_ERR_MEMPROT_BASE 0xd000 /*!< Starting number of Memory Protection API error codes */ /** * @brief Returns string for esp_err_t error codes diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index ac06862a0c..4dd7d09885 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -23,6 +23,9 @@ #if __has_include("esp_image_format.h") #include "esp_image_format.h" #endif +#if __has_include("esp_memprot_err.h") +#include "esp_memprot_err.h" +#endif #if __has_include("esp_mesh.h") #include "esp_mesh.h" #endif @@ -758,6 +761,33 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING ERR_TBL_IT(ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING), /* 49157 0xc005 */ +# endif + // components/esp_common/include/esp_err.h +# ifdef ESP_ERR_MEMPROT_BASE + ERR_TBL_IT(ESP_ERR_MEMPROT_BASE), /* 53248 0xd000 Starting number of Memory Protection API + error codes */ +# endif + // components/esp_hw_support/include/esp_memprot_err.h +# ifdef ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID + ERR_TBL_IT(ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID), /* 53249 0xd001 */ +# endif +# ifdef ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID + ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID), /* 53250 0xd002 */ +# endif +# ifdef ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE + ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE), /* 53251 0xd003 */ +# endif +# ifdef ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED + ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED), /* 53252 0xd004 */ +# endif +# ifdef ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID + ERR_TBL_IT(ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID), /* 53253 0xd005 */ +# endif +# ifdef ESP_ERR_MEMPROT_WORLD_INVALID + ERR_TBL_IT(ESP_ERR_MEMPROT_WORLD_INVALID), /* 53254 0xd006 */ +# endif +# ifdef ESP_ERR_MEMPROT_AREA_INVALID + ERR_TBL_IT(ESP_ERR_MEMPROT_AREA_INVALID), /* 53255 0xd007 */ # endif }; #endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP diff --git a/components/esp_hw_support/include/esp_memprot.h b/components/esp_hw_support/include/esp_memprot.h new file mode 100644 index 0000000000..c9557eae93 --- /dev/null +++ b/components/esp_hw_support/include/esp_memprot.h @@ -0,0 +1,199 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +///////////////////////////////////////////////////////////////////////////////////////// +// ESP Memory Protection API (PMS) +// - allows configuration and violation-interrupt handling of the PMS module operations +// - not intended for public use. + +#pragma once + +#include "sdkconfig.h" +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST + +#include +#include +#include "esp_err.h" +#include "esp_memprot_err.h" +#include "soc_memprot_types.h" +#include "esp_memprot_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_MEMPROT_ERR_CHECK(retval, fnc) if ((retval=fnc) != ESP_OK) { return retval; } + +/** +* @brief Basic PMS interrupt source info +*/ +typedef struct { + esp_mprot_mem_t mem_type; /*!< Memory type containing the faulting address */ + int core; /*!< CPU/Core ID running the faulting instruction */ +} esp_memp_intr_source_t; + +/** + * @brief Clears current interrupt ON flag for given Memory type and CPU/Core ID + * + * This operation is non-atomic for some chips by PMS module design + * In such a case the interrupt clearing happens in two steps: + * 1. Interrupt CLR flag is set (clears interrupt-ON status and inhibits linked interrupt processing) + * 2. Interrupt CLR flag is reset (resumes the interrupt monitoring) + * + * @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_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); + +/** + * @brief Checks whether any of the PMS settings is locked + * + * @param[out] locked Any lock on? (true/false) + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on invalid locked ptr + * Other failures: error code of any failing esp_mprot_get_*_lock() routine (called internally) + */ +esp_err_t esp_mprot_is_conf_locked_any(bool *locked); + +/** + * @brief Checks whether any PMS violation-interrupt monitoring is enabled + * + * @param[out] locked Any PMS violation interrupt monitor is enabled (true/false) + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on invalid enabled ptr + * Other failures: error code of esp_mprot_get_monitor_en() routine (called internally for all Memory types) + */ +esp_err_t esp_mprot_is_intr_ena_any(bool *enabled); + +/** + * @brief Returns active PMS violation-interrupt Memory type if any (MEMPROT_TYPE_NONE when none detected) + * and the CPU/CoreID which was running the faulty code (-1 when no interrupt available) + * + * If there are more interrupts indicated on (shouldn't happen), the order of precedence is given by 'esp_mprot_mem_t' enum definition (low->high) + * + * @param[out] mem_type Out-pointer for Memory type given by the faulting address (see esp_mprot_mem_t enum) + * @param[out] core Out-pointer for CPU/Core ID (see *_CPU_NUM defs in soc.h) + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on passing invalid pointer(s) + */ +esp_err_t esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr); + +/** + * @brief Returns the address which caused the violation interrupt for given Memory type and CPU/Core ID. + * This function is to be called after a basic resolving of (current) interrupt's parameters (ie corresponding + * Memory type and CPU ID see esp_mprot_get_active_intr()). This is to minimize processing time of actual exception + * as this API is typicaly used in a panic-handling code. + * If there is no active interrupt available for the Memory type/CPU ID required, fault_addr is set to NULL. + * + * @param mem_type memory type + * @param[out] fault_addr Address of the operation which caused the PMS violation interrupt + * @param core Faulting instruction 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 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); + +/** + * @brief Returns PMS World identifier of the code causing the violation interrupt + * + * The value is read from appropriate PMS violation status register and thus might be 0 if the interrupt is not currently active. + * + * @param mem_type Memory type + * @param[out] world PMS World type (see esp_mprot_pms_world_t) + * @param core Faulting instruction 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 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); + +/** + * @brief Returns an operation type which caused the violation interrupt + * + * The operation resolving is processed over various PMS status register flags, according to given Memory type argument. + * If the interrupt is not active the result returned is irrelevant (likely evaluated to MEMPROT_OP_READ). + * + * @param mem_type Memory type + * @param[out] oper Operation type (see MEMPROT_OP_* defines) + * @param core Faulting instruction 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 oper pointer + */ +esp_err_t esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core); + +/** + * @brief Checks whether given memory type supports byte-enables info + * + * Byte-enables status is available only for DMA/DRAM operations + * + * @param mem_type memory type + * + * @return byte-enables info available true/false + */ +bool esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type); + +/** + * @brief Returns byte-enables for the address which caused the violation interrupt + * + * The value is taken from appropriate PMS violation status register, based on given Memory type + * + * @param mem_type Memory type (MEMPROT_TYPE_DRAM0_SRAM) + * @param[out] byte_en Byte-enables bits + * @param core Faulting instruction 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 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); + +/** + * @brief Convenient routine for setting the PMS defaults + * + * Called on system startup, depending on ESP_SYSTEM_MEMPROT_FEATURE Kconfig value + * + * @param memp_config pointer to Memprot configuration structure (esp_memp_config_t). The structure si chip-specific, + * for details and defaults see appropriate [target-chip]/soc_memprot_types.h + * + * @return ESP_OK on success + * Other failures: error code of the failing routine called internally. No specific error processing provided in such a case + * due to large number of embedded calls (ie no global unique error table is provided and thus one error code can have different meanings, + * depending on the routine issuing the error) + */ +esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config); + +/** + * @brief Generates PMS configuration string of actual device (diagnostics) + * + * The functions generates a string from current configuration, control and status registers of the PMS (or similar) module of actual device. + * The values are fetched using HAL LL calls to help finding possible errors in the Memprot API implementation + * + * @param[out] dump_info_string configuration string buffer pointer. The string is allocated by the callee and must be freed by the caller. + * + * @return ESP_OK on success + * ESP_ERR_NO_MEM on buffer allocation failure + * ESP_ERR_INVALID_ARGUMENT on invalid dump_info_string pointer + */ +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 new file mode 100644 index 0000000000..5556d2c889 --- /dev/null +++ b/components/esp_hw_support/include/esp_memprot_err.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief ESP Memprot API error code definition +*/ +#define ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID (ESP_ERR_MEMPROT_BASE + 1) /**< Memory type invalid in given context */ +#define ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID (ESP_ERR_MEMPROT_BASE + 2) /**< Splitting address invalid in given context */ +#define ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE (ESP_ERR_MEMPROT_BASE + 3) /**< Splitting address out of range */ +#define ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED (ESP_ERR_MEMPROT_BASE + 4) /**< Splitting address not aligned to required boundaries */ +#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 */ + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_memprot_types.h b/components/esp_hw_support/include/esp_memprot_types.h new file mode 100644 index 0000000000..e37fee5457 --- /dev/null +++ b/components/esp_hw_support/include/esp_memprot_types.h @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief PMS World type (attribute per PMS area, similar to x86 Ring scheme) + */ +typedef enum { + MEMPROT_PMS_WORLD_NONE = 0x00000000, + MEMPROT_PMS_WORLD_0 = 0x00000001, + MEMPROT_PMS_WORLD_1 = 0x00000002, + MEMPROT_PMS_WORLD_2 = 0x00000004, + MEMPROT_PMS_WORLD_ALL = 0x7FFFFFFF, + MEMPROT_PMS_WORLD_INVALID = 0x80000000 +} esp_mprot_pms_world_t; + +/** + * @brief Memory operation/permission type recognized by PMS + */ +#define MEMPROT_OP_NONE 0x00000000 +#define MEMPROT_OP_READ 0x00000001 +#define MEMPROT_OP_WRITE 0x00000002 +#define MEMPROT_OP_EXEC 0x00000004 +#define MEMPROT_OP_INVALID 0x80000000 + +#ifdef __cplusplus +} +#endif 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 new file mode 100644 index 0000000000..caeb758486 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/esp_memprot_internal.h @@ -0,0 +1,199 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST + +#include +#include +#include "esp_err.h" +#include "esp_memprot_err.h" +#include "hal/memprot_types.h" +#include "soc_memprot_types.h" +#include "esp_memprot_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief Convert Memprot low level errors to esp_err_t +*/ +esp_err_t esp_mprot_ll_err_to_esp_err(const memprot_ll_err_t err); + +/** + * @brief Convert Memprot low level PMS World IDs to esp_mprot_pms_world_t + */ +esp_mprot_pms_world_t esp_mprot_ll_world_to_hl_world(const memprot_ll_world_t world); + +/** + * @brief Converts operation type to string, no combination of operations allowed + * + * @param oper_type PMS operation type + */ +const char *esp_mprot_oper_type_to_str(const uint32_t oper_type); + +/** + * @brief Converts PMS World type to string + * + * @param area_type PMS World type + */ +const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type); + +/** + * @brief Sets splitting address for given line type in the target Memory 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 + * + * @return ESP_OK on success + * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type + * ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID on invalid line_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); + +/** + * @brief Gets PMS splitting address for given split_addr type + * + * The value is read from the PMS configuration registers + * + * @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 + * + * @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); + +/** + * @brief Returns default main I/D splitting address for given Memory type + * + * @param mem_type memory type + * @param[out] def_split_addr Main I/D splitting address of required mem_type + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on invalid def_split_addr pointer + * ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type + */ +esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr); + +/** + * @brief Sets a lock for the main IRAM/DRAM splitting addresses + * Locks can be unlocked only by digital system reset + * + * @param mem_type memory type + * + * @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); + +/** + * @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 + * + * @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); + +/** + * @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 + * + * @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); + +/** + * @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 + * + * @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); + +/** + * @brief Sets permissions for given PMS Area + * + * @param area_type PMS area type + * @param flags combination of MEMPROT_OP_* defines + * + * @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); + +/** + * @brief Gets current permissions for given PMS Area + * + * @param area_type PMS area type + * @param[out] flags combination of MEMPROT_OP_* defines + * + * @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); + +/** + * @brief Sets a lock for PMS interrupt monitor settings of required Memory type + * + * Locks can be unlocked only by digital system reset + * + * @param mem_type memory type (see esp_mprot_mem_t enum) + * + * @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); + +/** + * @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 + * + * @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); + +/** + * @brief Enable PMS violation interrupt monitoring of required Memory type + * + * @param mem_type memory type + * @param enable enable/disable violation interrupt monitoring + * + * @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); + +#ifdef __cplusplus +} +#endif + +#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST diff --git a/components/esp_hw_support/include/soc/esp32c3/memprot.h b/components/esp_hw_support/include/soc/esp32c3/memprot.h deleted file mode 100644 index 818cd677dc..0000000000 --- a/components/esp_hw_support/include/soc/esp32c3/memprot.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -/* INTERNAL API - * generic interface to PMS memory protection features - */ - -#pragma once - -#include -#include - -#include "esp_attr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef IRAM_SRAM_START -#define IRAM_SRAM_START 0x4037C000 -#endif - -#ifndef DRAM_SRAM_START -#define DRAM_SRAM_START 0x3FC7C000 -#endif - -#ifndef MAP_DRAM_TO_IRAM -#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START) -#endif - -#ifndef MAP_IRAM_TO_DRAM -#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START) -#endif - -typedef enum { - MEMPROT_NONE = 0x00000000, - MEMPROT_IRAM0_SRAM = 0x00000001, - MEMPROT_DRAM0_SRAM = 0x00000002, - MEMPROT_ALL = 0xFFFFFFFF -} mem_type_prot_t; - -typedef enum { - MEMPROT_SPLITLINE_NONE = 0, - MEMPROT_IRAM0_DRAM0_SPLITLINE, - MEMPROT_IRAM0_LINE_0_SPLITLINE, - MEMPROT_IRAM0_LINE_1_SPLITLINE, - MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, - MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE -} split_line_t; - -typedef enum { - MEMPROT_PMS_AREA_NONE = 0, - MEMPROT_IRAM0_PMS_AREA_0, - MEMPROT_IRAM0_PMS_AREA_1, - MEMPROT_IRAM0_PMS_AREA_2, - MEMPROT_IRAM0_PMS_AREA_3, - MEMPROT_DRAM0_PMS_AREA_0, - MEMPROT_DRAM0_PMS_AREA_1, - MEMPROT_DRAM0_PMS_AREA_2, - MEMPROT_DRAM0_PMS_AREA_3 -} pms_area_t; - -typedef enum -{ - MEMPROT_PMS_WORLD_0 = 0, - MEMPROT_PMS_WORLD_1, - MEMPROT_PMS_WORLD_2, - MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF -} pms_world_t; - -typedef enum -{ - MEMPROT_PMS_OP_READ = 0, - MEMPROT_PMS_OP_WRITE, - MEMPROT_PMS_OP_FETCH, - MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF -} pms_operation_type_t; - -/** - * @brief Converts Memory protection type to string - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type); - -/** - * @brief Converts Split line type to string - * - * @param line_type Split line type (see split_line_t enum) - */ -const char *esp_memprot_split_line_to_str(split_line_t line_type); - -/** - * @brief Converts PMS Area type to string - * - * @param area_type PMS Area type (see pms_area_t enum) - */ -const char *esp_memprot_pms_to_str(pms_area_t area_type); - -/** - * @brief Returns PMS splitting address for given Split line type - * - * The value is taken from PMS configuration registers (IRam0 range) - * For details on split lines see 'esp_memprot_set_prot_int' function description - * - * @param line_type Split line type (see split_line_t enum) - * - * @return appropriate split line address - */ -uint32_t *esp_memprot_get_split_addr(split_line_t line_type); - -/** - * @brief Returns default main IRAM/DRAM splitting address - * - * The address value is given by _iram_text_end global (IRam0 range) - - * @return Main I/D split line (IRam0_DRam0_Split_Addr) - */ -void *esp_memprot_get_default_main_split_addr(void); - -/** - * @brief Sets a lock for the main IRAM/DRAM splitting address - * - * Locks can be unlocked only by digital system reset - */ -void esp_memprot_set_split_line_lock(void); - -/** - * @brief Gets a lock status for the main IRAM/DRAM splitting address - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_split_line_lock(void); - -/** - * @brief Sets required split line address - * - * @param line_type Split line type (see split_line_t enum) - * @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM) - */ -void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr); - -/** - * @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 protection type (see mem_type_prot_t enum) - */ -void esp_memprot_set_pms_lock(mem_type_prot_t mem_type); - -/** - * @brief Gets a lock status for PMS Area settings of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type); - -/** - * @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM) - * - * @param area_type IRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag - * @param w Write permission flag - * @param x Execute permission flag - */ -void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x); - -/** - * @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM) - * - * @param area_type IRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag holder - * @param w Write permission flag holder - * @param x Execute permission flag holder - */ -void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x); - -/** - * @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM) - * - * @param area_type DRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag - * @param w Write permission flag - */ -void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w); - -/** - * @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM) - * - * @param area_type DRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag holder - * @param w Write permission flag holder - */ -void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w); - -/** - * @brief Sets a lock for PMS interrupt monitor settings of required Memory type - * - * Locks can be unlocked only by digital system reset - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type); - -/** - * @brief Gets a lock status for PMS interrupt monitor settings of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type); - -/** - * @brief Enable PMS violation interrupt monitoring of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * @param enable/disable - */ -void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable); - -/** - * @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (enabled/disabled) - */ -bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type); - -/** - * @brief Gets CPU ID for currently active PMS violation interrupt - * - * @return CPU ID (CPU_PRO for ESP32C3) - */ -int IRAM_ATTR esp_memprot_intr_get_cpuid(void); - -/** - * @brief Clears current interrupt ON flag for given Memory type - * - * Interrupt clearing happens in two steps: - * 1. Interrupt CLR flag is set (to clear the interrupt ON status) - * 2. Interrupt CLR flag is reset (to allow further monitoring) - * This operation is non-atomic by PMS module design - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type); - -/** - * @brief Returns active PMS violation interrupt (if any) - * - * This function iterates through supported Memory type status registers - * and returns the first interrupt-on flag. If none is found active, - * MEMPROT_NONE is returned. - * Order of checking (in current version): - * 1. MEMPROT_IRAM0_SRAM - * 2. MEMPROT_DRAM0_SRAM - * - * @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum) - */ -mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void); - -/** - * @brief Checks whether any violation interrupt is active - * - * @return true/false (yes/no) - */ -bool IRAM_ATTR esp_memprot_is_locked_any(void); - -/** - * @brief Checks whether any violation interrupt is enabled - * - * @return true/false (yes/no) - */ -bool IRAM_ATTR esp_memprot_is_intr_ena_any(void); - -/** - * @brief Checks whether any violation interrupt is enabled - * - * @return true/false (yes/no) - */ -bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type); - -/** - * @brief Returns the address which caused the violation interrupt (if any) - * - * The address is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return faulting address - */ -uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type); - -/** - * @brief Returns the World identifier of the code causing the violation interrupt (if any) - * - * The value is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return World identifier (see pms_world_t enum) - */ -pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type); - -/** - * @brief Returns Read or Write operation type which caused the violation interrupt (if any) - * - * The value (bit) is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t) - */ -pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type); - -/** - * @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any) - * - * The value (bit) is taken from appropriate PMS violation status register, based given Memory type - * Effective only on IRam0 access - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (LoadStore bit on/off) - */ -bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type); - -/** - * @brief Returns byte-enables for the address which caused the violation interrupt (if any) - * - * The value is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return byte-enables - */ -uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type); - -/** - * @brief Returns raw contents of DRam0 status register 1 - * - * @return 32-bit register value - */ -uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void); - -/** - * @brief Returns raw contents of DRam0 status register 2 - * - * @return 32-bit register value - */ -uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void); - -/** - * @brief Returns raw contents of IRam0 status register - * - * @return 32-bit register value - */ -uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void); - -/** - * @brief Register PMS violation interrupt in global interrupt matrix for given Memory type - * - * Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM - * The registration makes the panic-handler routine being called when the interrupt appears - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type); - -/** - * @brief Convenient routine for setting the PMS defaults - * - * Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings - * For implementation details see 'esp_memprot_set_prot_int' description - * - * @param invoke_panic_handler register all interrupts for panic handling (true/false) - * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false) - * @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int') - */ -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); - -/** - * @brief Internal routine for setting the PMS defaults - * - * Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address - * (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line - * is used (&_iram_text_end) and all the remaining lines share the same address. - * The function sets all the split lines and PMS areas to the same space, - * ie there is a single instruction space and single data space at the end. - * The PMS split lines and permission areas scheme described below: - * - * DRam0/DMA IRam0 - * ----------------------------------------------- - * ... | IRam0_PMS_0 | - * DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr - * ... | IRam0_PMS_1 | - * ... ----------------------------------------------- IRam0_line0_Split_addr - * | IRam0_PMS_2 | - * =============================================== IRam0_DRam0_Split_addr (main I/D) - * | DRam0_PMS_1 | - * DRam0_DMA_line0_Split_addr ----------------------------------------------- ... - * | DRam0_PMS_2 | ... - * DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3 - * | DRam0_PMS_3 | ... - * ----------------------------------------------- - * - * Default settings provided by 'esp_memprot_set_prot_int' are as follows: - * - * DRam0/DMA IRam0 - * ----------------------------------------------- - * | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 | - * | DRam0_PMS_0 | IRam0_line1_Split_addr - * DRam0_DMA_line0_Split_addr | | = - * = =============================================== IRam0_line0_Split_addr - * DRam0_DMA_line1_Split_addr | | = - * | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D) - * | IRam0_PMS_3 | - * ----------------------------------------------- - * - * Once the memprot feature is locked, it can be unlocked only by digital system reset - * - * @param invoke_panic_handler register all the violation interrupts for panic handling (true/false) - * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false) - * @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end) - * @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t) - */ -void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask); - -/** - * @brief Returns raw contents of PMS interrupt monitor register for given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return 32-bit register value - */ -uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type); - -#ifdef __cplusplus -} -#endif 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 new file mode 100644 index 0000000000..318c610961 --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h @@ -0,0 +1,175 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +////////////////////////////////////////////////////////// +// ESP32-C3 PMS memory protection types +// + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memory types recognized by PMS + */ +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_IRAM0_ANY = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_IRAM0_RTCFAST +} esp_mprot_mem_t; + +/** + * @brief Splitting address (line) type + */ +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_MAIN = MEMPROT_SPLIT_ADDR_IRAM0_DRAM0 +} esp_mprot_split_addr_t; + +/** + * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address) + */ +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; + +/** +* @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 */ +} esp_memp_config_t; + +#define ESP_MEMPROT_DEFAULT_CONFIG() { \ + .invoke_panic_handler = true, \ + .lock_feature = true, \ + .split_addr = NULL, \ + .mem_type_mask = MEMPROT_TYPE_ALL \ +} + +/** + * @brief Converts Memory protection type to string + * + * @param mem_type Memory protection type + */ +static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type) +{ + switch (mem_type) { + case 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 "ALL"; + default: + return "INVALID"; + } +} + +/** + * @brief Converts Splitting address type to string + * + * @param line_type Split line type + */ +static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type) +{ + switch (line_type) { + case 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 "SPLIT_ADDR_ALL"; + default: + return "SPLIT_ADDR_INVALID"; + } +} + +/** + * @brief Converts PMS Area type to string + * + * @param area_type PMS Area type + */ +static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type) +{ + switch (area_type) { + case 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 "PMS_AREA_ALL"; + default: + return "PMS_AREA_INVALID"; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/soc/esp32h2/memprot.h b/components/esp_hw_support/include/soc/esp32h2/memprot.h deleted file mode 100644 index 75228580ff..0000000000 --- a/components/esp_hw_support/include/soc/esp32h2/memprot.h +++ /dev/null @@ -1,448 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -/* INTERNAL API - * generic interface to PMS memory protection features - */ - -#pragma once - -#include -#include -#include "esp_attr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef IRAM_SRAM_START -#define IRAM_SRAM_START 0x4037C000 -#endif - -#ifndef DRAM_SRAM_START -#define DRAM_SRAM_START 0x3FC7C000 -#endif - -#ifndef MAP_DRAM_TO_IRAM -#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START) -#endif - -#ifndef MAP_IRAM_TO_DRAM -#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START) -#endif - -typedef enum { - MEMPROT_NONE = 0x00000000, - MEMPROT_IRAM0_SRAM = 0x00000001, - MEMPROT_DRAM0_SRAM = 0x00000002, - MEMPROT_ALL = 0xFFFFFFFF -} mem_type_prot_t; - -typedef enum { - MEMPROT_SPLITLINE_NONE = 0, - MEMPROT_IRAM0_DRAM0_SPLITLINE, - MEMPROT_IRAM0_LINE_0_SPLITLINE, - MEMPROT_IRAM0_LINE_1_SPLITLINE, - MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, - MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE -} split_line_t; - -typedef enum { - MEMPROT_PMS_AREA_NONE = 0, - MEMPROT_IRAM0_PMS_AREA_0, - MEMPROT_IRAM0_PMS_AREA_1, - MEMPROT_IRAM0_PMS_AREA_2, - MEMPROT_IRAM0_PMS_AREA_3, - MEMPROT_DRAM0_PMS_AREA_0, - MEMPROT_DRAM0_PMS_AREA_1, - MEMPROT_DRAM0_PMS_AREA_2, - MEMPROT_DRAM0_PMS_AREA_3 -} pms_area_t; - -typedef enum -{ - MEMPROT_PMS_WORLD_0 = 0, - MEMPROT_PMS_WORLD_1, - MEMPROT_PMS_WORLD_2, - MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF -} pms_world_t; - -typedef enum -{ - MEMPROT_PMS_OP_READ = 0, - MEMPROT_PMS_OP_WRITE, - MEMPROT_PMS_OP_FETCH, - MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF -} pms_operation_type_t; - -/** - * @brief Converts Memory protection type to string - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type); - -/** - * @brief Converts Split line type to string - * - * @param line_type Split line type (see split_line_t enum) - */ -const char *esp_memprot_split_line_to_str(split_line_t line_type); - -/** - * @brief Converts PMS Area type to string - * - * @param area_type PMS Area type (see pms_area_t enum) - */ -const char *esp_memprot_pms_to_str(pms_area_t area_type); - -/** - * @brief Returns PMS splitting address for given Split line type - * - * The value is taken from PMS configuration registers (IRam0 range) - * For details on split lines see 'esp_memprot_set_prot_int' function description - * - * @param line_type Split line type (see split_line_t enum) - * - * @return appropriate split line address - */ -uint32_t *esp_memprot_get_split_addr(split_line_t line_type); - -/** - * @brief Returns default main IRAM/DRAM splitting address - * - * The address value is given by _iram_text_end global (IRam0 range) - - * @return Main I/D split line (IRam0_DRam0_Split_Addr) - */ -void *esp_memprot_get_default_main_split_addr(void); - -/** - * @brief Sets a lock for the main IRAM/DRAM splitting address - * - * Locks can be unlocked only by digital system reset - */ -void esp_memprot_set_split_line_lock(void); - -/** - * @brief Gets a lock status for the main IRAM/DRAM splitting address - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_split_line_lock(void); - -/** - * @brief Sets required split line address - * - * @param line_type Split line type (see split_line_t enum) - * @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM) - */ -void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr); - -/** - * @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 protection type (see mem_type_prot_t enum) - */ -void esp_memprot_set_pms_lock(mem_type_prot_t mem_type); - -/** - * @brief Gets a lock status for PMS Area settings of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type); - -/** - * @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM) - * - * @param area_type IRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag - * @param w Write permission flag - * @param x Execute permission flag - */ -void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x); - -/** - * @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM) - * - * @param area_type IRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag holder - * @param w Write permission flag holder - * @param x Execute permission flag holder - */ -void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x); - -/** - * @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM) - * - * @param area_type DRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag - * @param w Write permission flag - */ -void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w); - -/** - * @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM) - * - * @param area_type DRam0 PMS Area type (see pms_area_t enum) - * @param r Read permission flag holder - * @param w Write permission flag holder - */ -void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w); - -/** - * @brief Sets a lock for PMS interrupt monitor settings of required Memory type - * - * Locks can be unlocked only by digital system reset - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type); - -/** - * @brief Gets a lock status for PMS interrupt monitor settings of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type); - -/** - * @brief Enable PMS violation interrupt monitoring of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * @param enable/disable - */ -void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable); - -/** - * @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (enabled/disabled) - */ -bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type); - -/** - * @brief Gets CPU ID for currently active PMS violation interrupt - * - * @return CPU ID (CPU_PRO for ESP32H2) - */ -int IRAM_ATTR esp_memprot_intr_get_cpuid(void); - -/** - * @brief Clears current interrupt ON flag for given Memory type - * - * Interrupt clearing happens in two steps: - * 1. Interrupt CLR flag is set (to clear the interrupt ON status) - * 2. Interrupt CLR flag is reset (to allow further monitoring) - * This operation is non-atomic by PMS module design - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type); - -/** - * @brief Returns active PMS violation interrupt (if any) - * - * This function iterates through supported Memory type status registers - * and returns the first interrupt-on flag. If none is found active, - * MEMPROT_NONE is returned. - * Order of checking (in current version): - * 1. MEMPROT_IRAM0_SRAM - * 2. MEMPROT_DRAM0_SRAM - * - * @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum) - */ -mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void); - -/** - * @brief Checks whether any violation interrupt is active - * - * @return true/false (yes/no) - */ -bool IRAM_ATTR esp_memprot_is_locked_any(void); - -/** - * @brief Checks whether any violation interrupt is enabled - * - * @return true/false (yes/no) - */ -bool IRAM_ATTR esp_memprot_is_intr_ena_any(void); - -/** - * @brief Checks whether any violation interrupt is enabled - * - * @return true/false (yes/no) - */ -bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type); - -/** - * @brief Returns the address which caused the violation interrupt (if any) - * - * The address is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return faulting address - */ -uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type); - -/** - * @brief Returns the World identifier of the code causing the violation interrupt (if any) - * - * The value is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return World identifier (see pms_world_t enum) - */ -pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type); - -/** - * @brief Returns Read or Write operation type which caused the violation interrupt (if any) - * - * The value (bit) is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t) - */ -pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type); - -/** - * @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any) - * - * The value (bit) is taken from appropriate PMS violation status register, based given Memory type - * Effective only on IRam0 access - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return true/false (LoadStore bit on/off) - */ -bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type); - -/** - * @brief Returns byte-enables for the address which caused the violation interrupt (if any) - * - * The value is taken from appropriate PMS violation status register, based given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return byte-enables - */ -uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type); - -/** - * @brief Returns raw contents of DRam0 status register 1 - * - * @return 32-bit register value - */ -uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void); - -/** - * @brief Returns raw contents of DRam0 status register 2 - * - * @return 32-bit register value - */ -uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void); - -/** - * @brief Returns raw contents of IRam0 status register - * - * @return 32-bit register value - */ -uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void); - -/** - * @brief Register PMS violation interrupt in global interrupt matrix for given Memory type - * - * Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM - * The registration makes the panic-handler routine being called when the interrupt appears - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - */ -void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type); - -/** - * @brief Convenient routine for setting the PMS defaults - * - * Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings - * For implementation details see 'esp_memprot_set_prot_int' description - * - * @param invoke_panic_handler register all interrupts for panic handling (true/false) - * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false) - * @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int') - */ -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); - -/** - * @brief Internal routine for setting the PMS defaults - * - * Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address - * (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line - * is used (&_iram_text_end) and all the remaining lines share the same address. - * The function sets all the split lines and PMS areas to the same space, - * ie there is a single instruction space and single data space at the end. - * The PMS split lines and permission areas scheme described below: - * - * DRam0/DMA IRam0 - * ----------------------------------------------- - * ... | IRam0_PMS_0 | - * DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr - * ... | IRam0_PMS_1 | - * ... ----------------------------------------------- IRam0_line0_Split_addr - * | IRam0_PMS_2 | - * =============================================== IRam0_DRam0_Split_addr (main I/D) - * | DRam0_PMS_1 | - * DRam0_DMA_line0_Split_addr ----------------------------------------------- ... - * | DRam0_PMS_2 | ... - * DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3 - * | DRam0_PMS_3 | ... - * ----------------------------------------------- - * - * Default settings provided by 'esp_memprot_set_prot_int' are as follows: - * - * DRam0/DMA IRam0 - * ----------------------------------------------- - * | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 | - * | DRam0_PMS_0 | IRam0_line1_Split_addr - * DRam0_DMA_line0_Split_addr | | = - * = =============================================== IRam0_line0_Split_addr - * DRam0_DMA_line1_Split_addr | | = - * | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D) - * | IRam0_PMS_3 | - * ----------------------------------------------- - * - * Once the memprot feature is locked, it can be unlocked only by digital system reset - * - * @param invoke_panic_handler register all the violation interrupts for panic handling (true/false) - * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false) - * @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end) - * @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t) - */ -void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask); - -/** - * @brief Returns raw contents of PMS interrupt monitor register for given Memory type - * - * @param mem_type Memory protection type (see mem_type_prot_t enum) - * - * @return 32-bit register value - */ -uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type); - -#ifdef __cplusplus -} -#endif 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 new file mode 100644 index 0000000000..3048088eba --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +////////////////////////////////////////////////////////// +// ESP32-H2 PMS memory protection types +// + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memory types recognized by PMS + */ +typedef enum { + MEMPROT_TYPE_NONE = 0x00000000, + MEMPROT_TYPE_ALL = 0x7FFFFFFF, + MEMPROT_TYPE_INVALID = 0x80000000 +} esp_mprot_mem_t; + +/** + * @brief Splitting address (line) type + */ +typedef enum { + MEMPROT_SPLIT_ADDR_NONE = 0x00000000, + MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF, + MEMPROT_SPLIT_ADDR_INVALID = 0x80000000 +} esp_mprot_split_addr_t; + +/** + * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address) + */ +typedef enum { + MEMPROT_PMS_AREA_NONE = 0x00000000, + MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF, + MEMPROT_PMS_AREA_INVALID = 0x80000000 +} esp_mprot_pms_area_t; + +/** +* @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 */ +} esp_memp_config_t; + +#define ESP_MEMPROT_DEFAULT_CONFIG() {\ + .invoke_panic_handler = true, \ + .lock_feature = true, \ + .split_addr = NULL, \ + .mem_type_mask = MEMPROT_TYPE_ALL \ +} + +/** + * @brief Converts Memory protection type to string + * + * @param mem_type Memory protection type + */ +static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type) +{ + switch (mem_type) { + case MEMPROT_TYPE_NONE: + return "MEMPROT_TYPE_NONE"; + case MEMPROT_TYPE_ALL: + return "MEMPROT_TYPE_ALL"; + default: + return "MEMPROT_TYPE_INVALID"; + } +} + +/** + * @brief Converts Splitting address type to string + * + * @param line_type Split line type + */ +static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type) +{ + switch (line_type) { + case MEMPROT_SPLIT_ADDR_NONE: + return "MEMPROT_SPLIT_ADDR_NONE"; + case MEMPROT_SPLIT_ADDR_ALL: + return "MEMPROT_SPLIT_ADDR_ALL"; + default: + return "MEMPROT_SPLIT_ADDR_INVALID"; + } +} + +/** + * @brief Converts PMS Area type to string + * + * @param area_type PMS Area type + */ +static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type) +{ + switch (area_type) { + case MEMPROT_PMS_AREA_NONE: + return "MEMPROT_PMS_AREA_NONE"; + case MEMPROT_PMS_AREA_ALL: + return "MEMPROT_PMS_AREA_ALL"; + default: + return "MEMPROT_PMS_AREA_INVALID"; + } +} + +#ifdef __cplusplus +} +#endif 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 new file mode 100644 index 0000000000..f17e214313 --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +////////////////////////////////////////////////////////// +// ESP32-S2 PMS memory protection types +// + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memory types recognized by PMS + */ +typedef enum { + MEMPROT_TYPE_NONE = 0x00000000, + MEMPROT_TYPE_ALL = 0x7FFFFFFF, + MEMPROT_TYPE_INVALID = 0x80000000 +} esp_mprot_mem_t; + +/** + * @brief Splitting address (line) type + */ +typedef enum { + MEMPROT_SPLIT_ADDR_NONE = 0x00000000, + MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF, + MEMPROT_SPLIT_ADDR_INVALID = 0x80000000 +} esp_mprot_split_addr_t; + +/** + * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address) + */ +typedef enum { + MEMPROT_PMS_AREA_NONE = 0x00000000, + MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF, + MEMPROT_PMS_AREA_INVALID = 0x80000000 +} esp_mprot_pms_area_t; + +/** +* @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 */ +} esp_memp_config_t; + +#define ESP_MEMPROT_DEFAULT_CONFIG() { \ + .invoke_panic_handler = true, \ + .lock_feature = true, \ + .split_addr = NULL, \ + .mem_type_mask = MEMPROT_TYPE_ALL \ +} + +/** + * @brief Converts Memory protection type to string + * + * @param mem_type Memory protection type + */ +static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type) +{ + switch (mem_type) { + case MEMPROT_TYPE_NONE: + return "MEMPROT_TYPE_NONE"; + case MEMPROT_TYPE_ALL: + return "MEMPROT_TYPE_ALL"; + default: + return "MEMPROT_TYPE_INVALID"; + } +} + +/** + * @brief Converts Splitting address type to string + * + * @param line_type Split line type + */ +static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type) +{ + switch (line_type) { + case MEMPROT_SPLIT_ADDR_NONE: + return "MEMPROT_SPLIT_ADDR_NONE"; + case MEMPROT_SPLIT_ADDR_ALL: + return "MEMPROT_SPLIT_ADDR_ALL"; + default: + return "MEMPROT_SPLIT_ADDR_INVALID"; + } +} + +/** + * @brief Converts PMS Area type to string + * + * @param area_type PMS Area type + */ +static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type) +{ + switch (area_type) { + case MEMPROT_PMS_AREA_NONE: + return "MEMPROT_PMS_AREA_NONE"; + case MEMPROT_PMS_AREA_ALL: + return "MEMPROT_PMS_AREA_ALL"; + default: + return "MEMPROT_PMS_AREA_INVALID"; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/soc/esp32s3/memprot.h b/components/esp_hw_support/include/soc/esp32s3/memprot.h deleted file mode 100644 index 948e067668..0000000000 --- a/components/esp_hw_support/include/soc/esp32s3/memprot.h +++ /dev/null @@ -1,484 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -/* INTERNAL API - * generic interface to MMU memory protection features - */ - -#pragma once -#include -#include -#include "esp_attr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - MEMPROT_NONE = 0x00000000, - MEMPROT_IRAM0_SRAM = 0x00000001, - MEMPROT_DRAM0_SRAM = 0x00000002, - MEMPROT_IRAM0_RTCFAST = 0x00000004, - MEMPROT_DRAM0_RTCFAST = 0x00000008, - MEMPROT_PERI1_RTCSLOW = 0x00000010, - MEMPROT_PERI2_RTCSLOW_0 = 0x00000020, - MEMPROT_PERI2_RTCSLOW_1 = 0x00000040, - MEMPROT_ALL = 0xFFFFFFFF -} mem_type_prot_t; - - -/** - * @brief Returns splitting address for required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Splitting address for the memory region required. - * The address is given by region-specific global symbol exported from linker script, - * it is not read out from related configuration register. - */ -uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type); - -/** - * @brief Initializes illegal memory access control (MMU) for required memory section. - * - * All memory access interrupts share ETS_MEMACCESS_ERR_INUM input channel, it is caller's - * responsibility to properly detect actual intr. source as well as possible prioritization in case - * of multiple source reported during one intr.handling routine run - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - */ -void esp_memprot_intr_init(mem_type_prot_t mem_type); - -/** - * @brief Enable/disable the memory protection interrupt - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param enable enable/disable - */ -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); - -/** - * @brief Sets a request for clearing interrupt-on flag for specified memory region (register write) - * - * @note When called without actual interrupt-on flag set, subsequent occurrence of related interrupt is ignored. - * Should be used only after the real interrupt appears, typically as the last step in interrupt handler's routine. - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - */ -void esp_memprot_clear_intr(mem_type_prot_t mem_type); - -/** - * @brief Detects which memory protection interrupt is active - * - * @note Check order - * MEMPROT_IRAM0_SRAM - * MEMPROT_IRAM0_RTCFAST - * MEMPROT_DRAM0_SRAM - * MEMPROT_DRAM0_RTCFAST - * - * @return Memory protection area type (see mem_type_prot_t enum) - */ -mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void); - -/** - * @brief Gets interrupt status register contents for specified memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Contents of status register - */ -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); - -/** - * @brief Get details of given interrupt status - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param faulting_address Faulting address causing the interrupt [out] - * @param op_type Operation being processed at the faulting address [out] - * IRAM0: 0 - read, 1 - write - * DRAM0: 0 - read, 1 - write - * @param op_subtype Additional info for op_type [out] - * IRAM0: 0 - instruction segment access, 1 - data segment access - * DRAM0: 0 - non-atomic operation, 1 - atomic operation - */ -void IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); - -/** - * @brief Gets string representation of required memory region identifier - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return mem_type as string - */ -const char *IRAM_ATTR esp_memprot_type_to_str(mem_type_prot_t mem_type); - -/** - * @brief Detects whether any of the interrupt locks is active (requires digital system reset to unlock) - * - * @return true/false - */ -bool esp_memprot_is_locked_any(void); - -/** - * @brief Sets lock for specified memory region. - * - * Locks can be unlocked only by digital system reset - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - */ -void esp_memprot_set_lock(mem_type_prot_t mem_type); - -/** - * @brief Gets lock status for required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return true/false (locked/unlocked) - */ -bool esp_memprot_get_lock(mem_type_prot_t mem_type); - -/** - * @brief Gets permission control configuration register contents for required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Permission control register contents - */ -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); - -/** - * @brief Gets interrupt permission settings for unified management block - * - * Gets interrupt permission settings register contents for required memory region, returns settings for unified management blocks - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Permission settings register contents - */ -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type); - -/** - * @brief Gets interrupt permission settings for split management block - * - * Gets interrupt permission settings register contents for required memory region, returns settings for split management blocks - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Permission settings register contents - */ -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type); - -/** - * @brief Detects whether any of the memory protection interrupts is enabled - * - * @return true/false - */ -bool esp_memprot_is_intr_ena_any(void); - -/** - * @brief Gets interrupt-enabled flag for given memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Interrupt-enabled value - */ -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type); - -/** - * @brief Gets interrupt-active flag for given memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Interrupt-active value - */ -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type); - -/** - * @brief Gets interrupt-clear request flag for given memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * - * @return Interrupt-clear request value - */ -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); - -/** - * @brief Gets read permission value for specified block and memory region - * - * Returns read permission bit value for required unified-management block (0-3) in given memory region. - * Applicable to all memory types. - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param block Memory block identifier (0-3) - * - * @return Read permission value for required block - */ -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block); - -/** - * @brief Gets write permission value for specified block and memory region - * - * Returns write permission bit value for required unified-management block (0-3) in given memory region. - * Applicable to all memory types. - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param block Memory block identifier (0-3) - * - * @return Write permission value for required block - */ -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block); - -/** - * @brief Gets execute permission value for specified block and memory region - * - * Returns execute permission bit value for required unified-management block (0-3) in given memory region. - * Applicable only to IRAM memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param block Memory block identifier (0-3) - * - * @return Execute permission value for required block - */ -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block); - -/** - * @brief Sets permissions for specified block in DRAM region - * - * Sets Read and Write permission for specified unified-management block (0-3) in given memory region. - * Applicable only to DRAM memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param block Memory block identifier (0-3) - * @param write_perm Write permission flag - * @param read_perm Read permission flag - */ -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); - -/** - * @brief Sets permissions for high and low memory segment in DRAM region - * - * Sets Read and Write permission for both low and high memory segments given by splitting address. - * The splitting address must be equal to or higher then beginning of block 5 - * Applicable only to DRAM memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param split_addr Address to split the memory region to lower and higher segment - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - */ -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); - -/** - * @brief Sets permissions for specified block in IRAM region - * - * Sets Read, Write and Execute permission for specified unified-management block (0-3) in given memory region. - * Applicable only to IRAM memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param block Memory block identifier (0-3) - * @param write_perm Write permission flag - * @param exec_perm Execute permission flag - */ -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); - -/** - * @brief Sets permissions for high and low memory segment in IRAM region - * - * Sets Read, Write and Execute permission for both low and high memory segments given by splitting address. - * The splitting address must be equal to or higher then beginning of block 5 - * Applicable only to IRAM memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param split_addr Address to split the memory region to lower and higher segment - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param lx Low segment Execute permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - * @param hx High segment Execute permission flag - */ -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); - -/** - * @brief Activates memory protection for all supported memory region types - * - * @note The feature is disabled when JTAG interface is connected - * - * @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing) - * @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing) - * @param mem_type_mask holds a set of required memory protection types (bitmask built of mem_type_prot_t). NULL means default (MEMPROT_ALL in this version) - */ -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); - -/** - * @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param lx Low segment Execute permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - * @param hx High segment Execute permission flag - */ -void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); - -/** - * @brief Get permission settings bits for DRAM0 split mgmt. Only DRAM0 memory types allowed - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - */ -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); - -/** - * @brief Sets permissions for high and low memory segment in PERIBUS1 region - * - * Sets Read and Write permission for both low and high memory segments given by splitting address. - * Applicable only to PERIBUS1 memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param split_addr Address to split the memory region to lower and higher segment - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - */ -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); - -/** - * @brief Get permission settings bits for PERIBUS1 split mgmt. Only PERIBUS1 memory types allowed - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - */ -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); - -/** - * @brief Get permission settings bits for PERIBUS2 split mgmt. Only PERIBUS2 memory types allowed - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param lx Low segment Execute permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - * @param hx High segment Execute permission flag - */ -void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); - -/** - * @brief Sets permissions for high and low memory segment in PERIBUS2 region - * - * Sets Read Write permission for both low and high memory segments given by splitting address. - * Applicable only to PERIBUS2 memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param split_addr Address to split the memory region to lower and higher segment - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param lx Low segment Execute permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - * @param hx High segment Execute permission flag - */ -void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); - -/** - * @brief Get permissions for specified memory type. Irrelevant bits are ignored - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lw Low segment Write permission flag - * @param lr Low segment Read permission flag - * @param lx Low segment Execute permission flag - * @param hw High segment Write permission flag - * @param hr High segment Read permission flag - * @param hx High segment Execute permission flag - */ -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); - -/** - * @brief Get Read permission settings for low and high regions of given memory type - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Read permission flag - * @param hr High segment Read permission flag - */ -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); - -/** - * @brief Get Write permission settings for low and high regions of given memory type - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Write permission flag - * @param hr High segment Write permission flag - */ -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw); - -/** - * @brief Get Execute permission settings for low and high regions of given memory type - * Applicable only to IBUS-compatible memory types - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Exec permission flag - * @param hr High segment Exec permission flag - */ -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx); - -/** - * @brief Returns the lowest address in required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - */ -uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type); - -/** - * @brief Returns the highest address in required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - */ -uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type); - -/** - * @brief Sets READ permission bit for required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Read permission flag - * @param hr High segment Read permission flag - */ -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); - -/** - * @brief Sets WRITE permission bit for required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Write permission flag - * @param hr High segment Write permission flag - */ -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw); - -/** - * @brief Sets EXECUTE permission bit for required memory region - * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Exec permission flag - * @param hr High segment Exec permission flag - */ -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); - - -#ifdef __cplusplus -} -#endif 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 new file mode 100644 index 0000000000..06dde33ffa --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h @@ -0,0 +1,119 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +////////////////////////////////////////////////////////// +// ESP32-S3 PMS memory protection types +// + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memory types recognized by PMS + */ +typedef enum { + MEMPROT_TYPE_NONE = 0x00000000, + MEMPROT_TYPE_ALL = 0x7FFFFFFF, + MEMPROT_TYPE_INVALID = 0x80000000 +} esp_mprot_mem_t; + +/** + * @brief Splitting address (line) type + */ +typedef enum { + MEMPROT_SPLIT_ADDR_NONE = 0x00000000, + MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF, + MEMPROT_SPLIT_ADDR_INVALID = 0x80000000 +} esp_mprot_split_addr_t; + +/** + * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address) + */ +typedef enum { + MEMPROT_PMS_AREA_NONE = 0x00000000, + MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF, + MEMPROT_PMS_AREA_INVALID = 0x80000000 +} esp_mprot_pms_area_t; + +/** +* @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 */ +} esp_memp_config_t; + +#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} \ +} + +/** + * @brief Converts Memory protection type to string + * + * @param mem_type Memory protection type + */ +static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type) +{ + switch (mem_type) { + case MEMPROT_TYPE_NONE: + return "MEMPROT_TYPE_NONE"; + case MEMPROT_TYPE_ALL: + return "MEMPROT_TYPE_ALL"; + default: + return "MEMPROT_TYPE_INVALID"; + } +} + +/** + * @brief Converts Splitting address type to string + * + * @param line_type Split line type + */ +static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type) +{ + switch (line_type) { + case MEMPROT_SPLIT_ADDR_NONE: + return "MEMPROT_SPLIT_ADDR_NONE"; + case MEMPROT_SPLIT_ADDR_ALL: + return "MEMPROT_SPLIT_ADDR_ALL"; + default: + return "MEMPROT_SPLIT_ADDR_INVALID"; + } +} + +/** + * @brief Converts PMS Area type to string + * + * @param area_type PMS Area type + */ +static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type) +{ + switch (area_type) { + case MEMPROT_PMS_AREA_NONE: + return "MEMPROT_PMS_AREA_NONE"; + case MEMPROT_PMS_AREA_ALL: + return "MEMPROT_PMS_AREA_ALL"; + default: + return "MEMPROT_PMS_AREA_INVALID"; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32c3/CMakeLists.txt b/components/esp_hw_support/port/esp32c3/CMakeLists.txt index f72abaac20..1544faad47 100644 --- a/components/esp_hw_support/port/esp32c3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c3/CMakeLists.txt @@ -10,11 +10,15 @@ set(srcs "cpu_util_esp32c3.c" if(NOT BOOTLOADER_BUILD) list(APPEND srcs "../async_memcpy_impl_gdma.c" - "memprot.c" "esp_hmac.c" "esp_crypto_lock.c" "esp_ds.c" "dport_access.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 new file mode 100644 index 0000000000..bbda57d2b2 --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/esp_memprot.c @@ -0,0 +1,869 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "soc/periph_defs.h" +#include "esp_intr_alloc.h" +#include "hal/memprot_ll.h" +#include "riscv/interrupt.h" +#include "esp32c3/rom/ets_sys.h" +#include "esp_cpu.h" +#include "esp_fault.h" +#include "esp_attr.h" +#include "hal/memprot_types.h" +#include "esp_private/esp_memprot_internal.h" +#include "esp_memprot.h" + +extern int _iram_text_end; +extern int _rtc_text_end; + +static void *esp_memprot_iram0_get_def_split_addr(void) +{ + return &_iram_text_end; +} + +static void *esp_memprot_dram0_get_def_split_addr(void) +{ + return MAP_IRAM_TO_DRAM(&_iram_text_end); +} + +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) +{ + 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 */ + return esp_mprot_ll_err_to_esp_err(memprot_ll_set_rtcfast_split_line(line_addr, MEMP_LL_WORLD_0)); + } 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) +{ + if (line_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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 */ + return esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(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; +} + +esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr) +{ + if (def_split_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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) +{ + 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! + memprot_ll_set_pif_constraint_lock(); + 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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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: + *locked = memprot_ll_get_pif_constraint_lock(); + 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) +{ + 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! + memprot_ll_set_pif_constraint_lock(); + 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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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: + *locked = memprot_ll_get_pif_constraint_lock(); + 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) +{ + 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: + memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW); + break; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI: + memprot_ll_rtcfast_set_pms_area(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) +{ + if (flags == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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: + memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW); + break; + case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI: + memprot_ll_rtcfast_get_pms_area(&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) +{ + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + memprot_ll_iram0_set_monitor_lock(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + memprot_ll_dram0_set_monitor_lock(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + memprot_ll_rtcfast_set_monitor_lock(); + 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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + *locked = memprot_ll_iram0_get_monitor_lock(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + *locked = memprot_ll_dram0_get_monitor_lock(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + *locked = memprot_ll_rtcfast_get_monitor_lock(); + 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) +{ + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + memprot_ll_iram0_set_monitor_en(enable); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + memprot_ll_dram0_set_monitor_en(enable); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + memprot_ll_rtcfast_set_monitor_en(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) +{ + if (enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + *enabled = memprot_ll_iram0_get_monitor_en(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + *enabled = memprot_ll_dram0_get_monitor_en(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + *enabled = memprot_ll_rtcfast_get_monitor_en(); + 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))) +{ + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + memprot_ll_iram0_set_monitor_intrclr(); + memprot_ll_iram0_reset_monitor_intrclr(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + memprot_ll_dram0_set_monitor_intrclr(); + memprot_ll_dram0_reset_monitor_intrclr(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + memprot_ll_rtcfast_set_monitor_intrclr(); + memprot_ll_rtcfast_reset_monitor_intrclr(); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr) +{ + if (active_memp_intr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + active_memp_intr->core = PRO_CPU_NUM; + + if (memprot_ll_iram0_get_monitor_status_intr() > 0) { + active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_SRAM; + } else if (memprot_ll_dram0_get_monitor_status_intr() > 0) { + active_memp_intr->mem_type = MEMPROT_TYPE_DRAM0_SRAM; + } else if (memprot_ll_rtcfast_get_monitor_status_intr() > 0) { + active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_RTCFAST; + } else { + active_memp_intr->mem_type = MEMPROT_TYPE_NONE; + } + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + 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)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on)) + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on)); + *locked |= lock_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on)); + *locked |= lock_on; + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled) +{ + if (enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + bool ena_on = false; + esp_err_t res; + + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on)) + *enabled |= ena_on; + ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on)) + *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))) +{ + if (fault_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + *fault_addr = (void *)memprot_ll_iram0_get_monitor_status_fault_addr(); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + *fault_addr = (void *)memprot_ll_dram0_get_monitor_status_fault_addr(); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + *fault_addr = (void *)memprot_ll_rtcfast_get_monitor_status_fault_addr(); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + 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))) +{ + if (world == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_mprot_pms_world_t res; + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + res = esp_mprot_ll_world_to_hl_world(memprot_ll_iram0_get_monitor_status_fault_world()); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + res = esp_mprot_ll_world_to_hl_world(memprot_ll_dram0_get_monitor_status_fault_world()); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + res = esp_mprot_ll_world_to_hl_world(memprot_ll_rtcfast_get_monitor_status_fault_world()); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + if (res == MEMPROT_PMS_WORLD_INVALID) { + return ESP_ERR_MEMPROT_WORLD_INVALID; + } + + *world = res; + + 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))) +{ + if (oper == NULL) { + return ESP_ERR_INVALID_ARG; + } + + uint32_t operation = MEMPROT_OP_NONE; + + if ((mem_type == MEMPROT_TYPE_IRAM0_SRAM && memprot_ll_iram0_get_monitor_status_fault_loadstore() == 0) || + (mem_type == MEMPROT_TYPE_IRAM0_RTCFAST && memprot_ll_rtcfast_get_monitor_status_fault_loadstore() == 0)) { + operation = MEMPROT_OP_EXEC; + } + + if (operation == MEMPROT_OP_NONE) { + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + operation = memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ; + break; + case MEMPROT_TYPE_DRAM0_SRAM: + operation = memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ; + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + operation = memprot_ll_rtcfast_get_monitor_status_fault_wr() == 1 ? 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 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))) +{ + if (byte_en == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_TYPE_DRAM0_SRAM: + *byte_en = memprot_ll_dram0_get_monitor_status_fault_byte_en(); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + return ESP_OK; +} + +/* internal */ +static esp_err_t esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type) +{ + ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM); + + switch (mem_type) { + case MEMPROT_TYPE_IRAM0_SRAM: + intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); + break; + case MEMPROT_TYPE_DRAM0_SRAM: + intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); + break; + case MEMPROT_TYPE_IRAM0_RTCFAST: + intr_matrix_set(PRO_CPU_NUM, memprot_ll_rtcfast_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); + break; + default: + return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID; + } + + /* Set the type and priority to cache error interrupts. */ + esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL); + esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); + + ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM); + + return ESP_OK; +} + +esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config) +{ + if (memp_config == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (memp_config->mem_type_mask == MEMPROT_TYPE_NONE) { + return ESP_ERR_NO_MEM; + } + + //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; + } + + 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; + esp_err_t ret = ESP_OK; + + //disable protection (must be unlocked) + if (use_iram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false)) + } + if (use_dram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false)) + } + if (use_rtcfast) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false)) + } + + //panic handling + if (memp_config->invoke_panic_handler) { + if (use_iram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_SRAM)) + } + if (use_dram0) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_DRAM0_SRAM)) + } + if (use_rtcfast) { + ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_RTCFAST)) + } + } + + //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 = 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)) + 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)))) + + //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)) + } + 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)) + } + 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)) + } + + //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)) + } + 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)) + } + 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)) + } + + //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)) + } + 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)) + } + 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)) + } + } + + 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 = calloc(1024, 1); + + if (*dump_info_string == NULL) { + return ESP_ERR_NO_MEM; + } + + 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, + "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); + + uint32_t 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(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 = memprot_ll_get_pif_constraint_lock(); + + 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 (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); + + 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(&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(&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); + + bool monitor_lock_i = memprot_ll_iram0_get_monitor_lock(); + bool monitor_en_i = memprot_ll_iram0_get_monitor_en(); + bool monitor_clr_i = memprot_ll_iram0_get_monitor_intrclr(); + bool monitor_lock_d = memprot_ll_dram0_get_monitor_lock(); + bool monitor_en_d = memprot_ll_dram0_get_monitor_en(); + bool monitor_clr_d = memprot_ll_dram0_get_monitor_intrclr(); + bool monitor_lock_rtc = memprot_ll_rtcfast_get_monitor_lock(); + bool monitor_en_rtc = memprot_ll_rtcfast_get_monitor_en(); + bool monitor_clr_rtc = memprot_ll_rtcfast_get_monitor_intrclr(); + + sprintf((*dump_info_string + offset), + "Monitor settings:\n" + " IRAM0 (lock=%u):\n enabled=%u\n intr_clr=%u\n" + " DRAM0 (lock=%u):\n enabled=%u\n intr_clr=%u\n" + " RTCFAST (lock=%u):\n enabled=%u\n intr_clr=%u\n", + monitor_lock_i, monitor_en_i, monitor_clr_i, + monitor_lock_d, monitor_en_d, monitor_clr_d, + monitor_lock_rtc, monitor_en_rtc, monitor_clr_rtc); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c3/memprot.c b/components/esp_hw_support/port/esp32c3/memprot.c deleted file mode 100644 index 72982b2397..0000000000 --- a/components/esp_hw_support/port/esp32c3/memprot.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* INTERNAL API - * implementation of PMS memory protection features - */ - -#include -#include "sdkconfig.h" -#include "soc/sensitive_reg.h" -#include "soc/dport_access.h" -#include "soc/periph_defs.h" -#include "esp_intr_alloc.h" -#include "hal/memprot_ll.h" -#include "esp32c3/memprot.h" -#include "riscv/interrupt.h" -#include "esp32c3/rom/ets_sys.h" -#include "esp_log.h" -#include "esp_fault.h" -#include "soc/cpu.h" - -extern int _iram_text_end; -static const char *TAG = "memprot"; - -const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type) -{ - switch (mem_type) { - case MEMPROT_NONE: - return "NONE"; - case MEMPROT_IRAM0_SRAM: - return "IRAM0_SRAM"; - case MEMPROT_DRAM0_SRAM: - return "DRAM0_SRAM"; - case MEMPROT_ALL: - return "ALL"; - default: - return "UNKNOWN"; - } -} - -const char *esp_memprot_split_line_to_str(split_line_t line_type) -{ - switch (line_type) { - case MEMPROT_IRAM0_DRAM0_SPLITLINE: - return "MEMPROT_IRAM0_DRAM0_SPLITLINE"; - case MEMPROT_IRAM0_LINE_0_SPLITLINE: - return "MEMPROT_IRAM0_LINE_0_SPLITLINE"; - case MEMPROT_IRAM0_LINE_1_SPLITLINE: - return "MEMPROT_IRAM0_LINE_1_SPLITLINE"; - case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE: - return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE"; - case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE: - return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE"; - default: - return "UNKNOWN"; - } -} - -const char *esp_memprot_pms_to_str(pms_area_t area_type) -{ - switch (area_type) { - case MEMPROT_IRAM0_PMS_AREA_0: - return "MEMPROT_IRAM0_PMS_AREA_0"; - case MEMPROT_IRAM0_PMS_AREA_1: - return "MEMPROT_IRAM0_PMS_AREA_1"; - case MEMPROT_IRAM0_PMS_AREA_2: - return "MEMPROT_IRAM0_PMS_AREA_2"; - case MEMPROT_IRAM0_PMS_AREA_3: - return "MEMPROT_IRAM0_PMS_AREA_3"; - case MEMPROT_DRAM0_PMS_AREA_0: - return "MEMPROT_DRAM0_PMS_AREA_0"; - case MEMPROT_DRAM0_PMS_AREA_1: - return "MEMPROT_DRAM0_PMS_AREA_1"; - case MEMPROT_DRAM0_PMS_AREA_2: - return "MEMPROT_DRAM0_PMS_AREA_2"; - case MEMPROT_DRAM0_PMS_AREA_3: - return "MEMPROT_DRAM0_PMS_AREA_3"; - default: - return "UNKNOWN"; - } -} - - -/* split lines */ - -void *esp_memprot_get_default_main_split_addr() -{ - return &_iram_text_end; -} - -uint32_t *esp_memprot_get_split_addr(split_line_t line_type) -{ - switch ( line_type ) { - case MEMPROT_IRAM0_DRAM0_SPLITLINE: - return memprot_ll_get_iram0_split_line_main_I_D(); - case MEMPROT_IRAM0_LINE_0_SPLITLINE: - return memprot_ll_get_iram0_split_line_I_0(); - case MEMPROT_IRAM0_LINE_1_SPLITLINE: - return memprot_ll_get_iram0_split_line_I_1(); - case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE: - return memprot_ll_get_dram0_split_line_D_0(); - case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE: - return memprot_ll_get_dram0_split_line_D_1(); - default: - abort(); - } -} - -void esp_memprot_set_split_line_lock() -{ - memprot_ll_set_iram0_dram0_split_line_lock(); -} - -bool esp_memprot_get_split_line_lock() -{ - return memprot_ll_get_iram0_dram0_split_line_lock(); -} - -void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr) -{ - ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr); - - //split-line must be divisible by 512 (PMS module restriction) - assert( ((uint32_t)line_addr) % 0x200 == 0 ); - - switch ( line_type ) { - case MEMPROT_IRAM0_DRAM0_SPLITLINE: - memprot_ll_set_iram0_split_line_main_I_D(line_addr); - break; - case MEMPROT_IRAM0_LINE_0_SPLITLINE: - memprot_ll_set_iram0_split_line_I_0(line_addr); - break; - case MEMPROT_IRAM0_LINE_1_SPLITLINE: - memprot_ll_set_iram0_split_line_I_1(line_addr); - break; - case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE: - memprot_ll_set_dram0_split_line_D_0(line_addr); - break; - case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE: - memprot_ll_set_dram0_split_line_D_1(line_addr); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr); - abort(); - } -} - - -/* PMS */ - -void esp_memprot_set_pms_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_set_pms_lock(); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_set_pms_lock(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_pms_lock(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_pms_lock(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x); - - switch ( area_type ) { - case MEMPROT_IRAM0_PMS_AREA_0: - memprot_ll_iram0_set_pms_area_0(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_1: - memprot_ll_iram0_set_pms_area_1(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_2: - memprot_ll_iram0_set_pms_area_2(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_3: - memprot_ll_iram0_set_pms_area_3(r, w, x); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - -void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w); - - switch ( area_type ) { - case MEMPROT_IRAM0_PMS_AREA_0: - memprot_ll_iram0_get_pms_area_0(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_1: - memprot_ll_iram0_get_pms_area_1(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_2: - memprot_ll_iram0_get_pms_area_2(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_3: - memprot_ll_iram0_get_pms_area_3(r, w, x); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - -void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w); - - switch ( area_type ) { - case MEMPROT_DRAM0_PMS_AREA_0: - memprot_ll_dram0_set_pms_area_0(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_1: - memprot_ll_dram0_set_pms_area_1(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_2: - memprot_ll_dram0_set_pms_area_2(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_3: - memprot_ll_dram0_set_pms_area_3(r, w); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - -void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w); - - switch ( area_type ) { - case MEMPROT_DRAM0_PMS_AREA_0: - memprot_ll_dram0_get_pms_area_0(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_1: - memprot_ll_dram0_get_pms_area_1(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_2: - memprot_ll_dram0_get_pms_area_2(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_3: - memprot_ll_dram0_get_pms_area_3(r, w); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - - -/* monitor */ - -void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_set_monitor_lock(); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_set_monitor_lock(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_lock(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_lock(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_set_monitor_en(enable); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_set_monitor_en(enable); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_en(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_en(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_is_intr_ena_any() -{ - return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM); -} - -void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_clear_monitor_intr(); - memprot_ll_iram0_reset_clear_monitor_intr(); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_clear_monitor_intr(); - memprot_ll_dram0_reset_clear_monitor_intr(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -mem_type_prot_t esp_memprot_get_active_intr_memtype() -{ - if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) { - return MEMPROT_IRAM0_SRAM; - } else if ( memprot_ll_dram0_get_monitor_status_intr() ) { - return MEMPROT_DRAM0_SRAM; - } - - return MEMPROT_NONE; -} - -bool esp_memprot_is_locked_any() -{ - return - esp_memprot_get_split_line_lock() || - esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) || - esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) || - esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) || - esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM); -} - -bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_intr() == 1; - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_intr() == 1; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_fault_addr(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_fault_addr(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type) -{ - uint32_t world = 0; - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - world = memprot_ll_iram0_get_monitor_status_fault_world(); - break; - case MEMPROT_DRAM0_SRAM: - world = memprot_ll_dram0_get_monitor_status_fault_world(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } - - switch ( world ) { - case 0x01: return MEMPROT_PMS_WORLD_0; - case 0x10: return MEMPROT_PMS_WORLD_1; - default: return MEMPROT_PMS_WORLD_INVALID; - } -} - -pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ; - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_fault_byte_en(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -int esp_memprot_intr_get_cpuid() -{ - return PRO_CPU_NUM; -} - -void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type)); - - ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM); - - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); - break; - case MEMPROT_DRAM0_SRAM: - intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } - - /* Set the type and priority to cache error interrupts. */ - esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL); - esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); - - ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM); -} - -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) -{ - esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask); -} - -void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask); - - uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask; - bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM; - bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM; - - if (required_mem_prot == MEMPROT_NONE) { - return; - } - - //disable protection - if (use_iram0) { - esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false); - } - if (use_dram0) { - esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false); - } - - //if being debugged check we are not glitched and dont enable Memprot - if (esp_cpu_in_ocd_debug_mode()) { - ESP_FAULT_ASSERT(esp_cpu_in_ocd_debug_mode()); - } else { - - if (invoke_panic_handler) { - if (use_iram0) { - esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM); - } - if (use_dram0) { - esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM); - } - } - - //set split lines (must-have for all mem_types) - const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr; - esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr); - esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr); - esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr); - esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, - (void *) (MAP_IRAM_TO_DRAM((uint32_t) line_addr))); - esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE, - (void *) (MAP_IRAM_TO_DRAM((uint32_t) line_addr))); - - //set permissions - if (required_mem_prot & MEMPROT_IRAM0_SRAM) { - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false); - } - if (required_mem_prot & MEMPROT_DRAM0_SRAM) { - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_0, true, false); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true); - } - - //reenable the protection - if (use_iram0) { - esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM); - esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true); - } - if (use_dram0) { - esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM); - esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true); - } - - //lock if required - if (lock_feature) { - esp_memprot_set_split_line_lock(); - if (use_iram0) { - esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM); - esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM); - } - if (use_dram0) { - esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM); - esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM); - } - } - } -} - -uint32_t esp_memprot_get_dram_status_reg_1() -{ - return memprot_ll_dram0_get_monitor_status_register_1(); -} - -uint32_t esp_memprot_get_dram_status_reg_2() -{ - return memprot_ll_dram0_get_monitor_status_register_2(); -} - -uint32_t esp_memprot_get_iram_status_reg() -{ - return memprot_ll_iram0_get_monitor_status_register(); -} - -uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_enable_register(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_enable_register(); - default: - abort(); - } -} diff --git a/components/esp_hw_support/port/esp32h2/CMakeLists.txt b/components/esp_hw_support/port/esp32h2/CMakeLists.txt index 46e1b856ec..2b723bcd9f 100644 --- a/components/esp_hw_support/port/esp32h2/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h2/CMakeLists.txt @@ -10,11 +10,15 @@ set(srcs "cpu_util_esp32h2.c" if(NOT BOOTLOADER_BUILD) list(APPEND srcs "../async_memcpy_impl_gdma.c" - "memprot.c" "esp_hmac.c" "esp_crypto_lock.c" "esp_ds.c" "dport_access.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 new file mode 100644 index 0000000000..df6f58e79e --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/esp_memprot.c @@ -0,0 +1,215 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "soc/periph_defs.h" +#include "esp_intr_alloc.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) +{ + 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) +{ + if (line_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *line_addr = NULL; + + return ESP_OK; +} + +esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr) +{ + if (def_split_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *def_split_addr = NULL; + + return ESP_OK; +} + +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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags) +{ + return ESP_OK; +} + +esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags) +{ + if (flags == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *flags = MEMPROT_OP_NONE; + + return ESP_OK; +} + +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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable) +{ + return ESP_OK; +} + +esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled) +{ + if (enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *enabled = false; + + 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; +} + +esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr) +{ + if (active_memp_intr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + active_memp_intr->mem_type = MEMPROT_TYPE_NONE; + active_memp_intr->core = -1; + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled) +{ + if (enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *enabled = false; + + 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))) +{ + if (fault_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *fault_addr = NULL; + + 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))) +{ + if (world == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *world = MEMPROT_PMS_WORLD_NONE; + + 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))) +{ + if (oper == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *oper = MEMPROT_OP_NONE; + + return ESP_OK; +} + +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))) +{ + if (byte_en == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *byte_en = 0; + + return ESP_OK; +} + +esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config) +{ + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32h2/memprot.c b/components/esp_hw_support/port/esp32h2/memprot.c deleted file mode 100644 index 9e79de34f4..0000000000 --- a/components/esp_hw_support/port/esp32h2/memprot.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* INTERNAL API - * implementation of PMS memory protection features - */ - -#include -#include "sdkconfig.h" -#include "soc/sensitive_reg.h" -#include "soc/dport_access.h" -#include "soc/periph_defs.h" -#include "esp_intr_alloc.h" -#include "hal/memprot_ll.h" -#include "esp32h2/memprot.h" -#include "riscv/interrupt.h" -#include "esp32h2/rom/ets_sys.h" -#include "esp_log.h" - -extern int _iram_text_end; -static const char *TAG = "memprot"; - -const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type) -{ - switch (mem_type) { - case MEMPROT_NONE: - return "NONE"; - case MEMPROT_IRAM0_SRAM: - return "IRAM0_SRAM"; - case MEMPROT_DRAM0_SRAM: - return "DRAM0_SRAM"; - case MEMPROT_ALL: - return "ALL"; - default: - return "UNKNOWN"; - } -} - -const char *esp_memprot_split_line_to_str(split_line_t line_type) -{ - switch (line_type) { - case MEMPROT_IRAM0_DRAM0_SPLITLINE: - return "MEMPROT_IRAM0_DRAM0_SPLITLINE"; - case MEMPROT_IRAM0_LINE_0_SPLITLINE: - return "MEMPROT_IRAM0_LINE_0_SPLITLINE"; - case MEMPROT_IRAM0_LINE_1_SPLITLINE: - return "MEMPROT_IRAM0_LINE_1_SPLITLINE"; - case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE: - return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE"; - case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE: - return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE"; - default: - return "UNKNOWN"; - } -} - -const char *esp_memprot_pms_to_str(pms_area_t area_type) -{ - switch (area_type) { - case MEMPROT_IRAM0_PMS_AREA_0: - return "MEMPROT_IRAM0_PMS_AREA_0"; - case MEMPROT_IRAM0_PMS_AREA_1: - return "MEMPROT_IRAM0_PMS_AREA_1"; - case MEMPROT_IRAM0_PMS_AREA_2: - return "MEMPROT_IRAM0_PMS_AREA_2"; - case MEMPROT_IRAM0_PMS_AREA_3: - return "MEMPROT_IRAM0_PMS_AREA_3"; - case MEMPROT_DRAM0_PMS_AREA_0: - return "MEMPROT_DRAM0_PMS_AREA_0"; - case MEMPROT_DRAM0_PMS_AREA_1: - return "MEMPROT_DRAM0_PMS_AREA_1"; - case MEMPROT_DRAM0_PMS_AREA_2: - return "MEMPROT_DRAM0_PMS_AREA_2"; - case MEMPROT_DRAM0_PMS_AREA_3: - return "MEMPROT_DRAM0_PMS_AREA_3"; - default: - return "UNKNOWN"; - } -} - - -/* split lines */ - -void *esp_memprot_get_default_main_split_addr() -{ - return &_iram_text_end; -} - -uint32_t *esp_memprot_get_split_addr(split_line_t line_type) -{ - switch ( line_type ) { - case MEMPROT_IRAM0_DRAM0_SPLITLINE: - return memprot_ll_get_iram0_split_line_main_I_D(); - case MEMPROT_IRAM0_LINE_0_SPLITLINE: - return memprot_ll_get_iram0_split_line_I_0(); - case MEMPROT_IRAM0_LINE_1_SPLITLINE: - return memprot_ll_get_iram0_split_line_I_1(); - case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE: - return memprot_ll_get_dram0_split_line_D_0(); - case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE: - return memprot_ll_get_dram0_split_line_D_1(); - default: - abort(); - } -} - -void esp_memprot_set_split_line_lock() -{ - memprot_ll_set_iram0_dram0_split_line_lock(); -} - -bool esp_memprot_get_split_line_lock() -{ - return memprot_ll_get_iram0_dram0_split_line_lock(); -} - -void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr) -{ - ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr); - - //split-line must be divisible by 512 (PMS module restriction) - assert( ((uint32_t)line_addr) % 0x200 == 0 ); - - switch ( line_type ) { - case MEMPROT_IRAM0_DRAM0_SPLITLINE: - memprot_ll_set_iram0_split_line_main_I_D(line_addr); - break; - case MEMPROT_IRAM0_LINE_0_SPLITLINE: - memprot_ll_set_iram0_split_line_I_0(line_addr); - break; - case MEMPROT_IRAM0_LINE_1_SPLITLINE: - memprot_ll_set_iram0_split_line_I_1(line_addr); - break; - case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE: - memprot_ll_set_dram0_split_line_D_0(line_addr); - break; - case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE: - memprot_ll_set_dram0_split_line_D_1(line_addr); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr); - abort(); - } -} - - -/* PMS */ - -void esp_memprot_set_pms_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_set_pms_lock(); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_set_pms_lock(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_pms_lock(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_pms_lock(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x); - - switch ( area_type ) { - case MEMPROT_IRAM0_PMS_AREA_0: - memprot_ll_iram0_set_pms_area_0(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_1: - memprot_ll_iram0_set_pms_area_1(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_2: - memprot_ll_iram0_set_pms_area_2(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_3: - memprot_ll_iram0_set_pms_area_3(r, w, x); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - -void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w); - - switch ( area_type ) { - case MEMPROT_IRAM0_PMS_AREA_0: - memprot_ll_iram0_get_pms_area_0(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_1: - memprot_ll_iram0_get_pms_area_1(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_2: - memprot_ll_iram0_get_pms_area_2(r, w, x); - break; - case MEMPROT_IRAM0_PMS_AREA_3: - memprot_ll_iram0_get_pms_area_3(r, w, x); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - -void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w); - - switch ( area_type ) { - case MEMPROT_DRAM0_PMS_AREA_0: - memprot_ll_dram0_set_pms_area_0(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_1: - memprot_ll_dram0_set_pms_area_1(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_2: - memprot_ll_dram0_set_pms_area_2(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_3: - memprot_ll_dram0_set_pms_area_3(r, w); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - -void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w); - - switch ( area_type ) { - case MEMPROT_DRAM0_PMS_AREA_0: - memprot_ll_dram0_get_pms_area_0(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_1: - memprot_ll_dram0_get_pms_area_1(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_2: - memprot_ll_dram0_get_pms_area_2(r, w); - break; - case MEMPROT_DRAM0_PMS_AREA_3: - memprot_ll_dram0_get_pms_area_3(r, w); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type)); - abort(); - } -} - - -/* monitor */ - -void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_set_monitor_lock(); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_set_monitor_lock(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_lock(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_lock(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_set_monitor_en(enable); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_set_monitor_en(enable); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_en(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_en(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_is_intr_ena_any() -{ - return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM); -} - -void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type)); - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - memprot_ll_iram0_clear_monitor_intr(); - memprot_ll_iram0_reset_clear_monitor_intr(); - break; - case MEMPROT_DRAM0_SRAM: - memprot_ll_dram0_clear_monitor_intr(); - memprot_ll_dram0_reset_clear_monitor_intr(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -mem_type_prot_t esp_memprot_get_active_intr_memtype() -{ - if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) { - return MEMPROT_IRAM0_SRAM; - } else if ( memprot_ll_dram0_get_monitor_status_intr() ) { - return MEMPROT_DRAM0_SRAM; - } - - return MEMPROT_NONE; -} - -bool esp_memprot_is_locked_any() -{ - return - esp_memprot_get_split_line_lock() || - esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) || - esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) || - esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) || - esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM); -} - -bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_intr() == 1; - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_intr() == 1; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_fault_addr(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_fault_addr(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type) -{ - uint32_t world = 0; - - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - world = memprot_ll_iram0_get_monitor_status_fault_world(); - break; - case MEMPROT_DRAM0_SRAM: - world = memprot_ll_dram0_get_monitor_status_fault_world(); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } - - switch ( world ) { - case 0x01: return MEMPROT_PMS_WORLD_0; - case 0x10: return MEMPROT_PMS_WORLD_1; - default: return MEMPROT_PMS_WORLD_INVALID; - } -} - -pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ; - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type) -{ - switch ( mem_type ) { - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_status_fault_byte_en(); - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } -} - -int esp_memprot_intr_get_cpuid() -{ - return PRO_CPU_NUM; -} - -void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type)); - - ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM); - - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); - break; - case MEMPROT_DRAM0_SRAM: - intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM); - break; - default: - ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type)); - abort(); - } - - /* Set the type and priority to cache error interrupts. */ - esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL); - esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); - - ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM); -} - -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) -{ - esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask); -} - -void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask) -{ - ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask); - - uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask; - bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM; - bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM; - - if (required_mem_prot == MEMPROT_NONE) { - return; - } - - //disable protection - if (use_iram0) { - esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false); - } - if (use_dram0) { - esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false); - } - - //panic handling - if (invoke_panic_handler) { - if (use_iram0) { - esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM); - } - if (use_dram0) { - esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM); - } - } - - //set split lines (must-have for all mem_types) - const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr; - esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr); - esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr); - esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr); - esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))); - esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))); - - //set permissions - if (required_mem_prot & MEMPROT_IRAM0_SRAM) { - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false); - } - if (required_mem_prot & MEMPROT_DRAM0_SRAM) { - esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, true, false ); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true); - } - - //reenable protection - if (use_iram0) { - esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM); - esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true); - } - if (use_dram0) { - esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM); - esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true); - } - - //lock if required - if (lock_feature) { - esp_memprot_set_split_line_lock(); - if (use_iram0) { - esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM); - esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM); - } - if (use_dram0) { - esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM); - esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM); - } - } -} - -uint32_t esp_memprot_get_dram_status_reg_1() -{ - return memprot_ll_dram0_get_monitor_status_register_1(); -} - -uint32_t esp_memprot_get_dram_status_reg_2() -{ - return memprot_ll_dram0_get_monitor_status_register_2(); -} - -uint32_t esp_memprot_get_iram_status_reg() -{ - return memprot_ll_iram0_get_monitor_status_register(); -} - -uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return memprot_ll_iram0_get_monitor_enable_register(); - case MEMPROT_DRAM0_SRAM: - return memprot_ll_dram0_get_monitor_enable_register(); - default: - abort(); - } -} diff --git a/components/esp_hw_support/port/esp32s3/CMakeLists.txt b/components/esp_hw_support/port/esp32s3/CMakeLists.txt index e375c6df6d..c4b6b5f8f3 100644 --- a/components/esp_hw_support/port/esp32s3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32s3/CMakeLists.txt @@ -18,7 +18,6 @@ if(NOT BOOTLOADER_BUILD) "esp_hmac.c" "esp_ds.c" "esp_crypto_lock.c" - "memprot.c" "spiram.c") if(CONFIG_SPIRAM_MODE_QUAD) @@ -27,6 +26,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "opiram_psram.c") endif() + 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 new file mode 100644 index 0000000000..df6f58e79e --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/esp_memprot.c @@ -0,0 +1,215 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "soc/periph_defs.h" +#include "esp_intr_alloc.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) +{ + 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) +{ + if (line_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *line_addr = NULL; + + return ESP_OK; +} + +esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr) +{ + if (def_split_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *def_split_addr = NULL; + + return ESP_OK; +} + +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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags) +{ + return ESP_OK; +} + +esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags) +{ + if (flags == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *flags = MEMPROT_OP_NONE; + + return ESP_OK; +} + +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) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable) +{ + return ESP_OK; +} + +esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled) +{ + if (enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *enabled = false; + + 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; +} + +esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr) +{ + if (active_memp_intr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + active_memp_intr->mem_type = MEMPROT_TYPE_NONE; + active_memp_intr->core = -1; + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked) +{ + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *locked = false; + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled) +{ + if (enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *enabled = false; + + 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))) +{ + if (fault_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *fault_addr = NULL; + + 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))) +{ + if (world == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *world = MEMPROT_PMS_WORLD_NONE; + + 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))) +{ + if (oper == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *oper = MEMPROT_OP_NONE; + + return ESP_OK; +} + +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))) +{ + if (byte_en == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *byte_en = 0; + + return ESP_OK; +} + +esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config) +{ + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32s3/memprot.c b/components/esp_hw_support/port/esp32s3/memprot.c deleted file mode 100644 index 3fdbf55b9a..0000000000 --- a/components/esp_hw_support/port/esp32s3/memprot.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* INTERNAL API - * implementation of generic interface to MMU memory protection features - */ - -#include -#include "esp32s3/memprot.h" - -mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void) -{ - return MEMPROT_NONE; -} diff --git a/components/esp_hw_support/port/esp_memprot_conv.c b/components/esp_hw_support/port/esp_memprot_conv.c new file mode 100644 index 0000000000..e3d4557306 --- /dev/null +++ b/components/esp_hw_support/port/esp_memprot_conv.c @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_memprot_err.h" +#include "hal/memprot_types.h" +#include "esp_memprot_types.h" + +esp_err_t esp_mprot_ll_err_to_esp_err(const memprot_ll_err_t err) +{ + switch (err) { + case MEMP_LL_OK: return ESP_OK; + case MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE: return ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE; + case MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED: return ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED; + case MEMP_LL_ERR_UNI_BLOCK_INVALID: return ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID; + case MEMP_LL_ERR_WORLD_INVALID: return ESP_ERR_MEMPROT_WORLD_INVALID; + case MEMP_LL_ERR_AREA_INVALID: return ESP_ERR_MEMPROT_AREA_INVALID; + default: + return ESP_FAIL; + } +} + +esp_mprot_pms_world_t esp_mprot_ll_world_to_hl_world(const memprot_ll_world_t world) +{ + switch (world) { + case MEMP_LL_WORLD_NONE: return MEMPROT_PMS_WORLD_NONE; + case MEMP_LL_WORLD_0: return MEMPROT_PMS_WORLD_0; + case MEMP_LL_WORLD_1: return MEMPROT_PMS_WORLD_1; + default: + return MEMPROT_PMS_WORLD_INVALID; + } +} + +const char *esp_mprot_oper_type_to_str(const uint32_t oper_type) +{ + switch (oper_type) { + case MEMPROT_OP_NONE: return "NONE"; + case MEMPROT_OP_READ: return "READ"; + case MEMPROT_OP_WRITE: return "WRITE"; + case MEMPROT_OP_EXEC: return "EXEC"; + default: return "INVALID"; + } +} + +const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type) +{ + switch (world_type) { + case MEMPROT_PMS_WORLD_NONE: + return "PMS_WORLD_NONE"; + case MEMPROT_PMS_WORLD_0: + return "PMS_WORLD_0"; + case MEMPROT_PMS_WORLD_1: + return "PMS_WORLD_1"; + case MEMPROT_PMS_WORLD_2: + return "PMS_WORLD_2"; + case MEMPROT_PMS_WORLD_ALL: + return "PMS_WORLD_ALL"; + default: + return "PMS_WORLD_INVALID"; + } +} diff --git a/components/esp_system/esp_system.c b/components/esp_system/esp_system.c index da05aa0bd0..8d2457b2c0 100644 --- a/components/esp_system/esp_system.c +++ b/components/esp_system/esp_system.c @@ -14,14 +14,12 @@ #include "soc/rtc_cntl_reg.h" #include "esp_private/panic_internal.h" #include "esp_rom_uart.h" +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE #if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32C3 -#include "esp32c3/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32H2 -#include "esp32h2/memprot.h" +#else +#include "esp_memprot.h" +#endif #endif #define SHUTDOWN_HANDLERS_NO 5 @@ -86,9 +84,18 @@ void IRAM_ATTR esp_restart(void) bool digital_reset_needed = false; #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_IDF_TARGET_ESP32S2 if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) { digital_reset_needed = true; } +#else + bool is_on = false; + if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) { + digital_reset_needed = true; + } else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) { + digital_reset_needed = true; + } +#endif #endif if (digital_reset_needed) { esp_restart_noos_dig(); diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index 0ebeda06c1..e6fe6307a4 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -21,8 +21,9 @@ SECTIONS 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 */ + /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; . = ALIGN(4); @@ -368,7 +369,7 @@ 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 section exists for use by Memprot unit tests only */ *(.iram_end_test) /* ESP32-C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index f34f22fcfe..5736e5cd9b 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -15,11 +15,8 @@ #include "cache_err_int.h" #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE -#if CONFIG_IDF_TARGET_ESP32C3 -#include "esp32c3/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32H2 -#include "esp32h2/memprot.h" -#endif +#include "esp_private/esp_memprot_internal.h" +#include "esp_memprot.h" #endif #if CONFIG_ESP_SYSTEM_USE_EH_FRAME @@ -154,35 +151,62 @@ static inline void print_cache_err_details(const void *frame) * explanation of why the panic occured. */ #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE + +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(")"); + static inline void print_memprot_err_details(const void *frame __attribute__((unused))) { + if (s_memp_intr.mem_type == MEMPROT_TYPE_INVALID && s_memp_intr.core == -1) { + panic_print_str(" - no details available -\r\n"); + return; + } + //common memprot fault info - mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); - panic_print_str( " memory type: "); - panic_print_str( esp_memprot_mem_type_to_str(mem_type) ); - panic_print_str( "\r\n faulting address: 0x"); - panic_print_hex( esp_memprot_get_violate_addr(mem_type) ); - panic_print_str( "\r\n world:"); - panic_print_dec( esp_memprot_get_violate_world(mem_type) ); + panic_print_str(" memory type: "); + panic_print_str(esp_mprot_mem_type_to_str(s_memp_intr.mem_type)); - char operation = 0; - // IRAM fault: check instruction-fetch flag - if ( mem_type == MEMPROT_IRAM0_SRAM ) { - if ( esp_memprot_get_violate_loadstore(mem_type) ) { - operation = 'X'; - } + 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); + if (res == ESP_OK) { + panic_print_str("0x"); + panic_print_hex((int)faulting_addr); + } else { + PRINT_MEMPROT_ERROR(res) } - // W/R - common - if ( operation == 0 ) { - operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R'; + + 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); + if (res == ESP_OK) { + panic_print_str(esp_mprot_pms_world_to_str(world)); + } else { + PRINT_MEMPROT_ERROR(res) } + panic_print_str( "\r\n operation type: "); - panic_print_char( operation ); + uint32_t operation; + 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) + } - // DRAM/DMA fault: check byte-enables - if ( mem_type == MEMPROT_DRAM0_SRAM ) { + if (esp_mprot_has_byte_enables(s_memp_intr.mem_type)) { panic_print_str("\r\n byte-enables: " ); - panic_print_hex(esp_memprot_get_violate_byte_en(mem_type)); + uint32_t byte_enables; + 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) + } } panic_print_str("\r\n"); @@ -271,11 +295,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info) info->reason = pseudo_reason[PANIC_RSN_INTWDT_CPU0 + core]; } #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE - else if ( frame->mcause == ETS_MEMPROT_ERR_INUM ) { - - info->core = esp_memprot_intr_get_cpuid(); + else if (frame->mcause == ETS_MEMPROT_ERR_INUM) { info->reason = pseudo_reason[PANIC_RSN_MEMPROT]; info->details = print_memprot_err_details; + info->core = esp_mprot_get_active_intr(&s_memp_intr) == ESP_OK ? s_memp_intr.core : -1; } #endif } @@ -318,7 +341,8 @@ void panic_arch_fill_info(void *frame, panic_info_t *info) info->frame = ®s; } -static void panic_print_basic_backtrace(const void *frame, int core) { +static void panic_print_basic_backtrace(const void *frame, int core) +{ // Basic backtrace panic_print_str("\r\nStack memory:\r\n"); uint32_t sp = (uint32_t)((RvExcFrame *)frame)->sp; diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index 23d0b09453..c5c5eb5de1 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -22,13 +22,11 @@ #include "soc/extmem_reg.h" #include "soc/cache_memory.h" #include "soc/rtc_cntl_reg.h" -#if CONFIG_IDF_TARGET_ESP32S2 -#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#ifdef CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/memprot.h" -#endif -#elif CONFIG_IDF_TARGET_ESP32S3 -#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE -#include "esp32s3/memprot.h" +#else +#include "esp_memprot.h" #endif #endif #endif // CONFIG_IDF_TARGET_ESP32 @@ -268,13 +266,9 @@ static inline void print_memprot_err_details(const void *f) mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); if (mem_type != MEMPROT_NONE) { -#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged if (esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype) != ESP_OK) { op_type = MEMPROT_OP_INVALID; } -#else - esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype); -#endif } if (op_type == MEMPROT_OP_INVALID) { @@ -437,9 +431,11 @@ void panic_soc_fill_info(void *f, panic_info_t *info) info->exception = PANIC_EXCEPTION_DEBUG; } + //MV note: ESP32S3 PMS handling? + #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (frame->exccause == PANIC_RSN_CACHEERR) { -#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && CONFIG_IDF_TARGET_ESP32S2 if ( esp_memprot_is_intr_ena_any() ) { info->details = print_memprot_err_details; info->reason = "Memory protection fault"; diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index dca682c39d..e09b5d39d1 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -33,13 +33,11 @@ #include "esp32s2/rom/cache.h" #include "esp32s2/spiram.h" #include "esp32s2/dport_access.h" -#include "esp32s2/memprot.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rtc.h" #include "esp32s3/rom/cache.h" #include "esp32s3/spiram.h" #include "esp32s3/dport_access.h" -#include "esp32s3/memprot.h" #include "soc/assist_debug_reg.h" #include "soc/cache_memory.h" #include "soc/system_reg.h" @@ -48,12 +46,18 @@ #include "esp32c3/rtc.h" #include "esp32c3/rom/cache.h" #include "soc/cache_memory.h" -#include "esp32c3/memprot.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rtc.h" #include "esp32h2/rom/cache.h" #include "soc/cache_memory.h" -#include "esp32h2/memprot.h" +#endif + +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/memprot.h" +#else +#include "esp_memprot.h" +#endif #endif #include "esp_private/spi_flash_os.h" @@ -358,7 +362,7 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_IDF_TARGET_ESP32S3 extern int _rodata_reserved_end; - uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE)*sizeof(uint32_t); + uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE) * sizeof(uint32_t); #endif Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); @@ -475,12 +479,12 @@ void IRAM_ATTR call_start_cpu0(void) #endif extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off); - Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size/sizeof(uint32_t), \ - cache_mmu_drom_size/sizeof(uint32_t), \ - (uint32_t)&_rodata_reserved_start, \ - (uint32_t)&_rodata_reserved_end, \ - s_instr_flash2spiram_off, \ - s_rodata_flash2spiram_off); + Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size / sizeof(uint32_t), \ + cache_mmu_drom_size / sizeof(uint32_t), \ + (uint32_t)&_rodata_reserved_start, \ + (uint32_t)&_rodata_reserved_end, \ + s_instr_flash2spiram_off, \ + s_rodata_flash2spiram_off); #endif #if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP || \ @@ -548,32 +552,41 @@ void IRAM_ATTR call_start_cpu0(void) esp_cache_err_int_init(); -#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !CONFIG_ESP_SYSTEM_MEMPROT_TEST // Memprot cannot be locked during OS startup as the lock-on prevents any PMS changes until a next reboot // If such a situation appears, it is likely an malicious attempt to bypass the system safety setup -> print error & reset + +#if CONFIG_IDF_TARGET_ESP32S2 if (esp_memprot_is_locked_any()) { +#else + bool is_locked = false; + if (esp_mprot_is_conf_locked_any(&is_locked) != ESP_OK || is_locked) { +#endif ESP_EARLY_LOGE(TAG, "Memprot feature locked after the system reset! Potential safety corruption, rebooting."); esp_restart_noos_dig(); } + + //default configuration of PMS Memprot esp_err_t memp_err = ESP_OK; +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK -#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged - memp_err = esp_memprot_set_prot(true, true, NULL); + memp_err = esp_memprot_set_prot(PANIC_HNDL_ON, MEMPROT_LOCK, NULL); #else - esp_memprot_set_prot(true, true, NULL); -#endif -#else -#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged - memp_err = esp_memprot_set_prot(true, false, NULL); -#else - esp_memprot_set_prot(true, false, NULL); + memp_err = esp_memprot_set_prot(PANIC_HNDL_ON, MEMPROT_UNLOCK, NULL); #endif +#else //CONFIG_IDF_TARGET_ESP32S2 specific end + esp_memp_config_t memp_cfg = ESP_MEMPROT_DEFAULT_CONFIG(); +#if !CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK + memp_cfg.lock_feature = false; #endif + memp_err = esp_mprot_set_prot(&memp_cfg); +#endif //other IDF_TARGETS end + if (memp_err != ESP_OK) { - ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (error 0x%08X), rebooting.", memp_err); + ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (0x%08X: %s), rebooting.", memp_err, esp_err_to_name(memp_err)); esp_restart_noos_dig(); } -#endif +#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !CONFIG_ESP_SYSTEM_MEMPROT_TEST // Read the application binary image header. This will also decrypt the header if the image is encrypted. __attribute__((unused)) esp_image_header_t fhdr = {0}; diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c index 0ee5ac34d0..f7dd5399cf 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/panic_handler.c @@ -25,14 +25,14 @@ #if CONFIG_IDF_TARGET_ESP32 #include "esp32/dport_access.h" -#elif CONFIG_IDF_TARGET_ESP32S2 +#endif + +#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32C3 -#include "esp32c3/memprot.h" -#elif CONFIG_IDF_TARGET_ESP32H2 -#include "esp32h2/memprot.h" +#else +#include "esp_memprot.h" +#endif #endif #include "esp_private/panic_internal.h" @@ -229,9 +229,18 @@ void __attribute__((noreturn)) panic_restart(void) } #endif #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_IDF_TARGET_ESP32S2 if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) { digital_reset_needed = true; } +#else + bool is_on = false; + if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) { + digital_reset_needed = true; + } else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) { + digital_reset_needed = true; + } +#endif #endif if (digital_reset_needed) { esp_restart_noos_dig(); diff --git a/components/hal/esp32c3/include/hal/memprot_ll.h b/components/hal/esp32c3/include/hal/memprot_ll.h index ef3f15f952..4bfd38bae2 100644 --- a/components/hal/esp32c3/include/hal/memprot_ll.h +++ b/components/hal/esp32c3/include/hal/memprot_ll.h @@ -1,59 +1,22 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once -#include "soc/sensitive_reg.h" #include "soc/cache_memory.h" -#include "hal/assert.h" +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #ifdef __cplusplus extern "C" { #endif /* ****************************************************************************************************** - * *** GLOBALS *** - * NOTE: in this version, all the configurations apply only to WORLD_0 - */ - -#define IRAM_SRAM_START 0x4037C000 -#define DRAM_SRAM_START 0x3FC7C000 - -/* ICache size is fixed to 16KB on ESP32-C3 */ -#ifndef ICACHE_SIZE -#define ICACHE_SIZE 0x4000 -#endif - -#ifndef I_D_SRAM_SEGMENT_SIZE -#define I_D_SRAM_SEGMENT_SIZE 0x20000 -#endif - -#define I_D_SPLIT_LINE_SHIFT 0x9 -#define I_D_FAULT_ADDR_SHIFT 0x2 - -typedef union { - struct { - uint32_t cat0 : 2; - uint32_t cat1 : 2; - uint32_t cat2 : 2; - uint32_t res0 : 8; - uint32_t splitaddr : 8; - uint32_t res1 : 10; - }; - uint32_t val; -} constrain_reg_fields_t; - + * *** COMMON *** + * ******************************************************************************************************/ static inline void memprot_ll_set_iram0_dram0_split_line_lock(void) { REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, 1); @@ -64,7 +27,7 @@ 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(uint32_t regval, uint32_t base) +static inline void *memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t base) { constrain_reg_fields_t reg_val; reg_val.val = regval; @@ -85,43 +48,30 @@ static inline void* memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t /* ****************************************************************************************************** * *** IRAM0 *** - */ - -//16kB (CACHE) -#define IRAM0_SRAM_LEVEL_0_LOW IRAM_SRAM_START //0x40370000 -#define IRAM0_SRAM_LEVEL_0_HIGH (IRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x4037FFFF - -//128kB (LEVEL 1) -#define IRAM0_SRAM_LEVEL_1_LOW (IRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x40380000 -#define IRAM0_SRAM_LEVEL_1_HIGH (IRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x4039FFFF - -//128kB (LEVEL 2) -#define IRAM0_SRAM_LEVEL_2_LOW (IRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x403A0000 -#define IRAM0_SRAM_LEVEL_2_HIGH (IRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403BFFFF - -//128kB (LEVEL 3) -#define IRAM0_SRAM_LEVEL_3_LOW (IRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x403C0000 -#define IRAM0_SRAM_LEVEL_3_HIGH (IRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403DFFFF - -//permission bits -#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R 0x1 -#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W 0x2 -#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F 0x4 - + * ******************************************************************************************************/ static inline uint32_t memprot_ll_iram0_get_intr_source_num(void) { return ETS_CORE0_IRAM0_PMS_INTR_SOURCE; } - -/////////////////////////////////// -// IRAM0 - SPLIT LINES -/////////////////////////////////// - -static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg) +/* ******************************** + * IRAM0 - SPLIT LINES + * + * NOTES: + * 1. IRAM0/DRAM0 split-lines must be aligned to 512B boundaries (PMS module restriction) + * 2. split address must fall into appropriate IRAM0/DRAM0 region + */ +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg) { uint32_t addr = (uint32_t)line_addr; - HAL_ASSERT(addr >= IRAM0_SRAM_LEVEL_1_LOW && addr <= IRAM0_SRAM_LEVEL_3_HIGH); + + if (addr < IRAM0_SRAM_LEVEL_1_LOW || addr > IRAM0_SRAM_LEVEL_3_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE; + } + + if (addr % 0x200 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t category[3] = {0}; if (addr <= IRAM0_SRAM_LEVEL_1_HIGH) { @@ -141,47 +91,61 @@ static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32 (category[2] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2_S); uint32_t conf_addr = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V) << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S; - uint32_t reg_cfg = conf_addr | category_bits; REG_WRITE(sensitive_reg, reg_cfg); + + return MEMP_LL_OK; } /* can be both IRAM0/DRAM0 address */ -static inline void memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr) +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr) { - memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG); + return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG); } -static inline void memprot_ll_set_iram0_split_line_I_0(const void *line_addr) +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_0(const void *line_addr) { - memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG); + return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG); } -static inline void memprot_ll_set_iram0_split_line_I_1(const void *line_addr) +static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_1(const void *line_addr) { - memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG); + return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG); } -static inline void* memprot_ll_get_iram0_split_line_main_I_D(void) +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) & 0x3F; +} + +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) & 0x3F; +} + +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) & 0x3F; +} + +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) +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) +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) @@ -198,14 +162,14 @@ static inline bool memprot_ll_iram0_get_pms_lock(void) static inline uint32_t memprot_ll_iram0_set_permissions(bool r, bool w, bool x) { uint32_t permissions = 0; - if ( r ) { - permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R; + if (r) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R; } - if ( w ) { - permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W; + if (w) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W; } - if ( x ) { - permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F; + if (x) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F; } return permissions; @@ -233,39 +197,38 @@ static inline void memprot_ll_iram0_set_pms_area_3(bool r, bool w, bool x) static inline void memprot_ll_iram0_get_permissions(uint32_t perms, bool *r, bool *w, bool *x) { - *r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R; - *w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W; - *x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F; + *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); + 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); + 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); + 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); + memprot_ll_iram0_get_permissions(permissions, r, w, x); } /////////////////////////////////// // IRAM0 - MONITOR -/////////////////////////////////// // lock static inline void memprot_ll_iram0_set_monitor_lock(void) @@ -281,26 +244,31 @@ static inline bool memprot_ll_iram0_get_monitor_lock(void) // interrupt enable/clear static inline void memprot_ll_iram0_set_monitor_en(bool enable) { - if ( enable ) { - REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN ); + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN); } else { - REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN ); + REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN); } } +static inline bool memprot_ll_iram0_get_monitor_intrclr(void) +{ + return REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0; +} + static inline bool memprot_ll_iram0_get_monitor_en(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN ) == 1; + return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN) == 1; } -static inline void memprot_ll_iram0_clear_monitor_intr(void) +static inline void memprot_ll_iram0_set_monitor_intrclr(void) { - REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR ); + REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR); } -static inline void memprot_ll_iram0_reset_clear_monitor_intr(void) +static inline void memprot_ll_iram0_reset_monitor_intrclr(void) { - REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR ); + REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR); } static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void) @@ -308,31 +276,31 @@ static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void) return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG); } -// // permission violation status +// permission violation status static inline uint32_t memprot_ll_iram0_get_monitor_status_intr(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR ); + return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR); } static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_wr(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR ); + return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR); } static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_loadstore(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE ); + return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE); } static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_world(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD ); + return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD); } -static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_addr(void) +static inline intptr_t memprot_ll_iram0_get_monitor_status_fault_addr(void) { - uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR ); - return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0; + uint32_t addr = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR); + return (intptr_t)(addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0); } static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void) @@ -342,43 +310,309 @@ static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void) /* ****************************************************************************************************** - * *** DRAM0 *** + * *** RTC_FAST *** */ -//cache not available from DRAM (!) -#define DRAM0_SRAM_LEVEL_0_LOW DRAM_SRAM_START //0x3FC7C000 -#define DRAM0_SRAM_LEVEL_0_HIGH (DRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x3FC7FFFF +static inline uint32_t memprot_ll_rtcfast_get_intr_source_num(void) +{ + return ETS_CORE0_PIF_PMS_INTR_SOURCE; +} -//128kB -#define DRAM0_SRAM_LEVEL_1_LOW (DRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x3FC80000 -#define DRAM0_SRAM_LEVEL_1_HIGH (DRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FC9FFFF +//shared PIF PMS lock +//!!!: use after ALL the constraints have been set +static inline void memprot_ll_set_pif_constraint_lock(void) +{ + REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG, 1); +} -//128kB -#define DRAM0_SRAM_LEVEL_2_LOW (DRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x3FCA0000 -#define DRAM0_SRAM_LEVEL_2_HIGH (DRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCBFFFF +static inline bool memprot_ll_get_pif_constraint_lock(void) +{ + return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG) == 1; +} -//128kB -#define DRAM0_SRAM_LEVEL_3_LOW (DRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x3FCC0000 -#define DRAM0_SRAM_LEVEL_3_HIGH (DRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCDFFFF +static inline uint32_t memprot_ll_rtcfast_get_splitaddr_register(void) +{ + return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG); +} -#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W 0x2 -#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R 0x1 +/* ******************************** + * IRAM0 RTCFAST - SPLIT LINES + * + * NOTES: + * 1. there is only 1 split line for RTCFAST/WORLD + * 2. RTCFAST split-line must be aligned to 4B boundaries (PMS stores 11 bits of 13-bit offset in 8kB RTCFAST region) + * 3. RTCFAST has weird section structure (text -> dummy (!) -> force -> data) - .dummy section seems to have wrong mapping (it doesn't fall inline with .rtctext) + */ +static inline memprot_ll_err_t memprot_ll_set_rtcfast_split_line(const void *line_addr, memprot_ll_world_t world) +{ + uint32_t addr = (uint32_t)line_addr; + uint32_t mask; + 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; + } + + switch (world) { + case MEMP_LL_WORLD_0: + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M; + break; + case MEMP_LL_WORLD_1: + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M; + break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + //offset bits to store are the same width for both worlds -> using SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V + CLEAR_PERI_REG_MASK(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG, mask); + REG_SET_BITS(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG, mask, (addr >> 2) & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V); + + return MEMP_LL_OK; +} + +static inline memprot_ll_err_t memprot_ll_get_rtcfast_split_line(memprot_ll_world_t world, void **line_addr) +{ + uint32_t reg_addr = REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG); + uint32_t mask = 0; + uint32_t shift = 0; + + switch (world) { + case MEMP_LL_WORLD_0: + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M; + shift = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_S; + break; + case MEMP_LL_WORLD_1: + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M; + shift = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_S; + break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + *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(bool r, bool w, bool x) +{ + uint32_t permissions = 0; + if (r) { + permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R; + } + if (w) { + permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W; + } + if (x) { + permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F; + } + + return permissions; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_set_pms_area(bool r, bool w, bool x, memprot_ll_world_t world, memprot_ll_area_t area) +{ + uint32_t bits = 0; + uint32_t mask = 0; + + switch (world) { + case MEMP_LL_WORLD_0: { + switch (area) { + case MEMP_LL_AREA_LOW: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_S; + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_M; + break; + case MEMP_LL_AREA_HIGH: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_S; + mask = SENSITIVE_CORE_0_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) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_S; + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_M; + break; + case MEMP_LL_AREA_HIGH: + bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_S; + mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_M; + break; + default: + return MEMP_LL_ERR_AREA_INVALID; + } + } break; + default: + return MEMP_LL_ERR_WORLD_INVALID; + } + + CLEAR_PERI_REG_MASK(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, mask); + REG_SET_BITS(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, bits, mask); + + return MEMP_LL_OK; +} + +static inline void memprot_ll_rtcfast_get_permissions(uint32_t perms, bool *r, bool *w, bool *x) +{ + *r = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R; + *w = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W; + *x = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F; +} + +static inline memprot_ll_err_t memprot_ll_rtcfast_get_pms_area(bool *r, bool *w, bool *x, memprot_ll_world_t world, memprot_ll_area_t area) +{ + uint32_t permissions = 0; + + switch (world) { + case MEMP_LL_WORLD_0: { + switch (area) { + case MEMP_LL_AREA_LOW: + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L); + break; + case MEMP_LL_AREA_HIGH: + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_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: + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L); + break; + case MEMP_LL_AREA_HIGH: + permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_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 uint32_t memprot_ll_rtcfast_get_permission_register(void) +{ + return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG); +} + +/////////////////////////////////// +// RTC_FAST - MONITOR + +// lock +static inline void memprot_ll_rtcfast_set_monitor_lock(void) +{ + REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG, 1); +} + +static inline bool memprot_ll_rtcfast_get_monitor_lock(void) +{ + return REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG) == 1; +} + +// interrupt enable/clear +static inline void memprot_ll_rtcfast_set_monitor_en(bool enable) +{ + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN); + } else { + REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN); + } +} + +static inline bool memprot_ll_rtcfast_get_monitor_en(void) +{ + return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN) > 0; +} + +static inline bool memprot_ll_rtcfast_get_monitor_intrclr(void) +{ + return REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR) > 0; +} + +static inline void memprot_ll_rtcfast_set_monitor_intrclr(void) +{ + REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR); +} + +static inline void memprot_ll_rtcfast_reset_monitor_intrclr(void) +{ + REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR); +} + +static inline uint32_t memprot_ll_rtcfast_get_monitor_register(void) +{ + return REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG); +} + +// permission violation status +static inline uint32_t memprot_ll_rtcfast_get_monitor_status_intr(void) +{ + return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR); +} + +static inline intptr_t memprot_ll_rtcfast_get_monitor_status_fault_addr(void) +{ + //full address SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HADDR + return (intptr_t)REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_3_REG); +} + +static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_world(void) +{ + return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD); +} + +static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_loadstore(void) +{ + return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0); +} + +static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_wr(void) +{ + return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE); +} + + +/* ****************************************************************************************************** + * *** DRAM0 *** + * ******************************************************************************************************/ static inline uint32_t memprot_ll_dram0_get_intr_source_num(void) { return ETS_CORE0_DRAM0_PMS_INTR_SOURCE; } - /////////////////////////////////// // DRAM0 - SPLIT LINES -/////////////////////////////////// -static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg) +static inline memprot_ll_err_t memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg) { uint32_t addr = (uint32_t)line_addr; - HAL_ASSERT(addr >= DRAM0_SRAM_LEVEL_1_LOW && addr <= DRAM0_SRAM_LEVEL_3_HIGH); + + //sanity check: split address required above unified mgmt region & 32bit aligned + if (addr < DRAM0_SRAM_LEVEL_1_LOW || addr > DRAM0_SRAM_LEVEL_3_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE; + } + //split-line must be divisible by 512 (PMS module restriction) + if (addr % 0x200 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t category[3] = {0}; if (addr <= DRAM0_SRAM_LEVEL_1_HIGH) { @@ -398,36 +632,45 @@ static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32 (category[2] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2_S); uint32_t conf_addr = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V) << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S; - uint32_t reg_cfg = conf_addr | category_bits; REG_WRITE(sensitive_reg, reg_cfg); + + return MEMP_LL_OK; } -static inline void memprot_ll_set_dram0_split_line_D_0(const void *line_addr) +static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_0(const void *line_addr) { - memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG); + return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG); } -static inline void memprot_ll_set_dram0_split_line_D_1(const void *line_addr) +static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_1(const void *line_addr) { - memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG); + 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) +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) +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) & 0x3F; +} + +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) & 0x3F; +} /////////////////////////////////// // DRAM0 - PMS CONFIGURATION -/////////////////////////////////// // lock static inline void memprot_ll_dram0_set_pms_lock(void) @@ -444,11 +687,11 @@ static inline bool memprot_ll_dram0_get_pms_lock(void) static inline uint32_t memprot_ll_dram0_set_permissions(bool r, bool w) { uint32_t permissions = 0; - if ( r ) { - permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R; + if (r) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R; } - if ( w ) { - permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W; + if (w) { + permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W; } return permissions; @@ -476,37 +719,36 @@ static inline void memprot_ll_dram0_set_pms_area_3(bool r, bool w) static inline void memprot_ll_dram0_get_permissions(uint32_t perms, bool *r, bool *w ) { - *r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R; - *w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_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); + 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); + 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); + 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); + memprot_ll_dram0_get_permissions(permissions, r, w); } /////////////////////////////////// // DRAM0 - MONITOR -/////////////////////////////////// // lock static inline void memprot_ll_dram0_set_monitor_lock(void) @@ -522,26 +764,31 @@ static inline bool memprot_ll_dram0_get_monitor_lock(void) // interrupt enable/clear static inline void memprot_ll_dram0_set_monitor_en(bool enable) { - if ( enable ) { - REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN ); + if (enable) { + REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN); } else { - REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN ); + REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN); } } static inline bool memprot_ll_dram0_get_monitor_en(void) { - return REG_GET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN ) == 1; + return REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0; } -static inline void memprot_ll_dram0_clear_monitor_intr(void) +static inline void memprot_ll_dram0_set_monitor_intrclr(void) { - REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR ); + REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR); } -static inline void memprot_ll_dram0_reset_clear_monitor_intr(void) +static inline void memprot_ll_dram0_reset_monitor_intrclr(void) { - REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR ); + REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR); +} + +static inline bool memprot_ll_dram0_get_monitor_intrclr(void) +{ + return REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0; } static inline uint32_t memprot_ll_dram0_get_monitor_enable_register(void) @@ -552,33 +799,33 @@ static inline uint32_t memprot_ll_dram0_get_monitor_enable_register(void) // permission violation status static inline uint32_t memprot_ll_dram0_get_monitor_status_intr(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR ); + return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR); } static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_lock(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK ); + return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK); } static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_world(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD ); + return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD); } static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_addr(void) { - uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR ); + uint32_t addr = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR); return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + DRAM0_ADDRESS_LOW : 0; } static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_wr(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR ); + return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR); } static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_byte_en(void) { - return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN ); + return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN); } static inline uint32_t memprot_ll_dram0_get_monitor_status_register_1(void) diff --git a/components/hal/include/hal/memprot_types.h b/components/hal/include/hal/memprot_types.h index 42231f43ea..15e3c3959a 100644 --- a/components/hal/include/hal/memprot_types.h +++ b/components/hal/include/hal/memprot_types.h @@ -1,16 +1,8 @@ -// Copyright 2015-2021 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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -25,11 +17,34 @@ extern "C" { typedef enum { MEMP_LL_OK = 0, MEMP_LL_FAIL = 1, - MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2, + 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_UNI_BLOCK_INVALID = 4, + MEMP_LL_ERR_AREA_INVALID = 5, + MEMP_LL_ERR_WORLD_INVALID = 6 } memprot_ll_err_t; +/** + * @brief Memprot LL PMS World IDs + * + */ +typedef enum { + MEMP_LL_WORLD_NONE = 0x00, + MEMP_LL_WORLD_0 = 0x01, + MEMP_LL_WORLD_1 = 0x10 +} memprot_ll_world_t; + +/** + * @brief Memprot LL PMS Area IDs + * + */ +typedef enum { + MEMP_LL_AREA_NONE = 0, + MEMP_LL_AREA_LOW = 1, + MEMP_LL_AREA_HIGH = 2 +} memprot_ll_area_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c3/include/soc/memprot_defs.h b/components/soc/esp32c3/include/soc/memprot_defs.h new file mode 100644 index 0000000000..b08e1f83b4 --- /dev/null +++ b/components/soc/esp32c3/include/soc/memprot_defs.h @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc.h" +#include "soc/sensitive_reg.h" +#include "esp32c3/rom/cache.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { + struct { + uint32_t cat0 : 2; + uint32_t cat1 : 2; + uint32_t cat2 : 2; + uint32_t res0 : 8; + uint32_t splitaddr : 8; + uint32_t res1 : 10; + }; + uint32_t val; +} constrain_reg_fields_t; + +#ifndef I_D_SRAM_SEGMENT_SIZE +#define I_D_SRAM_SEGMENT_SIZE 0x20000 +#endif + +#define I_D_SPLIT_LINE_SHIFT 0x9 +#define I_D_FAULT_ADDR_SHIFT 0x2 + +#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) +#define IRAM0_SRAM_LEVEL_0_LOW SOC_IRAM_LOW //0x40370000 +#define IRAM0_SRAM_LEVEL_0_HIGH (IRAM0_SRAM_LEVEL_0_LOW + CACHE_MEMORY_IBANK_SIZE - 0x1) //0x4037FFFF + +//128kB (LEVEL 1) +#define IRAM0_SRAM_LEVEL_1_LOW (IRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x40380000 +#define IRAM0_SRAM_LEVEL_1_HIGH (IRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x4039FFFF + +//128kB (LEVEL 2) +#define IRAM0_SRAM_LEVEL_2_LOW (IRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x403A0000 +#define IRAM0_SRAM_LEVEL_2_HIGH (IRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403BFFFF + +//128kB (LEVEL 3) +#define IRAM0_SRAM_LEVEL_3_LOW (IRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x403C0000 +#define IRAM0_SRAM_LEVEL_3_HIGH (IRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403DFFFF + +//permission bits +#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 + +//16kB ICACHE not available from DRAM0 + +//128kB (LEVEL 1) +#define DRAM0_SRAM_LEVEL_1_LOW SOC_DRAM_LOW //0x3FC80000 +#define DRAM0_SRAM_LEVEL_1_HIGH (DRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FC9FFFF + +//128kB (LEVEL 2) +#define DRAM0_SRAM_LEVEL_2_LOW (DRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x3FCA0000 +#define DRAM0_SRAM_LEVEL_2_HIGH (DRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCBFFFF + +//128kB (LEVEL 3) +#define DRAM0_SRAM_LEVEL_3_LOW (DRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x3FCC0000 +#define DRAM0_SRAM_LEVEL_3_HIGH (DRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCDFFFF + +#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 + +//permission bits +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W 0x1 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R 0x2 +#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F 0x4 + +#define AREA_LOW 0 +#define AREA_HIGH 1 + +#ifdef __cplusplus +} +#endif diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index d9569ff6b5..5247188171 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -457,7 +457,6 @@ components/esp_common/include/esp_assert.h components/esp_common/include/esp_bit_defs.h components/esp_common/include/esp_check.h components/esp_common/include/esp_compiler.h -components/esp_common/include/esp_err.h components/esp_common/include/esp_types.h components/esp_common/src/esp_err_to_name.c components/esp_common/test/test_attr.c @@ -1018,7 +1017,6 @@ components/hal/esp32c3/include/hal/hmac_hal.h components/hal/esp32c3/include/hal/hmac_ll.h components/hal/esp32c3/include/hal/i2c_ll.h components/hal/esp32c3/include/hal/interrupt_controller_ll.h -components/hal/esp32c3/include/hal/memprot_ll.h components/hal/esp32c3/include/hal/mpu_ll.h components/hal/esp32c3/include/hal/rtc_cntl_ll.h components/hal/esp32c3/include/hal/rwdt_ll.h @@ -1143,7 +1141,6 @@ components/hal/include/hal/interrupt_controller_types.h components/hal/include/hal/ledc_hal.h components/hal/include/hal/mcpwm_hal.h components/hal/include/hal/mcpwm_types.h -components/hal/include/hal/memprot_types.h components/hal/include/hal/mpu_hal.h components/hal/include/hal/mpu_types.h components/hal/include/hal/pcnt_hal.h @@ -3233,7 +3230,6 @@ tools/test_apps/system/gdb_loadable_elf/main/hello_world_main.c tools/test_apps/system/longjmp_test/app_test.py tools/test_apps/system/longjmp_test/main/hello_world_main.c tools/test_apps/system/memprot/app_test.py -tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c tools/test_apps/system/memprot/main/esp32c3/test_panic.c tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c tools/test_apps/system/memprot/main/esp32s2/test_panic.c diff --git a/tools/test_apps/system/memprot/README.md b/tools/test_apps/system/memprot/README.md index 98655f12ea..735329420b 100644 --- a/tools/test_apps/system/memprot/README.md +++ b/tools/test_apps/system/memprot/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-S2 | ESP32-C3 | +| Supported Targets | ESP32-C3 | ESP32-S2 | | ----------------- | -------- | -------- | diff --git a/tools/test_apps/system/memprot/app_test.py b/tools/test_apps/system/memprot/app_test.py index 9a4e3fd3e2..1530dc4219 100644 --- a/tools/test_apps/system/memprot/app_test.py +++ b/tools/test_apps/system/memprot/app_test.py @@ -15,7 +15,8 @@ MEM_TEST_S2 = [ MEM_TEST_C3 = [ ['IRAM0_SRAM', 'WRX'], - ['DRAM0_SRAM', 'WR'] + ['DRAM0_SRAM', 'WR'], + ['IRAM0_RTCFAST', 'WRX'], ] diff --git a/tools/test_apps/system/memprot/main/Kconfig.projbuild b/tools/test_apps/system/memprot/main/Kconfig.projbuild index e12919cc1e..3daabe92f6 100644 --- a/tools/test_apps/system/memprot/main/Kconfig.projbuild +++ b/tools/test_apps/system/memprot/main/Kconfig.projbuild @@ -1,4 +1,3 @@ -config ESP_SYSTEM_MEMPROT_IRAM_TESTBUF +config ESP_SYSTEM_MEMPROT_TEST bool - default y if IDF_TARGET_ESP32C3 - default n if !IDF_TARGET_ESP32C3 + default y 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 817e13680a..ab05cfedc7 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,9 +1,17 @@ -/* MEMPROT (PMS) testing code */ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include -#include "sdkconfig.h" -#include "esp32c3/memprot.h" -#include "esp_rom_sys.h" #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" /** * ESP32C3 MEMORY PROTECTION MODULE TEST @@ -11,11 +19,13 @@ * * In order to safely test all the memprot features, this test application uses memprot default settings * plus proprietary testing buffers: - * - iram_test_buffer (.iram_end_test, 1kB) - all low region operations - * - dram_test_buffer (.dram0.data, 1kB) - all high region operations + * - 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 = iram_test_buffer + 0x200 - * - test_ptr_high = dram_test_buffer + 0x200 + * - 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) @@ -28,19 +38,31 @@ * | DRam0_PMS_0 | * | | * | | - * | - - - - - - - iram_test_buffer - - - - - - -| IRam0_line1_Split_addr + * | - - - - - - - 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 | | = - * | - - - - - - - dram_test_buffer - - - - - - -| IRam0_DRam0_Split_addr (main I/D) + * | - - - - - - - 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) + * | | * ----------------------------------------------- - * - * For more details on PMS memprot settings see 'esp_memprot_set_prot_int' function in esp32c3/memprot.h */ @@ -48,345 +70,519 @@ slli a0,a0,0x1 ret */ -static uint8_t fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 }; +static uint8_t s_fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 }; typedef int (*fnc_ptr)(int); #define SRAM_TEST_BUFFER_SIZE 0x400 #define SRAM_TEST_OFFSET 0x200 -static uint8_t __attribute__((section(".iram_end_test"))) iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0}; -static uint8_t dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0}; +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}; extern volatile bool g_override_illegal_instruction; - -static void *test_memprot_addr_low(mem_type_prot_t mem_type) +static void *test_mprot_addr_low(esp_mprot_mem_t mem_type) { - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return (void*)((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET); - case MEMPROT_DRAM0_SRAM: - return (void*)MAP_IRAM_TO_DRAM((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET); - default: - abort(); + 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_memprot_addr_high(mem_type_prot_t mem_type) +static void *test_mprot_addr_high(esp_mprot_mem_t mem_type) { - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - return (void*)MAP_DRAM_TO_IRAM((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET); - case MEMPROT_DRAM0_SRAM: - return (void*)((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET); - default: - abort(); + 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)) dump_status_register(mem_type_prot_t mem_type) +static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_mem_t mem_type) { - char operation = 0; + esp_rom_printf("FAULT ["); - // IRAM fault: check instruction-fetch flag - if ( mem_type == MEMPROT_IRAM0_SRAM ) { - if ( esp_memprot_get_violate_loadstore(mem_type) ) { - operation = 'X'; - } + void *addr; + esp_err_t err = esp_mprot_get_violate_addr(mem_type, &addr, NULL); + 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)); } - // W/R - common - if ( operation == 0 ) { - operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R'; + esp_mprot_pms_world_t world; + err = esp_mprot_get_violate_world(mem_type, &world, NULL); + 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)); } - esp_rom_printf( - " FAULT [ world: %u, fault addr: 0x%08X, operation: %c", - esp_memprot_get_violate_world(mem_type), - esp_memprot_get_violate_addr(mem_type), - operation - ); + uint32_t oper; + err = esp_mprot_get_violate_operation(mem_type, &oper, NULL); + 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_DRAM0_SRAM ) { - esp_rom_printf( ", byte en: 0x%08X", esp_memprot_get_violate_byte_en(mem_type) ); + if (mem_type == MEMPROT_TYPE_DRAM0_SRAM) { + uint32_t byteen; + err = esp_mprot_get_violate_byte_enables(mem_type, &byteen, NULL); + 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" ); + esp_rom_printf( "]\n" ); } -static void check_test_result(mem_type_prot_t mem_type, bool expected_status) +static void test_mprot_check_test_result(esp_mprot_mem_t mem_type, bool expected_status) { - bool test_result = - expected_status ? - !esp_memprot_get_violate_intr_on(mem_type) : - esp_memprot_get_violate_intr_on(mem_type); + 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; + } - if ( test_result ) { + 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 { - dump_status_register(mem_type); + test_mprot_dump_status_register(mem_type); } } -static void test_memprot_get_permissions(bool low, mem_type_prot_t mem_type, bool *read, bool *write, bool *exec ) +static void test_mprot_clear_all_interrupts(void) { - bool _r, _w, _x; - pms_area_t area = MEMPROT_PMS_AREA_NONE; + esp_err_t err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL); + 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); + 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); + 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)); + } +} - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: - area = low ? MEMPROT_IRAM0_PMS_AREA_2 : MEMPROT_IRAM0_PMS_AREA_3; - esp_memprot_iram_get_pms_area(area, &_r, &_w, &_x); +static void test_mprot_get_permissions(bool low, esp_mprot_mem_t mem_type, bool *read, bool *write, bool *exec ) +{ + 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_DRAM0_SRAM: - area = low ? MEMPROT_DRAM0_PMS_AREA_0 : MEMPROT_DRAM0_PMS_AREA_1; - esp_memprot_dram_get_pms_area(area, &_r, &_w); + 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(); } - if ( read ) { - *read = _r; + uint32_t flags; + esp_err_t err = esp_mprot_get_pms_area(area, &flags); + 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 ( write ) { - *write = _w; + + if (read) { + *read = flags & MEMPROT_OP_READ; } - if ( exec ) { - *exec = _x; + if (write) { + *write = flags & MEMPROT_OP_WRITE; + } + if (exec) { + *exec = flags & MEMPROT_OP_EXEC; } } -static void test_memprot_set_permissions(bool low, mem_type_prot_t mem_type, bool read, bool write, bool *exec) +static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool read, bool write, bool *exec) { - switch ( mem_type ) { - case MEMPROT_IRAM0_SRAM: { - bool _ex; - if (!exec) { - test_memprot_get_permissions( low, mem_type, NULL, NULL, &_ex); - exec = &_ex; - } + 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) { - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, read, write, *exec); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, read, write, *exec); - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, read, write, *exec); + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, flags)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, flags)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, flags)) != ESP_OK) { + break; + } } else { - esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, read, write, *exec); + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, flags)) != ESP_OK) { + break; + } } } break; - case MEMPROT_DRAM0_SRAM: { + case MEMPROT_TYPE_DRAM0_SRAM: { if (low) { - esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, read, write ); + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, flags)) != ESP_OK) { + break; + } } else { - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, read, write); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, read, write); - esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, read, write); + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, flags)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, flags)) != ESP_OK) { + break; + } + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, flags)) != 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)) != ESP_OK) { + break; + } + } else { + if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, flags)) != 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_memprot_read(mem_type_prot_t mem_type) +static void test_mprot_read(esp_mprot_mem_t mem_type) { - //get current READ & WRITE permission settings + test_mprot_clear_all_interrupts(); + + //get current permission settings bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high; - test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL); - test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL); + 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); + test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL); //get testing pointers for low & high regions - volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type); - volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type); + 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 = 100; //temporarily allow WRITE for setting the test values - esp_memprot_set_monitor_en(mem_type, false); - test_memprot_set_permissions(true, mem_type, read_perm_low, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL); - test_memprot_set_permissions(false, mem_type, read_perm_high, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL); + esp_err_t err = esp_mprot_set_monitor_en(mem_type, false); + 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(true, mem_type, read_perm_low, true, is_exec_mem ? &exec_perm_low : NULL); + test_mprot_set_permissions(false, mem_type, read_perm_high, true, is_exec_mem ? &exec_perm_high : NULL); + + //save testing values *ptr_low = test_val; *ptr_high = test_val + 1; - test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL); - test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL); - esp_memprot_set_monitor_en(mem_type, true); + //restore current PMS settings + 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); + + //reenable monitoring + err = esp_mprot_set_monitor_en(mem_type, true); + 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 read low: ", esp_memprot_mem_type_to_str(mem_type)); - esp_memprot_monitor_clear_intr(mem_type); + esp_rom_printf("%s read low: ", esp_mprot_mem_type_to_str(mem_type)); + err = esp_mprot_monitor_clear_intr(mem_type, NULL); + 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 ) { + if (read_perm_low && val != test_val) { esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val ); - dump_status_register(mem_type); + test_mprot_dump_status_register(mem_type); } else { - check_test_result(mem_type, read_perm_low); + test_mprot_check_test_result(mem_type, read_perm_low); } //perform READ in high region - esp_rom_printf("%s read high: ", esp_memprot_mem_type_to_str(mem_type)); - esp_memprot_monitor_clear_intr(mem_type); + esp_rom_printf("%s read high: ", esp_mprot_mem_type_to_str(mem_type)); + err = esp_mprot_monitor_clear_intr(mem_type, NULL); + 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; + } val = *ptr_high; - if ( read_perm_high && val != (test_val + 1) ) { + if (read_perm_high && val != (test_val + 1)) { esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val); - dump_status_register(mem_type); + test_mprot_dump_status_register(mem_type); } else { - check_test_result(mem_type, read_perm_high); + test_mprot_check_test_result(mem_type, read_perm_high); } } -static void test_memprot_write(mem_type_prot_t mem_type) +static void test_mprot_write(esp_mprot_mem_t mem_type) { + test_mprot_clear_all_interrupts(); + //get current READ & WRITE permission settings - bool write_perm_low, write_perm_high, read_perm_low, read_perm_high; - test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, NULL); - test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, NULL); + 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); + test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL); //ensure READ enabled - esp_memprot_set_monitor_en(mem_type, false); - test_memprot_set_permissions(true, mem_type, true, write_perm_low, NULL); - test_memprot_set_permissions(false, mem_type, true, write_perm_high, NULL); - esp_memprot_set_monitor_en(mem_type, true); + esp_err_t err = esp_mprot_set_monitor_en(mem_type, false); + 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; + } - //get testing pointers for low & high regions - volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type); - volatile uint32_t *ptr_high = test_memprot_addr_high(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); + 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 write low: ", esp_memprot_mem_type_to_str(mem_type)); - esp_memprot_monitor_clear_intr(mem_type); + esp_rom_printf("%s write low: ", esp_mprot_mem_type_to_str(mem_type)); + err = esp_mprot_monitor_clear_intr(mem_type, NULL); + 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; + } volatile uint32_t val = 0; *ptr_low = test_val; val = *ptr_low; - if ( val != test_val && write_perm_low ) { + if (val != test_val && write_perm_low) { esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val); - dump_status_register(mem_type); + test_mprot_dump_status_register(mem_type); } else { - check_test_result(mem_type, write_perm_low); + test_mprot_check_test_result(mem_type, write_perm_low); } //perform WRITE in high region - esp_rom_printf("%s write high: ", esp_memprot_mem_type_to_str(mem_type)); - esp_memprot_monitor_clear_intr(mem_type); + esp_rom_printf("%s write high: ", esp_mprot_mem_type_to_str(mem_type)); + err = esp_mprot_monitor_clear_intr(mem_type, NULL); + 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; + } val = 0; *ptr_high = test_val + 1; val = *ptr_high; - if ( val != (test_val + 1) && write_perm_high ) { + if (val != (test_val + 1) && write_perm_high) { esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val); - dump_status_register(mem_type); + test_mprot_dump_status_register(mem_type); } else { - check_test_result(mem_type, write_perm_high); + test_mprot_check_test_result(mem_type, write_perm_high); } //restore original permissions - esp_memprot_set_monitor_en(mem_type, false); - test_memprot_set_permissions(true, mem_type, true, read_perm_low, NULL); - test_memprot_set_permissions(false, mem_type, true, read_perm_high, NULL); - esp_memprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, false); + 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(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); + 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; + } } -static void test_memprot_exec(mem_type_prot_t mem_type) +static void test_mprot_exec(esp_mprot_mem_t mem_type) { - if ( mem_type != MEMPROT_IRAM0_SRAM ) { + if (!(mem_type & MEMPROT_TYPE_IRAM0_ANY)) { esp_rom_printf("Error: EXEC test available only for IRAM access.\n" ); return; } + test_mprot_clear_all_interrupts(); + bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high; //temporarily enable READ/WRITE - test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low); - test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high); - esp_memprot_set_monitor_en(mem_type, false); - test_memprot_set_permissions(true, mem_type, true, true, &exec_perm_low); - test_memprot_set_permissions(false, mem_type, true, true, &exec_perm_high); - esp_memprot_set_monitor_en(mem_type, true); + 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); + 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); + 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 testing pointers for low & high regions, zero 8B slot - void *fnc_ptr_low = test_memprot_addr_low(mem_type); - void *fnc_ptr_high = test_memprot_addr_high(mem_type); - memset( fnc_ptr_low, 0, 8); - memset( fnc_ptr_high, 0, 8); + void *fnc_ptr_low = test_mprot_addr_low(mem_type); + void *fnc_ptr_high = test_mprot_addr_high(mem_type); + memset(fnc_ptr_low, 0, 8); + memset(fnc_ptr_high, 0, 8); //inject the code to both low & high segments - memcpy( (void *)fnc_ptr_low, (const void *)fnc_buff, sizeof(fnc_buff) ); - memcpy( (void *)fnc_ptr_high, (const void *)fnc_buff, sizeof(fnc_buff) ); + memcpy((void *)fnc_ptr_low, (const void *)s_fnc_buff, sizeof(s_fnc_buff)); + memcpy((void *)fnc_ptr_high, (const void *)s_fnc_buff, sizeof(s_fnc_buff)); uint32_t res = 0; //LOW REGION: clear the intr flag & try to execute the code injected - esp_rom_printf("%s exec low: ", esp_memprot_mem_type_to_str(mem_type)); - esp_memprot_monitor_clear_intr(mem_type); + esp_rom_printf("%s exec low: ", esp_mprot_mem_type_to_str(mem_type)); + err = esp_mprot_monitor_clear_intr(mem_type, NULL); + 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_ptr fnc = (fnc_ptr)fnc_ptr_low; g_override_illegal_instruction = true; - res = fnc( 5 ); + res = fnc(5); g_override_illegal_instruction = false; //check results bool fnc_call_ok = res == 10; - if ( fnc_call_ok ) { - check_test_result(mem_type, exec_perm_low); + if (fnc_call_ok) { + test_mprot_check_test_result(mem_type, exec_perm_low); } else { - if ( !exec_perm_low ) { - check_test_result(mem_type, false); + 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 exec high: ", esp_memprot_mem_type_to_str(mem_type)); - esp_memprot_monitor_clear_intr(mem_type); + esp_rom_printf("%s exec high: ", esp_mprot_mem_type_to_str(mem_type)); + err = esp_mprot_monitor_clear_intr(mem_type, NULL); + 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; - res = fnc( 6 ); + res = fnc(6); g_override_illegal_instruction = false; fnc_call_ok = res == 12; - if ( fnc_call_ok ) { - check_test_result(mem_type, exec_perm_high); + if (fnc_call_ok) { + test_mprot_check_test_result(mem_type, exec_perm_high); } else { - if ( !exec_perm_high ) { - check_test_result(mem_type, false); + if (!exec_perm_high) { + test_mprot_check_test_result(mem_type, false); } else { esp_rom_printf(" FAULT [injected code not executed]\n"); } } //restore original permissions - esp_memprot_set_monitor_en(mem_type, false); - test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low); - test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high); - esp_memprot_set_monitor_en(mem_type, true); + err = esp_mprot_set_monitor_en(mem_type, false); + 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); + 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; + } } - /* ******************************************************************************************** * main test runner */ void app_main(void) { - esp_memprot_set_prot_int(false, false, NULL, NULL); + esp_memp_config_t memp_cfg = ESP_MEMPROT_DEFAULT_CONFIG(); + memp_cfg.invoke_panic_handler = false; + memp_cfg.lock_feature = false; - test_memprot_read(MEMPROT_IRAM0_SRAM); - test_memprot_write(MEMPROT_IRAM0_SRAM); - test_memprot_exec(MEMPROT_IRAM0_SRAM); + 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_memprot_read(MEMPROT_DRAM0_SRAM); - test_memprot_write(MEMPROT_DRAM0_SRAM); + test_mprot_read(MEMPROT_TYPE_IRAM0_SRAM); + test_mprot_write(MEMPROT_TYPE_IRAM0_SRAM); + test_mprot_exec(MEMPROT_TYPE_IRAM0_SRAM); + + test_mprot_read(MEMPROT_TYPE_DRAM0_SRAM); + test_mprot_write(MEMPROT_TYPE_DRAM0_SRAM); + + test_mprot_read(MEMPROT_TYPE_IRAM0_RTCFAST); + test_mprot_write(MEMPROT_TYPE_IRAM0_RTCFAST); + test_mprot_exec(MEMPROT_TYPE_IRAM0_RTCFAST); } diff --git a/tools/test_apps/system/memprot/sdkconfig.ci b/tools/test_apps/system/memprot/sdkconfig.ci deleted file mode 100644 index d0ea27a6c6..0000000000 --- a/tools/test_apps/system/memprot/sdkconfig.ci +++ /dev/null @@ -1 +0,0 @@ -CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n diff --git a/tools/test_apps/system/memprot/sdkconfig.defaults b/tools/test_apps/system/memprot/sdkconfig.defaults new file mode 100644 index 0000000000..8f58b66a0a --- /dev/null +++ b/tools/test_apps/system/memprot/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=n +CONFIG_ESP_SYSTEM_MEMPROT_TEST=y