mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 12:14:32 +02:00
Merge branch 'feature/esp32c3_memprot_master' into 'master'
ESP32C3 memory protection See merge request espressif/esp-idf!11979
This commit is contained in:
@@ -565,7 +565,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
|||||||
ESP_LOGI(TAG, "dram: %p", data_dram);
|
ESP_LOGI(TAG, "dram: %p", data_dram);
|
||||||
ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc);
|
ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc);
|
||||||
|
|
||||||
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
uint32_t* data_iram = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_EXEC);
|
uint32_t* data_iram = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_EXEC);
|
||||||
TEST_ASSERT(data_iram != NULL);
|
TEST_ASSERT(data_iram != NULL);
|
||||||
TEST_ASSERT(esp_ptr_executable(data_iram) || esp_ptr_in_iram(data_iram) || esp_ptr_in_diram_iram(data_iram));
|
TEST_ASSERT(esp_ptr_executable(data_iram) || esp_ptr_in_iram(data_iram) || esp_ptr_in_diram_iram(data_iram));
|
||||||
@@ -574,7 +574,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
|||||||
|
|
||||||
srand(52);
|
srand(52);
|
||||||
for (int i = 0; i < 320/4; i++) {
|
for (int i = 0; i < 320/4; i++) {
|
||||||
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
data_iram[i] = rand();
|
data_iram[i] = rand();
|
||||||
#endif
|
#endif
|
||||||
data_dram[i] = rand();
|
data_dram[i] = rand();
|
||||||
@@ -601,7 +601,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
|||||||
int x;
|
int x;
|
||||||
memset(trans, 0, sizeof(trans));
|
memset(trans, 0, sizeof(trans));
|
||||||
|
|
||||||
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
trans[0].length = 320*8,
|
trans[0].length = 320*8,
|
||||||
trans[0].tx_buffer = data_iram;
|
trans[0].tx_buffer = data_iram;
|
||||||
trans[0].rx_buffer = data_malloc+1;
|
trans[0].rx_buffer = data_malloc+1;
|
||||||
@@ -627,7 +627,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
|||||||
*ptr = 0xbc124960;
|
*ptr = 0xbc124960;
|
||||||
|
|
||||||
//Queue all transactions.
|
//Queue all transactions.
|
||||||
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
for (x=0; x<TEST_REGION_SIZE; x++) {
|
for (x=0; x<TEST_REGION_SIZE; x++) {
|
||||||
#else
|
#else
|
||||||
for (x=3; x<TEST_REGION_SIZE; x++) {
|
for (x=3; x<TEST_REGION_SIZE; x++) {
|
||||||
@@ -644,7 +644,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
|||||||
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
|
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
|
||||||
TEST_ASSERT(spi_bus_free(TEST_SPI_HOST) == ESP_OK);
|
TEST_ASSERT(spi_bus_free(TEST_SPI_HOST) == ESP_OK);
|
||||||
free(data_malloc);
|
free(data_malloc);
|
||||||
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
free(data_iram);
|
free(data_iram);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ else()
|
|||||||
"esp_ds.c"
|
"esp_ds.c"
|
||||||
"esp_crypto_lock.c"
|
"esp_crypto_lock.c"
|
||||||
"hw_random.c"
|
"hw_random.c"
|
||||||
|
"memprot.c"
|
||||||
"system_api_esp32c3.c")
|
"system_api_esp32c3.c")
|
||||||
set(include_dirs "include")
|
set(include_dirs "include")
|
||||||
|
|
||||||
|
@@ -14,12 +14,12 @@
|
|||||||
|
|
||||||
|
|
||||||
/* INTERNAL API
|
/* INTERNAL API
|
||||||
* generic interface to MMU memory protection features
|
* generic interface to PMS memory protection features
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdbool.h>
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -27,329 +27,67 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MEMPROT_IRAM0 = 0x00000000,
|
MEMPROT_NONE = 0x00000000,
|
||||||
MEMPROT_DRAM0 = 0x00000001,
|
MEMPROT_IRAM0_SRAM = 0x00000001,
|
||||||
MEMPROT_UNKNOWN
|
MEMPROT_DRAM0_SRAM = 0x00000002,
|
||||||
|
MEMPROT_ALL = 0xFFFFFFFF
|
||||||
} mem_type_prot_t;
|
} mem_type_prot_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
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 {
|
||||||
* @brief Returns splitting address for required memory region
|
MEMPROT_IRAM0_PMS_AREA_0,
|
||||||
*
|
MEMPROT_IRAM0_PMS_AREA_1,
|
||||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
MEMPROT_IRAM0_PMS_AREA_2,
|
||||||
*
|
MEMPROT_IRAM0_PMS_AREA_3,
|
||||||
* @return Splitting address for the memory region required.
|
MEMPROT_DRAM0_PMS_AREA_0,
|
||||||
* The address is given by region-specific global symbol exported from linker script,
|
MEMPROT_DRAM0_PMS_AREA_1,
|
||||||
* it is not read out from related configuration register.
|
MEMPROT_DRAM0_PMS_AREA_2,
|
||||||
*/
|
MEMPROT_DRAM0_PMS_AREA_3
|
||||||
uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type);
|
} pms_area_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
const char *mem_type_to_str(mem_type_prot_t mem_type);
|
||||||
* @brief Enable/disable the memory protection interrupt
|
const char *split_line_to_str(split_line_t line_type);
|
||||||
*
|
const char *pms_to_str(pms_area_t area_type);
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
void *esp_memprot_get_main_split_addr(void);
|
||||||
* @brief Detects whether any of the memory protection interrupts is active
|
void esp_memprot_set_split_line_lock(bool lock);
|
||||||
*
|
bool esp_memprot_get_split_line_lock(void);
|
||||||
* @return true/false
|
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
|
||||||
*/
|
|
||||||
bool esp_memprot_is_assoc_intr_any(void);
|
|
||||||
|
|
||||||
/**
|
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock);
|
||||||
* @brief Detects whether specific memory protection interrupt is active
|
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
|
||||||
*
|
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
|
||||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
|
||||||
*
|
|
||||||
* @return true/false
|
|
||||||
*/
|
|
||||||
bool esp_memprot_is_assoc_intr(mem_type_prot_t mem_type);
|
|
||||||
|
|
||||||
/**
|
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock);
|
||||||
* @brief Sets a request for clearing interrupt-on flag for specified memory region (register write)
|
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
|
||||||
*
|
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
|
||||||
* @note When called without actual interrupt-on flag set, subsequent occurrence of related interrupt is ignored.
|
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
|
||||||
* @brief Detects which memory protection interrupt is active, check order: IRAM0, DRAM0
|
void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
|
||||||
*
|
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
|
||||||
* @return Memory protection area type (see mem_type_prot_t enum)
|
bool IRAM_ATTR esp_memprot_is_locked_any(void);
|
||||||
*/
|
bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
|
||||||
mem_type_prot_t IRAM_ATTR esp_memprot_get_intr_memtype(void);
|
|
||||||
|
|
||||||
/**
|
uint32_t IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
|
||||||
* @brief Gets interrupt status register contents for specified memory region
|
uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
|
||||||
*
|
uint32_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
|
||||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
uint32_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
|
||||||
*
|
uint32_t IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
|
||||||
* @return Contents of status register
|
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
|
||||||
*/
|
|
||||||
uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type);
|
|
||||||
|
|
||||||
/**
|
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
|
||||||
* @brief Get details of given interrupt status
|
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
|
||||||
*
|
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
|
||||||
* @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 interrupt permission control 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_ena_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)
|
|
||||||
*/
|
|
||||||
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get permission settings bits for IRAM split mgmt based on current split address
|
|
||||||
*
|
|
||||||
* @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 DRAM split mgmt based on current split address
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@@ -359,7 +359,8 @@ SECTIONS
|
|||||||
/* Marks the end of IRAM code segment */
|
/* Marks the end of IRAM code segment */
|
||||||
.iram0.text_end (NOLOAD) :
|
.iram0.text_end (NOLOAD) :
|
||||||
{
|
{
|
||||||
. = ALIGN (16);
|
/* C3 memprot requires 512 B alignment for split lines */
|
||||||
|
. = ALIGN (0x200);
|
||||||
_iram_text_end = ABSOLUTE(.);
|
_iram_text_end = ABSOLUTE(.);
|
||||||
} > iram0_0_seg
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
520
components/esp32c3/memprot.c
Normal file
520
components/esp32c3/memprot.c
Normal file
@@ -0,0 +1,520 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
/* INTERNAL API
|
||||||
|
* implementation of PMS memory protection features
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "soc/sensitive_reg.h"
|
||||||
|
#include "soc/dport_access.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
static const char *TAG = "memprot";
|
||||||
|
|
||||||
|
#include "esp32c3/memprot.h"
|
||||||
|
#include "hal/memprot_ll.h"
|
||||||
|
#include "riscv/interrupt.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
extern int _iram_text_end;
|
||||||
|
|
||||||
|
const char *mem_type_to_str(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch (mem_type) {
|
||||||
|
case MEMPROT_NONE:
|
||||||
|
return "MEMPROT_NONE";
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return "MEMPROT_IRAM0_SRAM";
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return "MEMPROT_DRAM0_SRAM";
|
||||||
|
case MEMPROT_ALL:
|
||||||
|
return "MEMPROT_ALL";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *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 *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_main_split_addr()
|
||||||
|
{
|
||||||
|
return &_iram_text_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_split_line_lock(bool lock)
|
||||||
|
{
|
||||||
|
memprot_ll_set_iram0_dram0_split_line_lock(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)
|
||||||
|
{
|
||||||
|
uint32_t addr = (uint32_t)line_addr;
|
||||||
|
ESP_LOGD(TAG, "Setting split line %s, addr: 0x%08X", split_line_to_str(line_type), addr);
|
||||||
|
|
||||||
|
//split-line must be divisible by 512
|
||||||
|
assert( 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_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", addr);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - get split lines
|
||||||
|
|
||||||
|
|
||||||
|
/* PMS */
|
||||||
|
|
||||||
|
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_set_pms_lock(%s, %s)", mem_type_to_str(mem_type), lock ? "true" : "false");
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_set_pms_lock(lock);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_set_pms_lock(lock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", 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_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", 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_LOGE(TAG, "Invalid area_type %d", pms_to_str(area_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", 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_LOGE(TAG, "Invalid area_type %d", pms_to_str(area_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO - get single areas */
|
||||||
|
|
||||||
|
|
||||||
|
/* monitor */
|
||||||
|
|
||||||
|
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_set_monitor_lock(%s, %s)", mem_type_to_str(mem_type), lock ? "true" : "false");
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_set_monitor_lock(lock);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_set_monitor_lock(lock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", 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_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_clear_monitor_intr();
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_clear_monitor_intr();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t 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();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_intr();
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_status_fault_world();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_fault_world();
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_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();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_fault_wr();
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t 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();
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", 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_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", 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_LOGE(TAG, "Invalid mem_type (%s), aborting", 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_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_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(true);
|
||||||
|
if (use_iram0) {
|
||||||
|
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM, true);
|
||||||
|
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM, true);
|
||||||
|
}
|
||||||
|
if (use_dram0) {
|
||||||
|
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM, true);
|
||||||
|
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -29,29 +29,6 @@ menu "ESP32S2-specific"
|
|||||||
default 160 if ESP32S2_DEFAULT_CPU_FREQ_160
|
default 160 if ESP32S2_DEFAULT_CPU_FREQ_160
|
||||||
default 240 if ESP32S2_DEFAULT_CPU_FREQ_240
|
default 240 if ESP32S2_DEFAULT_CPU_FREQ_240
|
||||||
|
|
||||||
menu "Memory protection"
|
|
||||||
|
|
||||||
config ESP32S2_MEMPROT_FEATURE
|
|
||||||
bool "Enable memory protection"
|
|
||||||
default "y"
|
|
||||||
help
|
|
||||||
If enabled, permission control module watches all memory access and fires panic handler
|
|
||||||
if permission violation is detected. This feature automatically splits
|
|
||||||
memory into data and instruction segments and sets Read/Execute permissions
|
|
||||||
for instruction part (below splitting address) and Read/Write permissions
|
|
||||||
for data part (above splitting address). The memory protection is effective
|
|
||||||
on all access through IRAM0 and DRAM0 buses.
|
|
||||||
|
|
||||||
config ESP32S2_MEMPROT_FEATURE_LOCK
|
|
||||||
depends on ESP32S2_MEMPROT_FEATURE
|
|
||||||
bool "Lock memory protection settings"
|
|
||||||
default "y"
|
|
||||||
help
|
|
||||||
Once locked, memory protection settings cannot be changed anymore.
|
|
||||||
The lock is reset only on the chip startup.
|
|
||||||
|
|
||||||
endmenu # Memory protection
|
|
||||||
|
|
||||||
menu "Cache config"
|
menu "Cache config"
|
||||||
|
|
||||||
choice ESP32S2_INSTRUCTION_CACHE_SIZE
|
choice ESP32S2_INSTRUCTION_CACHE_SIZE
|
||||||
|
@@ -98,4 +98,28 @@ menu "ESP System Settings"
|
|||||||
If enabled, the CPU will be powered down in light sleep. Enabling this option will consume
|
If enabled, the CPU will be powered down in light sleep. Enabling this option will consume
|
||||||
1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA.
|
1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA.
|
||||||
|
|
||||||
|
menu "Memory protection"
|
||||||
|
|
||||||
|
config ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
bool "Enable memory protection"
|
||||||
|
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2
|
||||||
|
default "y"
|
||||||
|
help
|
||||||
|
If enabled, the permission control module watches all the memory access and fires the panic handler
|
||||||
|
if a permission violation is detected. This feature automatically splits
|
||||||
|
the SRAM memory into data and instruction segments and sets Read/Execute permissions
|
||||||
|
for the instruction part (below given splitting address) and Read/Write permissions
|
||||||
|
for the data part (above the splitting address). The memory protection is effective
|
||||||
|
on all access through the IRAM0 and DRAM0 buses.
|
||||||
|
|
||||||
|
config ESP_SYSTEM_MEMPROT_FEATURE_LOCK
|
||||||
|
depends on ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
bool "Lock memory protection settings"
|
||||||
|
default "y"
|
||||||
|
help
|
||||||
|
Once locked, memory protection settings cannot be changed anymore.
|
||||||
|
The lock is reset only on the chip startup.
|
||||||
|
|
||||||
|
endmenu # Memory protection
|
||||||
|
|
||||||
endmenu # ESP System Settings
|
endmenu # ESP System Settings
|
||||||
|
@@ -22,6 +22,9 @@
|
|||||||
#if CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/cache_err_int.h"
|
#include "esp32c3/cache_err_int.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
#include "esp32c3/memprot.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DIM(array) (sizeof(array)/sizeof(*array))
|
#define DIM(array) (sizeof(array)/sizeof(*array))
|
||||||
@@ -145,6 +148,47 @@ static inline void print_cache_err_details(const void* frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when a memory protection error occurs (PMS). It prints details such as the
|
||||||
|
* explanation of why the panic occured.
|
||||||
|
*/
|
||||||
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
static inline void print_memprot_err_details(const void *frame)
|
||||||
|
{
|
||||||
|
//common memprot fault info
|
||||||
|
mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
|
||||||
|
panic_print_str( " memory type: ");
|
||||||
|
panic_print_str( mem_type_to_str(mem_type) );
|
||||||
|
panic_print_str( "\r\n faulting address: ");
|
||||||
|
panic_print_hex( esp_memprot_get_violate_addr(mem_type) );
|
||||||
|
panic_print_str( "\r\n world: ");
|
||||||
|
panic_print_hex( esp_memprot_get_violate_world(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) == 1 ) {
|
||||||
|
operation = 'X';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// W/R - common
|
||||||
|
if ( operation == 0 ) {
|
||||||
|
operation = esp_memprot_get_violate_wr(mem_type) == 1 ? 'W' : 'R';
|
||||||
|
}
|
||||||
|
panic_print_str( "\r\n operation type: ");
|
||||||
|
panic_print_char( operation );
|
||||||
|
|
||||||
|
// DRAM/DMA fault: check byte-enables
|
||||||
|
if ( mem_type == MEMPROT_DRAM0_SRAM ) {
|
||||||
|
panic_print_str("\r\n byte-enables: " );
|
||||||
|
panic_print_hex(esp_memprot_get_violate_byte_en(mem_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
panic_print_str("\r\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void panic_print_registers(const void *f, int core)
|
void panic_print_registers(const void *f, int core)
|
||||||
{
|
{
|
||||||
uint32_t *regs = (uint32_t *)f;
|
uint32_t *regs = (uint32_t *)f;
|
||||||
@@ -190,7 +234,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
|||||||
#if SOC_CPU_NUM > 1
|
#if SOC_CPU_NUM > 1
|
||||||
"Interrupt wdt timeout on CPU1",
|
"Interrupt wdt timeout on CPU1",
|
||||||
#endif
|
#endif
|
||||||
"Cache error"
|
"Cache error",
|
||||||
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
"Memory protection fault",
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
info->reason = pseudo_reason[0];
|
info->reason = pseudo_reason[0];
|
||||||
@@ -204,14 +251,16 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
|||||||
* assign function print_cache_err_details to our structure's
|
* assign function print_cache_err_details to our structure's
|
||||||
* details field. As its name states, it will give more details
|
* details field. As its name states, it will give more details
|
||||||
* about why the error happened. */
|
* about why the error happened. */
|
||||||
|
|
||||||
info->core = esp_cache_err_get_cpuid();
|
info->core = esp_cache_err_get_cpuid();
|
||||||
info->reason = pseudo_reason[PANIC_RSN_CACHEERR];
|
info->reason = pseudo_reason[PANIC_RSN_CACHEERR];
|
||||||
info->details = print_cache_err_details;
|
info->details = print_cache_err_details;
|
||||||
|
|
||||||
} else if (frame->mcause == ETS_T1_WDT_INUM) {
|
} else if (frame->mcause == ETS_T1_WDT_INUM) {
|
||||||
/* Watchdog interrupt occured, get the core on which it happened
|
/* Watchdog interrupt occured, get the core on which it happened
|
||||||
* and update the reason/message accordingly. */
|
* and update the reason/message accordingly. */
|
||||||
const int core = esp_cache_err_get_cpuid();
|
|
||||||
|
|
||||||
|
const int core = esp_cache_err_get_cpuid();
|
||||||
info->core = core;
|
info->core = core;
|
||||||
info->exception = PANIC_EXCEPTION_IWDT;
|
info->exception = PANIC_EXCEPTION_IWDT;
|
||||||
|
|
||||||
@@ -221,6 +270,14 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
|||||||
#endif
|
#endif
|
||||||
info->reason = pseudo_reason[PANIC_RSN_INTWDT_CPU0 + core];
|
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();
|
||||||
|
info->reason = pseudo_reason[PANIC_RSN_MEMPROT];
|
||||||
|
info->details = print_memprot_err_details;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void panic_arch_fill_info(void *frame, panic_info_t *info)
|
void panic_arch_fill_info(void *frame, panic_info_t *info)
|
||||||
|
@@ -31,11 +31,15 @@
|
|||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
#include "esp32s2/cache_err_int.h"
|
#include "esp32s2/cache_err_int.h"
|
||||||
|
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
#include "esp32s2/memprot.h"
|
#include "esp32s2/memprot.h"
|
||||||
|
#endif
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/cache_err_int.h"
|
#include "esp32s3/cache_err_int.h"
|
||||||
|
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
#include "esp32s3/memprot.h"
|
#include "esp32s3/memprot.h"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#endif // CONFIG_IDF_TARGET_ESP32
|
#endif // CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
void panic_print_registers(const void *f, int core)
|
void panic_print_registers(const void *f, int core)
|
||||||
@@ -261,6 +265,7 @@ static inline void print_cache_err_details(const void *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
static inline void print_memprot_err_details(const void *f)
|
static inline void print_memprot_err_details(const void *f)
|
||||||
{
|
{
|
||||||
uint32_t *fault_addr;
|
uint32_t *fault_addr;
|
||||||
@@ -278,6 +283,7 @@ static inline void print_memprot_err_details(const void *f)
|
|||||||
panic_print_hex( (uint32_t)fault_addr );
|
panic_print_hex( (uint32_t)fault_addr );
|
||||||
panic_print_str(" not permitted.\r\n");
|
panic_print_str(" not permitted.\r\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
static inline void print_cache_err_details(const void* f)
|
static inline void print_cache_err_details(const void* f)
|
||||||
@@ -346,10 +352,6 @@ static inline void print_cache_err_details(const void* f)
|
|||||||
}
|
}
|
||||||
panic_print_str("\r\n");
|
panic_print_str("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void print_memprot_err_details(const void *f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -429,10 +431,13 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
|||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S2
|
||||||
if (frame->exccause == PANIC_RSN_CACHEERR) {
|
if (frame->exccause == PANIC_RSN_CACHEERR) {
|
||||||
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
if ( esp_memprot_is_intr_ena_any() ) {
|
if ( esp_memprot_is_intr_ena_any() ) {
|
||||||
info->details = print_memprot_err_details;
|
info->details = print_memprot_err_details;
|
||||||
info->reason = "Memory protection fault";
|
info->reason = "Memory protection fault";
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
info->details = print_cache_err_details;
|
info->details = print_cache_err_details;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,7 @@
|
|||||||
#include "esp32s3/rom/cache.h"
|
#include "esp32s3/rom/cache.h"
|
||||||
#include "esp32c3/rom/rtc.h"
|
#include "esp32c3/rom/rtc.h"
|
||||||
#include "soc/cache_memory.h"
|
#include "soc/cache_memory.h"
|
||||||
|
#include "esp32c3/memprot.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "bootloader_flash_config.h"
|
#include "bootloader_flash_config.h"
|
||||||
@@ -453,14 +454,12 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||||||
|
|
||||||
esp_cache_err_int_init();
|
esp_cache_err_int_init();
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
|
||||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE_LOCK
|
|
||||||
esp_memprot_set_prot(true, true, NULL);
|
esp_memprot_set_prot(true, true, NULL);
|
||||||
#else
|
#else
|
||||||
esp_memprot_set_prot(true, false, NULL);
|
esp_memprot_set_prot(true, false, NULL);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bootloader_flash_update_id();
|
bootloader_flash_update_id();
|
||||||
|
@@ -37,6 +37,9 @@
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/memprot.h"
|
#include "esp32s3/memprot.h"
|
||||||
#include "esp32s3/cache_err_int.h"
|
#include "esp32s3/cache_err_int.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#include "esp32c3/memprot.h"
|
||||||
|
#include "esp32c3/cache_err_int.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "esp_private/panic_internal.h"
|
#include "esp_private/panic_internal.h"
|
||||||
@@ -183,8 +186,7 @@ static void panic_handler(void *frame, bool pseudo_excause)
|
|||||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||||
|| panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1
|
|| panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1
|
||||||
#endif
|
#endif
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
wdt_hal_write_protect_disable(&wdt0_context);
|
wdt_hal_write_protect_disable(&wdt0_context);
|
||||||
wdt_hal_handle_intr(&wdt0_context);
|
wdt_hal_handle_intr(&wdt0_context);
|
||||||
wdt_hal_write_protect_enable(&wdt0_context);
|
wdt_hal_write_protect_enable(&wdt0_context);
|
||||||
@@ -221,7 +223,7 @@ void __attribute__((noreturn)) panic_restart(void)
|
|||||||
digital_reset_needed = true;
|
digital_reset_needed = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_ESP_SYSTEM_CONFIG_MEMPROT_FEATURE
|
||||||
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
|
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
|
||||||
digital_reset_needed = true;
|
digital_reset_needed = true;
|
||||||
}
|
}
|
||||||
|
@@ -10,5 +10,9 @@ CONFIG_ESP32S2_PANIC_PRINT_HALT CONFIG_ESP_SYSTEM_PANIC_
|
|||||||
CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT
|
CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT
|
||||||
CONFIG_ESP32S2_PANIC_SILENT_REBOOT CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
CONFIG_ESP32S2_PANIC_SILENT_REBOOT CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
||||||
CONFIG_ESP32S2_PANIC_GDBSTUB CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
|
CONFIG_ESP32S2_PANIC_GDBSTUB CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
|
||||||
|
CONFIG_ESP32S2_MEMPROT_FEATURE CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
CONFIG_ESP32S2_MEMPROT_FEATURE_LOCK CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
|
||||||
|
CONFIG_ESP32C3_MEMPROT_FEATURE CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
CONFIG_ESP32C3_MEMPROT_FEATURE_LOCK CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
|
||||||
|
|
||||||
CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES CONFIG_ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES
|
CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES CONFIG_ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES
|
||||||
|
@@ -75,11 +75,15 @@ void IRAM_ATTR esp_restart(void)
|
|||||||
// Disable scheduler on this core.
|
// Disable scheduler on this core.
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2
|
bool digital_reset_needed = false;
|
||||||
|
#if CONFIG_ESP_SYSTEM_CONFIG_MEMPROT_FEATURE
|
||||||
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
|
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
|
||||||
esp_restart_noos_dig();
|
digital_reset_needed = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (digital_reset_needed) {
|
||||||
|
esp_restart_noos_dig();
|
||||||
|
}
|
||||||
esp_restart_noos();
|
esp_restart_noos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
446
components/hal/esp32c3/include/hal/memprot_ll.h
Normal file
446
components/hal/esp32c3/include/hal/memprot_ll.h
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "soc/sensitive_reg.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* === globals ====
|
||||||
|
*/
|
||||||
|
#ifndef SRAM_IRAM_START
|
||||||
|
#define SRAM_IRAM_START 0x4037C000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SRAM_DRAM_START
|
||||||
|
#define SRAM_DRAM_START 0x3FC7C000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
#ifndef I_D_SRAM_OFFSET
|
||||||
|
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 2nd stage bootloader iram_loader_seg start address */
|
||||||
|
#ifndef SRAM_DRAM_END
|
||||||
|
#define SRAM_DRAM_END (0x403D0000 - I_D_SRAM_OFFSET)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SRAM_IRAM_ORG
|
||||||
|
#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SRAM_DRAM_ORG
|
||||||
|
#define SRAM_DRAM_ORG (SRAM_DRAM_START + ICACHE_SIZE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef I_D_SRAM_SIZE
|
||||||
|
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define I_D_SPLIT_LINE_SHIFT 0x9
|
||||||
|
|
||||||
|
#define MAP_DRAM_TO_IRAM(addr) (addr - SRAM_DRAM_START + SRAM_IRAM_START)
|
||||||
|
#define MAP_IRAM_TO_DRAM(addr) (addr - SRAM_IRAM_START + SRAM_DRAM_START)
|
||||||
|
|
||||||
|
|
||||||
|
static inline void memprot_ll_set_iram0_dram0_split_line_lock(bool lock)
|
||||||
|
{
|
||||||
|
REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, lock ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* === IRAM0 ====
|
||||||
|
*/
|
||||||
|
//16kB (CACHE)
|
||||||
|
#define IRAM0_SRAM_LEVEL_0_LOW SRAM_IRAM_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SPLIT LINE */
|
||||||
|
|
||||||
|
static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg)
|
||||||
|
{
|
||||||
|
uint32_t addr = (uint32_t)line_addr;
|
||||||
|
assert( addr >= IRAM0_SRAM_LEVEL_1_LOW && addr <= IRAM0_SRAM_LEVEL_3_HIGH );
|
||||||
|
|
||||||
|
uint32_t category[3] = {0};
|
||||||
|
if (addr <= IRAM0_SRAM_LEVEL_1_HIGH) {
|
||||||
|
category[0] = 0x2;
|
||||||
|
category[1] = category[2] = 0x3;
|
||||||
|
} else if (addr >= IRAM0_SRAM_LEVEL_2_LOW && addr <= IRAM0_SRAM_LEVEL_2_HIGH) {
|
||||||
|
category[1] = 0x2;
|
||||||
|
category[2] = 0x3;
|
||||||
|
} else {
|
||||||
|
category[2] = 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//category bits are the same for all areas
|
||||||
|
uint32_t category_bits =
|
||||||
|
(category[0] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_0_S) |
|
||||||
|
(category[1] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_1_S) |
|
||||||
|
(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can be both IRAM0/DRAM0 address */
|
||||||
|
static inline void 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PMS */
|
||||||
|
|
||||||
|
static inline void memprot_ll_iram0_set_pms_lock(bool lock)
|
||||||
|
{
|
||||||
|
REG_WRITE(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG, lock ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool memprot_ll_iram0_get_pms_lock(void)
|
||||||
|
{
|
||||||
|
return REG_READ(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//world_0 permissions
|
||||||
|
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 ( w ) {
|
||||||
|
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
|
||||||
|
}
|
||||||
|
if ( x ) {
|
||||||
|
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F;
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_iram0_set_pms_area_0(bool r, bool w, bool x)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0, memprot_ll_iram0_set_permissions(r, w, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_iram0_set_pms_area_1(bool r, bool w, bool x)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1, memprot_ll_iram0_set_permissions(r, w, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_iram0_set_pms_area_2(bool r, bool w, bool x)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2, memprot_ll_iram0_set_permissions(r, w, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_iram0_set_pms_area_3(bool r, bool w, bool x)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3, memprot_ll_iram0_set_permissions(r, w, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MONITOR */
|
||||||
|
|
||||||
|
static inline void memprot_ll_iram0_set_monitor_lock(bool lock)
|
||||||
|
{
|
||||||
|
REG_WRITE(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG, lock ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool memprot_ll_iram0_get_monitor_lock(void)
|
||||||
|
{
|
||||||
|
return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
} else {
|
||||||
|
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_en(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT( 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)
|
||||||
|
{
|
||||||
|
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_status_intr(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT( 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_BIT( 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_BIT( 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_addr(void)
|
||||||
|
{
|
||||||
|
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* === DRAM0 ====
|
||||||
|
*/
|
||||||
|
|
||||||
|
//cache not available from DRAM
|
||||||
|
#define DRAM0_SRAM_LEVEL_0_LOW SRAM_DRAM_START //0x3FC7C000
|
||||||
|
#define DRAM0_SRAM_LEVEL_0_HIGH (DRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x3FC7FFFF
|
||||||
|
|
||||||
|
//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
|
||||||
|
|
||||||
|
//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
|
||||||
|
|
||||||
|
//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
|
||||||
|
|
||||||
|
#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W 0x2
|
||||||
|
#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R 0x1
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint32_t memprot_ll_dram0_get_intr_source_num(void)
|
||||||
|
{
|
||||||
|
return ETS_CORE0_DRAM0_PMS_INTR_SOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SPLIT LINE */
|
||||||
|
|
||||||
|
static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg)
|
||||||
|
{
|
||||||
|
uint32_t addr = (uint32_t)line_addr;
|
||||||
|
assert( addr >= DRAM0_SRAM_LEVEL_1_LOW && addr <= DRAM0_SRAM_LEVEL_3_HIGH );
|
||||||
|
|
||||||
|
uint32_t category[3] = {0};
|
||||||
|
if (addr <= DRAM0_SRAM_LEVEL_1_HIGH) {
|
||||||
|
category[0] = 0x2;
|
||||||
|
category[1] = category[2] = 0x3;
|
||||||
|
} else if (addr >= DRAM0_SRAM_LEVEL_2_LOW && addr <= DRAM0_SRAM_LEVEL_2_HIGH) {
|
||||||
|
category[1] = 0x2;
|
||||||
|
category[2] = 0x3;
|
||||||
|
} else {
|
||||||
|
category[2] = 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//category bits are the same for all areas
|
||||||
|
uint32_t category_bits =
|
||||||
|
(category[0] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_0_S) |
|
||||||
|
(category[1] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_1_S) |
|
||||||
|
(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void 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_2_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void 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_3_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PMS */
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_set_pms_lock(bool lock)
|
||||||
|
{
|
||||||
|
REG_WRITE(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG, lock ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool memprot_ll_dram0_get_pms_lock(void)
|
||||||
|
{
|
||||||
|
return REG_READ(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ( w ) {
|
||||||
|
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_set_pms_area_0(bool r, bool w)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0, memprot_ll_dram0_set_permissions(r, w));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_set_pms_area_1(bool r, bool w)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1, memprot_ll_dram0_set_permissions(r, w));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_set_pms_area_2(bool r, bool w)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2, memprot_ll_dram0_set_permissions(r, w));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_set_pms_area_3(bool r, bool w)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3, memprot_ll_dram0_set_permissions(r, w));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MONITOR */
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_set_monitor_lock(bool lock)
|
||||||
|
{
|
||||||
|
REG_WRITE(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG, lock ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool memprot_ll_dram0_get_monitor_lock(void)
|
||||||
|
{
|
||||||
|
return REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memprot_ll_dram0_clear_monitor_intr(void)
|
||||||
|
{
|
||||||
|
REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t memprot_ll_dram0_get_monitor_status_intr(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT( 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_BIT( 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_addr(void)
|
||||||
|
{
|
||||||
|
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_wr(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT( 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_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -11,7 +11,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#ifndef CONFIG_ESP32S2_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
TEST_CASE("Capabilities allocator test", "[heap]")
|
TEST_CASE("Capabilities allocator test", "[heap]")
|
||||||
{
|
{
|
||||||
char *m1, *m2[10];
|
char *m1, *m2[10];
|
||||||
|
@@ -23,7 +23,7 @@ TEST_CASE("realloc shrink buffer in place", "[heap]")
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_ESP32S2_MEMPROT_FEATURE
|
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
TEST_CASE("realloc shrink buffer with EXEC CAPS", "[heap]")
|
TEST_CASE("realloc shrink buffer with EXEC CAPS", "[heap]")
|
||||||
{
|
{
|
||||||
const size_t buffer_size = 64;
|
const size_t buffer_size = 64;
|
||||||
|
@@ -30,7 +30,7 @@ TEST_CASE("Allocate new heap at runtime", "[heap][ignore]")
|
|||||||
TEST_CASE("Allocate new heap with new capability", "[heap][ignore]")
|
TEST_CASE("Allocate new heap with new capability", "[heap][ignore]")
|
||||||
{
|
{
|
||||||
const size_t BUF_SZ = 100;
|
const size_t BUF_SZ = 100;
|
||||||
#ifdef CONFIG_ESP32S2_MEMPROT_FEATURE
|
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
const size_t ALLOC_SZ = 32;
|
const size_t ALLOC_SZ = 32;
|
||||||
#else
|
#else
|
||||||
const size_t ALLOC_SZ = 64; // More than half of BUF_SZ
|
const size_t ALLOC_SZ = 64; // More than half of BUF_SZ
|
||||||
|
@@ -20,5 +20,8 @@ enum _panic_reasons {
|
|||||||
PANIC_RSN_INTWDT_CPU1,
|
PANIC_RSN_INTWDT_CPU1,
|
||||||
#endif
|
#endif
|
||||||
PANIC_RSN_CACHEERR,
|
PANIC_RSN_CACHEERR,
|
||||||
|
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
PANIC_RSN_MEMPROT,
|
||||||
|
#endif
|
||||||
PANIC_RSN_COUNT
|
PANIC_RSN_COUNT
|
||||||
} panic_reasons;
|
} panic_reasons;
|
||||||
|
@@ -126,7 +126,12 @@ _vector_table:
|
|||||||
.endr
|
.endr
|
||||||
j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/
|
j _panic_handler /* Call panic handler for ETS_T1_WDT_INUM interrupt (soc-level panic)*/
|
||||||
j _panic_handler /* Call panic handler for ETS_CACHEERR_INUM interrupt (soc-level panic)*/
|
j _panic_handler /* Call panic handler for ETS_CACHEERR_INUM interrupt (soc-level panic)*/
|
||||||
|
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
|
j _panic_handler /* Call panic handler for ETS_MEMPROT_ERR_INUM interrupt (soc-level panic)*/
|
||||||
|
.rept (ETS_MAX_INUM - ETS_MEMPROT_ERR_INUM)
|
||||||
|
#else
|
||||||
.rept (ETS_MAX_INUM - ETS_CACHEERR_INUM)
|
.rept (ETS_MAX_INUM - ETS_CACHEERR_INUM)
|
||||||
|
#endif
|
||||||
j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */
|
j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */
|
||||||
.endr
|
.endr
|
||||||
|
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
#include "esp_bit_defs.h"
|
#include "esp_bit_defs.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#define PRO_CPU_NUM (0)
|
#define PRO_CPU_NUM (0)
|
||||||
|
|
||||||
#define DR_REG_SYSTEM_BASE 0x600c0000
|
#define DR_REG_SYSTEM_BASE 0x600c0000
|
||||||
@@ -314,6 +316,9 @@
|
|||||||
#define ETS_FRC1_INUM 22
|
#define ETS_FRC1_INUM 22
|
||||||
#define ETS_T1_WDT_INUM 24
|
#define ETS_T1_WDT_INUM 24
|
||||||
#define ETS_CACHEERR_INUM 25
|
#define ETS_CACHEERR_INUM 25
|
||||||
|
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
#define ETS_MEMPROT_ERR_INUM 26
|
||||||
|
#endif
|
||||||
#define ETS_DPORT_INUM 28
|
#define ETS_DPORT_INUM 28
|
||||||
|
|
||||||
//CPU0 Max valid interrupt number
|
//CPU0 Max valid interrupt number
|
||||||
|
@@ -45,7 +45,7 @@ const soc_memory_type_desc_t soc_memory_types[] = {
|
|||||||
{ "FAKEDRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT, 0 }, false, false},
|
{ "FAKEDRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT, 0 }, false, false},
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32C3_MEMPROT_FEATURE //TODO ESP32-C3 IDF-2092
|
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
#define SOC_MEMORY_TYPE_DEFAULT 0
|
#define SOC_MEMORY_TYPE_DEFAULT 0
|
||||||
#else
|
#else
|
||||||
#define SOC_MEMORY_TYPE_DEFAULT 2
|
#define SOC_MEMORY_TYPE_DEFAULT 2
|
||||||
|
@@ -55,7 +55,7 @@ const soc_memory_type_desc_t soc_memory_types[] = {
|
|||||||
{ "RTCRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT, 0 }, false, false},
|
{ "RTCRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT, 0 }, false, false},
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_MEMPROT_FEATURE
|
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||||
#define SOC_MEMORY_TYPE_DEFAULT 0
|
#define SOC_MEMORY_TYPE_DEFAULT 0
|
||||||
#else
|
#else
|
||||||
#define SOC_MEMORY_TYPE_DEFAULT 2
|
#define SOC_MEMORY_TYPE_DEFAULT 2
|
||||||
|
1
tools/unit-test-app/sdkconfig.defaults.esp32c3
Normal file
1
tools/unit-test-app/sdkconfig.defaults.esp32c3
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
@@ -1,5 +1,5 @@
|
|||||||
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
|
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
|
||||||
CONFIG_ESP32S2_MEMPROT_FEATURE=n
|
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
||||||
|
|
||||||
CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
|
CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
|
||||||
CONFIG_ESP32S2_ULP_COPROC_RISCV=y
|
CONFIG_ESP32S2_ULP_COPROC_RISCV=y
|
||||||
|
Reference in New Issue
Block a user