Security: ESP32C3 memory protection feature (IRAM0/DRAM0)

Software support for PMS module.
Allows controlled memory access to IRAM (R/W/X) and DRAM0 (R/W)
On/locked by default, configurable in Kconfig (esp_system)

Closes https://jira.espressif.com:8443/browse/IDF-2092
This commit is contained in:
Martin Vychodil 2021-01-04 19:38:10 +01:00
parent d097988608
commit 69096ddce5
24 changed files with 1166 additions and 374 deletions

View File

@ -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, "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);
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));
@ -574,7 +574,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
srand(52);
for (int i = 0; i < 320/4; i++) {
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
data_iram[i] = rand();
#endif
data_dram[i] = rand();
@ -601,7 +601,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
int x;
memset(trans, 0, sizeof(trans));
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
trans[0].length = 320*8,
trans[0].tx_buffer = data_iram;
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;
//Queue all transactions.
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
for (x=0; x<TEST_REGION_SIZE; x++) {
#else
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_free(TEST_SPI_HOST) == ESP_OK);
free(data_malloc);
#ifndef CONFIG_ESP32C3_MEMPROT_FEATURE
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
free(data_iram);
#endif
}

View File

@ -19,6 +19,7 @@ else()
"esp_ds.c"
"esp_crypto_lock.c"
"hw_random.c"
"memprot.c"
"system_api_esp32c3.c")
set(include_dirs "include")

View File

@ -14,12 +14,12 @@
/* INTERNAL API
* generic interface to MMU memory protection features
* generic interface to PMS memory protection features
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_attr.h"
#ifdef __cplusplus
@ -27,329 +27,67 @@ extern "C" {
#endif
typedef enum {
MEMPROT_IRAM0 = 0x00000000,
MEMPROT_DRAM0 = 0x00000001,
MEMPROT_UNKNOWN
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001,
MEMPROT_DRAM0_SRAM = 0x00000002,
MEMPROT_ALL = 0xFFFFFFFF
} 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;
/**
* @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);
typedef enum {
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;
/**
* @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);
const char *mem_type_to_str(mem_type_prot_t mem_type);
const char *split_line_to_str(split_line_t line_type);
const char *pms_to_str(pms_area_t area_type);
/**
* @brief Detects whether any of the memory protection interrupts is active
*
* @return true/false
*/
bool esp_memprot_is_assoc_intr_any(void);
void *esp_memprot_get_main_split_addr(void);
void esp_memprot_set_split_line_lock(bool lock);
bool esp_memprot_get_split_line_lock(void);
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
/**
* @brief Detects whether specific memory protection interrupt is active
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return true/false
*/
bool esp_memprot_is_assoc_intr(mem_type_prot_t mem_type);
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock);
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);
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
/**
* @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);
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock);
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);
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
/**
* @brief Detects which memory protection interrupt is active, check order: IRAM0, DRAM0
*
* @return Memory protection area type (see mem_type_prot_t enum)
*/
mem_type_prot_t IRAM_ATTR esp_memprot_get_intr_memtype(void);
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
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);
bool IRAM_ATTR esp_memprot_is_locked_any(void);
bool IRAM_ATTR esp_memprot_is_intr_ena_any(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);
uint32_t IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
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);
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);
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(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 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);
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
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);
#ifdef __cplusplus
}

View File

@ -359,7 +359,8 @@ SECTIONS
/* Marks the end of IRAM code segment */
.iram0.text_end (NOLOAD) :
{
. = ALIGN (16);
/* C3 memprot requires 512 B alignment for split lines */
. = ALIGN (0x200);
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg

View 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);
}
}
}

View File

@ -29,29 +29,6 @@ menu "ESP32S2-specific"
default 160 if ESP32S2_DEFAULT_CPU_FREQ_160
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"
choice ESP32S2_INSTRUCTION_CACHE_SIZE

View File

@ -98,4 +98,28 @@ menu "ESP System Settings"
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.
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

View File

@ -22,6 +22,9 @@
#if CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/cache_err_int.h"
#endif
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#include "esp32c3/memprot.h"
#endif
#define DIM(array) (sizeof(array)/sizeof(*array))
@ -33,7 +36,7 @@
*/
typedef struct {
const uint32_t bit;
const char* msg;
const char *msg;
} register_bit_t;
/**
@ -45,8 +48,8 @@ typedef struct {
* be set in the register will have its associated message printed.
*/
static inline bool test_and_print_register_bits(const uint32_t status,
const register_bit_t* reg_bits,
const uint32_t size)
const register_bit_t *reg_bits,
const uint32_t size)
{
/* Browse the flag/bit array and test each one with the given status
* register. */
@ -69,7 +72,7 @@ static inline bool test_and_print_register_bits(const uint32_t status,
* Function called when a cache error occurs. It prints details such as the
* explanation of why the panic occured.
*/
static inline void print_cache_err_details(const void* frame)
static inline void print_cache_err_details(const void *frame)
{
/* Define the array that contains the status (bits) to test on the register
* EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. each bit is accompanied by a small
@ -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)
{
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
"Interrupt wdt timeout on CPU1",
#endif
"Cache error"
"Cache error",
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
"Memory protection fault",
#endif
};
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
* details field. As its name states, it will give more details
* about why the error happened. */
info->core = esp_cache_err_get_cpuid();
info->reason = pseudo_reason[PANIC_RSN_CACHEERR];
info->details = print_cache_err_details;
} else if (frame->mcause == ETS_T1_WDT_INUM) {
/* Watchdog interrupt occured, get the core on which it happened
* 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->exception = PANIC_EXCEPTION_IWDT;
@ -221,6 +270,14 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
#endif
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)

View File

@ -31,11 +31,15 @@
#include "soc/rtc_cntl_reg.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/cache_err_int.h"
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#include "esp32s2/memprot.h"
#endif
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/cache_err_int.h"
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#include "esp32s3/memprot.h"
#endif
#endif
#endif // CONFIG_IDF_TARGET_ESP32
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)
{
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_str(" not permitted.\r\n");
}
#endif
#elif CONFIG_IDF_TARGET_ESP32S3
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");
}
static inline void print_memprot_err_details(const void *f)
{
}
#endif
@ -429,10 +431,13 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
#if CONFIG_IDF_TARGET_ESP32S2
if (frame->exccause == PANIC_RSN_CACHEERR) {
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
if ( esp_memprot_is_intr_ena_any() ) {
info->details = print_memprot_err_details;
info->reason = "Memory protection fault";
} else {
} else
#endif
{
info->details = print_cache_err_details;
}
}

View File

@ -63,6 +63,7 @@
#include "esp32s3/rom/cache.h"
#include "esp32c3/rom/rtc.h"
#include "soc/cache_memory.h"
#include "esp32c3/memprot.h"
#endif
#include "bootloader_flash_config.h"
@ -253,11 +254,11 @@ void IRAM_ATTR call_start_cpu0(void)
// (This should be the first thing IDF app does, as any other piece of code could be
// relaxed by the linker to access something relative to __global_pointer$)
__asm__ __volatile__ (
".option push\n"
".option push\n"
".option norelax\n"
"la gp, __global_pointer$\n"
".option pop"
);
);
#endif
// Move exception vectors to IRAM
@ -453,14 +454,12 @@ void IRAM_ATTR call_start_cpu0(void)
esp_cache_err_int_init();
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_ESP32S2_MEMPROT_FEATURE
#if CONFIG_ESP32S2_MEMPROT_FEATURE_LOCK
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
esp_memprot_set_prot(true, true, NULL);
#else
esp_memprot_set_prot(true, false, NULL);
#endif
#endif
#endif
bootloader_flash_update_id();

View File

@ -37,6 +37,9 @@
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/memprot.h"
#include "esp32s3/cache_err_int.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/memprot.h"
#include "esp32c3/cache_err_int.h"
#endif
#include "esp_private/panic_internal.h"
@ -47,7 +50,7 @@
extern int _invalid_pc_placeholder;
extern void esp_panic_handler(panic_info_t*);
extern void esp_panic_handler(panic_info_t *);
static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
@ -181,10 +184,9 @@ static void panic_handler(void *frame, bool pseudo_excause)
#endif
if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|| panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1
|| panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1
#endif
)
{
) {
wdt_hal_write_protect_disable(&wdt0_context);
wdt_hal_handle_intr(&wdt0_context);
wdt_hal_write_protect_enable(&wdt0_context);
@ -221,7 +223,7 @@ void __attribute__((noreturn)) panic_restart(void)
digital_reset_needed = true;
}
#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()) {
digital_reset_needed = true;
}

View File

@ -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_SILENT_REBOOT CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
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

View File

@ -75,11 +75,15 @@ void IRAM_ATTR esp_restart(void)
// Disable scheduler on this core.
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()) {
esp_restart_noos_dig();
digital_reset_needed = true;
}
#endif
if (digital_reset_needed) {
esp_restart_noos_dig();
}
esp_restart_noos();
}

View 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

View File

@ -11,7 +11,7 @@
#include <stdlib.h>
#include <sys/param.h>
#ifndef CONFIG_ESP32S2_MEMPROT_FEATURE
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
TEST_CASE("Capabilities allocator test", "[heap]")
{
char *m1, *m2[10];

View File

@ -23,7 +23,7 @@ TEST_CASE("realloc shrink buffer in place", "[heap]")
#endif
#ifndef CONFIG_ESP32S2_MEMPROT_FEATURE
#ifndef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
TEST_CASE("realloc shrink buffer with EXEC CAPS", "[heap]")
{
const size_t buffer_size = 64;

View File

@ -30,7 +30,7 @@ TEST_CASE("Allocate new heap at runtime", "[heap][ignore]")
TEST_CASE("Allocate new heap with new capability", "[heap][ignore]")
{
const size_t BUF_SZ = 100;
#ifdef CONFIG_ESP32S2_MEMPROT_FEATURE
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
const size_t ALLOC_SZ = 32;
#else
const size_t ALLOC_SZ = 64; // More than half of BUF_SZ

View File

@ -20,5 +20,8 @@ enum _panic_reasons {
PANIC_RSN_INTWDT_CPU1,
#endif
PANIC_RSN_CACHEERR,
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
PANIC_RSN_MEMPROT,
#endif
PANIC_RSN_COUNT
} panic_reasons;

View File

@ -125,8 +125,13 @@ _vector_table:
j _interrupt_handler /* 24 identical entries, all pointing to the interrupt handler */
.endr
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)
#endif
j _interrupt_handler /* 6 identical entries, all pointing to the interrupt handler */
.endr

View File

@ -20,6 +20,8 @@
#include "esp_bit_defs.h"
#endif
#include "sdkconfig.h"
#define PRO_CPU_NUM (0)
#define DR_REG_SYSTEM_BASE 0x600c0000
@ -314,6 +316,9 @@
#define ETS_FRC1_INUM 22
#define ETS_T1_WDT_INUM 24
#define ETS_CACHEERR_INUM 25
#ifdef CONFIG_IDF_TARGET_ESP32C3
#define ETS_MEMPROT_ERR_INUM 26
#endif
#define ETS_DPORT_INUM 28
//CPU0 Max valid interrupt number

View File

@ -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},
};
#ifdef CONFIG_ESP32C3_MEMPROT_FEATURE //TODO ESP32-C3 IDF-2092
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#define SOC_MEMORY_TYPE_DEFAULT 0
#else
#define SOC_MEMORY_TYPE_DEFAULT 2

View File

@ -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},
};
#ifdef CONFIG_ESP32S2_MEMPROT_FEATURE
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#define SOC_MEMORY_TYPE_DEFAULT 0
#else
#define SOC_MEMORY_TYPE_DEFAULT 2

View File

@ -0,0 +1 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n

View File

@ -1,5 +1,5 @@
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_RISCV=y