Merge branch 'feature/esp32c3_memprot_test3' into 'master'

ESP32C3/ESP32S2: memprot API upgrade and test application

Closes IDF-2641

See merge request espressif/esp-idf!12941
This commit is contained in:
Angus Gratton 2021-04-13 18:42:46 +00:00
commit ec01a66557
23 changed files with 1503 additions and 298 deletions

View File

@ -287,6 +287,11 @@ example_test_C3_FLASH_ENC_OTA:
- .test_app_template
- .rules:test:custom_test-esp32s2
.test_app_esp32c3_template:
extends:
- .test_app_template
- .rules:test:custom_test-esp32c3
test_app_test_001:
extends: .test_app_esp32_template
tags:
@ -317,6 +322,12 @@ test_app_test_004:
- ESP32S2
- Example_GENERIC
test_app_test_005:
extends: .test_app_esp32c3_template
tags:
- ESP32C3
- Example_GENERIC
test_app_test_esp32_generic:
extends: .test_app_esp32_template
parallel: 4

View File

@ -38,9 +38,9 @@ else()
# Process the template file through the linker script generation mechanism, and use the output for linking the
# final binary
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32c3.project.ld.in"
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32c3.project.ld")
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32c3.project.ld")
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32c3.peripherals.ld")
target_link_libraries(${COMPONENT_LIB} PUBLIC gcc)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start_cpu0")

View File

@ -26,6 +26,22 @@
extern "C" {
#endif
#ifndef IRAM_SRAM_START
#define IRAM_SRAM_START 0x4037C000
#endif
#ifndef DRAM_SRAM_START
#define DRAM_SRAM_START 0x3FC7C000
#endif
#ifndef MAP_DRAM_TO_IRAM
#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START)
#endif
#ifndef MAP_IRAM_TO_DRAM
#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START)
#endif
typedef enum {
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001,
@ -34,6 +50,7 @@ typedef enum {
} mem_type_prot_t;
typedef enum {
MEMPROT_SPLITLINE_NONE = 0,
MEMPROT_IRAM0_DRAM0_SPLITLINE,
MEMPROT_IRAM0_LINE_0_SPLITLINE,
MEMPROT_IRAM0_LINE_1_SPLITLINE,
@ -42,6 +59,7 @@ typedef enum {
} split_line_t;
typedef enum {
MEMPROT_PMS_AREA_NONE = 0,
MEMPROT_IRAM0_PMS_AREA_0,
MEMPROT_IRAM0_PMS_AREA_1,
MEMPROT_IRAM0_PMS_AREA_2,
@ -52,43 +70,386 @@ typedef enum {
MEMPROT_DRAM0_PMS_AREA_3
} pms_area_t;
typedef enum
{
MEMPROT_PMS_WORLD_0 = 0,
MEMPROT_PMS_WORLD_1,
MEMPROT_PMS_WORLD_2,
MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
} pms_world_t;
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);
typedef enum
{
MEMPROT_PMS_OP_READ = 0,
MEMPROT_PMS_OP_WRITE,
MEMPROT_PMS_OP_FETCH,
MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
} pms_operation_type_t;
void *esp_memprot_get_main_split_addr(void);
void esp_memprot_set_split_line_lock(bool lock);
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
/**
* @brief Converts Split line type to string
*
* @param line_type Split line type (see split_line_t enum)
*/
const char *esp_memprot_split_line_to_str(split_line_t line_type);
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type (see pms_area_t enum)
*/
const char *esp_memprot_pms_to_str(pms_area_t area_type);
/**
* @brief Returns PMS splitting address for given Split line type
*
* The value is taken from PMS configuration registers (IRam0 range)
* For details on split lines see 'esp_memprot_set_prot_int' function description
*
* @param line_type Split line type (see split_line_t enum)
*
* @return appropriate split line address
*/
uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
/**
* @brief Returns default main IRAM/DRAM splitting address
*
* The address value is given by _iram_text_end global (IRam0 range)
* @return Main I/D split line (IRam0_DRam0_Split_Addr)
*/
void *esp_memprot_get_default_main_split_addr(void);
/**
* @brief Sets a lock for the main IRAM/DRAM splitting address
*
* Locks can be unlocked only by digital system reset
*/
void esp_memprot_set_split_line_lock(void);
/**
* @brief Gets a lock status for the main IRAM/DRAM splitting address
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_split_line_lock(void);
/**
* @brief Sets required split line address
*
* @param line_type Split line type (see split_line_t enum)
* @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
*/
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock);
/**
* @brief Sets a lock for PMS Area settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS Area settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
* @param x Execute permission flag
*/
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
/**
* @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
* @param x Execute permission flag holder
*/
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
/**
* @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
*/
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock);
/**
* @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
*/
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
/**
* @brief Sets a lock for PMS interrupt monitor settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Enable PMS violation interrupt monitoring of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
* @param enable/disable
*/
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
/**
* @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (enabled/disabled)
*/
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
/**
* @brief Gets CPU ID for currently active PMS violation interrupt
*
* @return CPU ID (CPU_PRO for ESP32C3)
*/
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
/**
* @brief Clears current interrupt ON flag for given Memory type
*
* Interrupt clearing happens in two steps:
* 1. Interrupt CLR flag is set (to clear the interrupt ON status)
* 2. Interrupt CLR flag is reset (to allow further monitoring)
* This operation is non-atomic by PMS module design
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
/**
* @brief Returns active PMS violation interrupt (if any)
*
* This function iterates through supported Memory type status registers
* and returns the first interrupt-on flag. If none is found active,
* MEMPROT_NONE is returned.
* Order of checking (in current version):
* 1. MEMPROT_IRAM0_SRAM
* 2. MEMPROT_DRAM0_SRAM
*
* @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
*/
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
/**
* @brief Checks whether any violation interrupt is active
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_locked_any(void);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
uint32_t IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
/**
* @brief Returns the address which caused the violation interrupt (if any)
*
* The address is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return faulting address
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
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);
/**
* @brief Returns the World identifier of the code causing the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return World identifier (see pms_world_t enum)
*/
pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
/**
* @brief Returns Read or Write operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
*/
pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
/**
* @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
* Effective only on IRam0 access
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (LoadStore bit on/off)
*/
bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
/**
* @brief Returns byte-enables for the address which caused the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return byte-enables
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
/**
* @brief Returns raw contents of DRam0 status register 1
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
/**
* @brief Returns raw contents of DRam0 status register 2
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
/**
* @brief Returns raw contents of IRam0 status register
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
/**
* @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
*
* Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
* The registration makes the panic-handler routine being called when the interrupt appears
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
/**
* @brief Convenient routine for setting the PMS defaults
*
* Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
* For implementation details see 'esp_memprot_set_prot_int' description
*
* @param invoke_panic_handler register all interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
*/
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
/**
* @brief Internal routine for setting the PMS defaults
*
* Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
* (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
* is used (&_iram_text_end) and all the remaining lines share the same address.
* The function sets all the split lines and PMS areas to the same space,
* ie there is a single instruction space and single data space at the end.
* The PMS split lines and permission areas scheme described below:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* ... | IRam0_PMS_0 |
* DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr
* ... | IRam0_PMS_1 |
* ... ----------------------------------------------- IRam0_line0_Split_addr
* | IRam0_PMS_2 |
* =============================================== IRam0_DRam0_Split_addr (main I/D)
* | DRam0_PMS_1 |
* DRam0_DMA_line0_Split_addr ----------------------------------------------- ...
* | DRam0_PMS_2 | ...
* DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3
* | DRam0_PMS_3 | ...
* -----------------------------------------------
*
* Default settings provided by 'esp_memprot_set_prot_int' are as follows:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
* | DRam0_PMS_0 | IRam0_line1_Split_addr
* DRam0_DMA_line0_Split_addr | | =
* = =============================================== IRam0_line0_Split_addr
* DRam0_DMA_line1_Split_addr | | =
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D)
* | IRam0_PMS_3 |
* -----------------------------------------------
*
* Once the memprot feature is locked, it can be unlocked only by digital system reset
*
* @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
*/
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
/**
* @brief Returns raw contents of PMS interrupt monitor register for given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return 32-bit register value
*/
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
#ifdef __cplusplus
}
#endif

View File

@ -340,6 +340,8 @@ SECTIONS
{
/* C3 memprot requires 512 B alignment for split lines */
. = ALIGN (0x200);
/* iram_end_test section exists for use by memprot unit tests only */
*(.iram_end_test)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg

View File

@ -22,34 +22,32 @@
#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 "esp32c3/memprot.h"
#include "riscv/interrupt.h"
#include "esp32c3/rom/ets_sys.h"
#include "esp_log.h"
extern int _iram_text_end;
static const char *TAG = "memprot";
const char *mem_type_to_str(mem_type_prot_t mem_type)
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_NONE:
return "MEMPROT_NONE";
return "NONE";
case MEMPROT_IRAM0_SRAM:
return "MEMPROT_IRAM0_SRAM";
return "IRAM0_SRAM";
case MEMPROT_DRAM0_SRAM:
return "MEMPROT_DRAM0_SRAM";
return "DRAM0_SRAM";
case MEMPROT_ALL:
return "MEMPROT_ALL";
return "ALL";
default:
return "UNKNOWN";
}
}
const char *split_line_to_str(split_line_t line_type)
const char *esp_memprot_split_line_to_str(split_line_t line_type)
{
switch (line_type) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
@ -67,7 +65,7 @@ const char *split_line_to_str(split_line_t line_type)
}
}
const char *pms_to_str(pms_area_t area_type)
const char *esp_memprot_pms_to_str(pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_IRAM0_PMS_AREA_0:
@ -94,14 +92,32 @@ const char *pms_to_str(pms_area_t area_type)
/* split lines */
void *esp_memprot_get_main_split_addr()
void *esp_memprot_get_default_main_split_addr()
{
return &_iram_text_end;
}
void esp_memprot_set_split_line_lock(bool lock)
uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
{
memprot_ll_set_iram0_dram0_split_line_lock(lock);
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
return memprot_ll_get_iram0_split_line_main_I_D();
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_0();
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_1();
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_0();
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_1();
default:
abort();
}
}
void esp_memprot_set_split_line_lock()
{
memprot_ll_set_iram0_dram0_split_line_lock();
}
bool esp_memprot_get_split_line_lock()
@ -111,11 +127,10 @@ bool esp_memprot_get_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_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", split_line_to_str(line_type), addr);
ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
//split-line must be divisible by 512
assert( addr % 0x200 == 0 );
//split-line must be divisible by 512 (PMS module restriction)
assert( ((uint32_t)line_addr) % 0x200 == 0 );
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
@ -134,36 +149,34 @@ void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
memprot_ll_set_dram0_split_line_D_1(line_addr);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", addr);
ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
abort();
}
}
// TODO - get split lines
/* PMS */
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock)
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s, %s)", mem_type_to_str(mem_type), lock ? "true" : "false");
ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_pms_lock(lock);
memprot_ll_iram0_set_pms_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_pms_lock(lock);
memprot_ll_dram0_set_pms_lock();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", mem_type_to_str(mem_type));
ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
@ -171,14 +184,14 @@ bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_pms_lock();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", pms_to_str(area_type), r, w, x);
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
@ -194,14 +207,37 @@ void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
memprot_ll_iram0_set_pms_area_3(r, w, x);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", pms_to_str(area_type));
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_get_pms_area_0(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_1:
memprot_ll_iram0_get_pms_area_1(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_2:
memprot_ll_iram0_get_pms_area_2(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_3:
memprot_ll_iram0_get_pms_area_3(r, w, x);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", pms_to_str(area_type), r, w);
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
@ -217,36 +253,57 @@ void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
memprot_ll_dram0_set_pms_area_3(r, w);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", pms_to_str(area_type));
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
/* TODO - get single areas */
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_get_pms_area_0(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_1:
memprot_ll_dram0_get_pms_area_1(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_2:
memprot_ll_dram0_get_pms_area_2(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_3:
memprot_ll_dram0_get_pms_area_3(r, w);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
/* monitor */
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock)
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s, %s)", mem_type_to_str(mem_type), lock ? "true" : "false");
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_lock(lock);
memprot_ll_iram0_set_monitor_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_lock(lock);
memprot_ll_dram0_set_monitor_lock();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", mem_type_to_str(mem_type));
ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
@ -254,14 +311,14 @@ bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_lock();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", mem_type_to_str(mem_type));
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
@ -271,14 +328,14 @@ void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
memprot_ll_dram0_set_monitor_en(enable);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", mem_type_to_str(mem_type));
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
@ -286,7 +343,7 @@ bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_en();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
@ -298,17 +355,19 @@ bool esp_memprot_is_intr_ena_any()
void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", mem_type_to_str(mem_type));
ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_clear_monitor_intr();
memprot_ll_iram0_reset_clear_monitor_intr();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_clear_monitor_intr();
memprot_ll_dram0_reset_clear_monitor_intr();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
@ -334,15 +393,15 @@ bool esp_memprot_is_locked_any()
esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
}
uint32_t esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_intr();
return memprot_ll_iram0_get_monitor_status_intr() == 1;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_intr();
return memprot_ll_dram0_get_monitor_status_intr() == 1;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
@ -355,44 +414,54 @@ uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_addr();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
{
uint32_t world = 0;
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_world();
world = memprot_ll_iram0_get_monitor_status_fault_world();
break;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_world();
world = memprot_ll_dram0_get_monitor_status_fault_world();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
switch ( world ) {
case 0x01: return MEMPROT_PMS_WORLD_0;
case 0x10: return MEMPROT_PMS_WORLD_1;
default: return MEMPROT_PMS_WORLD_INVALID;
}
}
uint32_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_wr();
return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_wr();
return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_loadstore();
return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
@ -403,7 +472,7 @@ uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_byte_en();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
@ -415,7 +484,7 @@ int esp_memprot_intr_get_cpuid()
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", mem_type_to_str(mem_type));
ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
@ -427,7 +496,7 @@ void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
@ -474,7 +543,7 @@ void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void
}
//set split lines (must-have for all mem_types)
const void *line_addr = split_addr == NULL ? esp_memprot_get_main_split_addr() : split_addr;
const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
@ -507,14 +576,41 @@ void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void
//lock if required
if (lock_feature) {
esp_memprot_set_split_line_lock(true);
esp_memprot_set_split_line_lock();
if (use_iram0) {
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM, true);
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM, true);
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
}
if (use_dram0) {
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM, true);
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM, true);
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
}
}
}
uint32_t esp_memprot_get_dram_status_reg_1()
{
return memprot_ll_dram0_get_monitor_status_register_1();
}
uint32_t esp_memprot_get_dram_status_reg_2()
{
return memprot_ll_dram0_get_monitor_status_register_2();
}
uint32_t esp_memprot_get_iram_status_reg()
{
return memprot_ll_iram0_get_monitor_status_register();
}
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_enable_register();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_enable_register();
default:
abort();
}
}

View File

@ -26,6 +26,32 @@
extern "C" {
#endif
//convenient constants for better code readabilty
#define RD_ENA true
#define RD_DIS false
#define WR_ENA true
#define WR_DIS false
#define EX_ENA true
#define EX_DIS false
#define RD_LOW_ENA true
#define RD_LOW_DIS false
#define WR_LOW_ENA true
#define WR_LOW_DIS false
#define EX_LOW_ENA true
#define EX_LOW_DIS false
#define RD_HIGH_ENA true
#define RD_HIGH_DIS false
#define WR_HIGH_ENA true
#define WR_HIGH_DIS false
#define EX_HIGH_ENA true
#define EX_HIGH_DIS false
#define PANIC_HNDL_ON true
#define PANIC_HNDL_OFF false
#define MEMPROT_LOCK true
#define MEMPROT_UNLOCK false
#define DEF_SPLIT_LINE NULL
//memory range types
typedef enum {
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001, //0x40020000-0x4006FFFF, RWX

View File

@ -85,7 +85,7 @@ SECTIONS
and will be retained during deep sleep.
User data marked with RTC_NOINIT_ATTR will be placed
into this section. See the file "esp_attr.h" for more information.
The memory location of the data is dependent on
The memory location of the data is dependent on
CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option.
*/
.rtc_noinit (NOLOAD):
@ -178,6 +178,8 @@ SECTIONS
/* align + add 16B for CPU dummy speculative instr. fetch */
. = ALIGN(4) + 16;
/* iram_end_test section exists for use by memprot unit tests only */
*(.iram_end_test)
_iram_text_end = ABSOLUTE(.);
_iram_end = ABSOLUTE(.);
} > iram0_0_seg

View File

@ -694,25 +694,25 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t
//set permissions
if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, NULL, false, true, true, true, true, true);
esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_IRAM0_RTCFAST) {
esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, NULL, false, true, true, true, true, true);
esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, NULL, false, true, true, true);
esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA);
}
if (required_mem_prot & MEMPROT_DRAM0_RTCFAST) {
esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, NULL, false, true, true, true);
esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA);
}
if (required_mem_prot & MEMPROT_PERI1_RTCSLOW) {
esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, NULL, true, true, true, true);
esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_0) {
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, NULL, true, true, false, true, true, false);
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_1) {
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, NULL, true, true, false, true, true, false);
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS);
}
//reenable protection (bus based)

View File

@ -151,27 +151,27 @@ static inline void print_cache_err_details(const void *frame)
* explanation of why the panic occured.
*/
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
static inline void print_memprot_err_details(const void *frame)
static inline void print_memprot_err_details(const void *frame __attribute__((unused)))
{
//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_str( esp_memprot_mem_type_to_str(mem_type) );
panic_print_str( "\r\n faulting address: 0x");
panic_print_hex( esp_memprot_get_violate_addr(mem_type) );
panic_print_str( "\r\n world: ");
panic_print_hex( esp_memprot_get_violate_world(mem_type) );
panic_print_str( "\r\n world:");
panic_print_dec( 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 ) {
if ( esp_memprot_get_violate_loadstore(mem_type) ) {
operation = 'X';
}
}
// W/R - common
if ( operation == 0 ) {
operation = esp_memprot_get_violate_wr(mem_type) == 1 ? 'W' : 'R';
operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R';
}
panic_print_str( "\r\n operation type: ");
panic_print_char( operation );

View File

@ -15,21 +15,19 @@
#pragma once
#include "soc/sensitive_reg.h"
#include "soc/cache_memory.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* === globals ====
/* ******************************************************************************************************
* *** GLOBALS ***
* NOTE: in this version, all the configurations apply only to WORLD_0
*/
#ifndef SRAM_IRAM_START
#define SRAM_IRAM_START 0x4037C000
#endif
#ifndef SRAM_DRAM_START
#define SRAM_DRAM_START 0x3FC7C000
#endif
#define IRAM_SRAM_START 0x4037C000
#define DRAM_SRAM_START 0x3FC7C000
/* ICache size is fixed to 16KB on ESP32-C3 */
#ifndef ICACHE_SIZE
@ -40,36 +38,12 @@ extern "C" {
#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 I_D_FAULT_ADDR_SHIFT 0x2
#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)
static inline void memprot_ll_set_iram0_dram0_split_line_lock(void)
{
REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, lock ? 1 : 0);
REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, 1);
}
static inline bool memprot_ll_get_iram0_dram0_split_line_lock(void)
@ -77,12 +51,19 @@ static inline bool memprot_ll_get_iram0_dram0_split_line_lock(void)
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG) == 1;
}
static inline void* memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t base)
{
return (void*)
(base + ((regval & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_M)
>> (SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S - I_D_SPLIT_LINE_SHIFT)));
}
/**
* === IRAM0 ====
/* ******************************************************************************************************
* *** IRAM0 ***
*/
//16kB (CACHE)
#define IRAM0_SRAM_LEVEL_0_LOW SRAM_IRAM_START //0x40370000
#define IRAM0_SRAM_LEVEL_0_LOW IRAM_SRAM_START //0x40370000
#define IRAM0_SRAM_LEVEL_0_HIGH (IRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x4037FFFF
//128kB (LEVEL 1)
@ -107,7 +88,10 @@ static inline uint32_t memprot_ll_iram0_get_intr_source_num(void)
return ETS_CORE0_IRAM0_PMS_INTR_SOURCE;
}
/* SPLIT LINE */
///////////////////////////////////
// IRAM0 - SPLIT LINES
///////////////////////////////////
static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg)
{
@ -125,7 +109,7 @@ static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32
category[2] = 0x2;
}
//category bits are the same for all areas
//NOTE: category & split line address bits are the same for all the 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) |
@ -154,12 +138,30 @@ 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)
static inline void* memprot_ll_get_iram0_split_line_main_I_D(void)
{
REG_WRITE(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG, lock ? 1 : 0);
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG), SOC_DIRAM_IRAM_LOW);
}
static inline void* memprot_ll_get_iram0_split_line_I_0(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG), SOC_DIRAM_IRAM_LOW);
}
static inline void* memprot_ll_get_iram0_split_line_I_1(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG), SOC_DIRAM_IRAM_LOW);
}
///////////////////////////////////
// IRAM0 - PMS CONFIGURATION
///////////////////////////////////
// lock
static inline void memprot_ll_iram0_set_pms_lock(void)
{
REG_WRITE(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_0_REG, 1);
}
static inline bool memprot_ll_iram0_get_pms_lock(void)
@ -167,7 +169,7 @@ 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
// permission settings
static inline uint32_t memprot_ll_iram0_set_permissions(bool r, bool w, bool x)
{
uint32_t permissions = 0;
@ -204,11 +206,46 @@ 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)
static inline void memprot_ll_iram0_get_permissions(uint32_t perms, bool *r, bool *w, bool *x)
{
REG_WRITE(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG, lock ? 1 : 0);
*r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
*w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
*x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F;
}
static inline void memprot_ll_iram0_get_pms_area_0(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
}
static inline void memprot_ll_iram0_get_pms_area_1(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
}
static inline void memprot_ll_iram0_get_pms_area_2(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
}
static inline void memprot_ll_iram0_get_pms_area_3(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
}
///////////////////////////////////
// IRAM0 - MONITOR
///////////////////////////////////
// lock
static inline void memprot_ll_iram0_set_monitor_lock(void)
{
REG_WRITE(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG, 1);
}
static inline bool memprot_ll_iram0_get_monitor_lock(void)
@ -216,6 +253,7 @@ static inline bool memprot_ll_iram0_get_monitor_lock(void)
return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_0_REG) == 1;
}
// interrupt enable/clear
static inline void memprot_ll_iram0_set_monitor_en(bool enable)
{
if ( enable ) {
@ -227,27 +265,38 @@ static inline void memprot_ll_iram0_set_monitor_en(bool enable)
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;
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN ) == 1;
}
static inline void memprot_ll_iram0_clear_monitor_intr(void)
{
REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR );
}
static inline void memprot_ll_iram0_reset_clear_monitor_intr(void)
{
REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR );
}
static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void)
{
return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG);
}
// // permission violation status
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 );
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR );
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_wr(void)
{
return REG_GET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_loadstore(void)
{
return REG_GET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE );
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE );
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_world(void)
@ -257,16 +306,22 @@ static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_world(void)
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 );
uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0;
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void)
{
return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG);
}
/**
* === DRAM0 ====
/* ******************************************************************************************************
* *** DRAM0 ***
*/
//cache not available from DRAM
#define DRAM0_SRAM_LEVEL_0_LOW SRAM_DRAM_START //0x3FC7C000
//cache not available from DRAM (!)
#define DRAM0_SRAM_LEVEL_0_LOW DRAM_SRAM_START //0x3FC7C000
#define DRAM0_SRAM_LEVEL_0_HIGH (DRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x3FC7FFFF
//128kB
@ -291,7 +346,9 @@ static inline uint32_t memprot_ll_dram0_get_intr_source_num(void)
}
/* SPLIT LINE */
///////////////////////////////////
// DRAM0 - SPLIT LINES
///////////////////////////////////
static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg)
{
@ -309,7 +366,7 @@ static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32
category[2] = 0x2;
}
//category bits are the same for all areas
//NOTE: line address & category bits, shifts and masks are the same for all the 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) |
@ -332,12 +389,25 @@ 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)
static inline void* memprot_ll_get_dram0_split_line_D_0(void)
{
REG_WRITE(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG, lock ? 1 : 0);
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG), SOC_DIRAM_DRAM_LOW);
}
static inline void* memprot_ll_get_dram0_split_line_D_1(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG), SOC_DIRAM_DRAM_LOW);
}
///////////////////////////////////
// DRAM0 - PMS CONFIGURATION
///////////////////////////////////
// lock
static inline void memprot_ll_dram0_set_pms_lock(void)
{
REG_WRITE(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG, 1);
}
static inline bool memprot_ll_dram0_get_pms_lock(void)
@ -345,6 +415,7 @@ static inline bool memprot_ll_dram0_get_pms_lock(void)
return REG_READ(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_0_REG) == 1;
}
// permission settings
static inline uint32_t memprot_ll_dram0_set_permissions(bool r, bool w)
{
uint32_t permissions = 0;
@ -378,12 +449,44 @@ 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)
static inline void memprot_ll_dram0_get_permissions(uint32_t perms, bool *r, bool *w )
{
REG_WRITE(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG, lock ? 1 : 0);
*r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
*w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
}
static inline void memprot_ll_dram0_get_pms_area_0(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0);
memprot_ll_dram0_get_permissions( permissions, r, w);
}
static inline void memprot_ll_dram0_get_pms_area_1(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1);
memprot_ll_dram0_get_permissions( permissions, r, w);
}
static inline void memprot_ll_dram0_get_pms_area_2(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2);
memprot_ll_dram0_get_permissions( permissions, r, w);
}
static inline void memprot_ll_dram0_get_pms_area_3(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3);
memprot_ll_dram0_get_permissions( permissions, r, w);
}
///////////////////////////////////
// DRAM0 - MONITOR
///////////////////////////////////
// lock
static inline void memprot_ll_dram0_set_monitor_lock(void)
{
REG_WRITE(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG, 1);
}
static inline bool memprot_ll_dram0_get_monitor_lock(void)
@ -391,6 +494,7 @@ static inline bool memprot_ll_dram0_get_monitor_lock(void)
return REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_0_REG) == 1;
}
// interrupt enable/clear
static inline void memprot_ll_dram0_set_monitor_en(bool enable)
{
if ( enable ) {
@ -406,18 +510,29 @@ static inline bool memprot_ll_dram0_get_monitor_en(void)
}
static inline void memprot_ll_dram0_clear_monitor_intr(void)
{
REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR );
}
static inline void memprot_ll_dram0_reset_clear_monitor_intr(void)
{
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_enable_register(void)
{
return REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG);
}
// permission violation status
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 );
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR );
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_lock(void)
{
return REG_GET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK );
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK );
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_world(void)
@ -427,19 +542,29 @@ static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_world(void)
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 );
uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + DRAM0_ADDRESS_LOW : 0;
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_wr(void)
{
return REG_GET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_byte_en(void)
{
return REG_GET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN );
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN );
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_register_1(void)
{
return REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG);
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_register_2(void)
{
return REG_READ(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG);
}
#ifdef __cplusplus
}

View File

@ -26,10 +26,12 @@ extern "C" {
//IRAM0 interrupt status bitmasks
#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1
#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1
#define CONF_REG_ADDRESS_SHIFT 2
static inline void esp_memprot_iram0_clear_intr(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR);
}
static inline uint32_t esp_memprot_iram0_get_intr_source_num(void)
@ -104,6 +106,7 @@ static inline uint32_t esp_memprot_iram0_get_lock_bit(void)
* === IRAM0 SRAM
* ========================================================================================
*/
#define IRAM0_SRAM_BASE_ADDRESS 0x40000000
#define IRAM0_SRAM_ADDRESS_LOW 0x40020000
#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF
@ -126,6 +129,7 @@ static inline uint32_t esp_memprot_iram0_get_lock_bit(void)
#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address
#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant
#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S)
static inline uint32_t *esp_memprot_iram0_sram_get_fault_address(void)
{
@ -290,6 +294,7 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw
{
uint32_t addr = (uint32_t)split_addr;
assert(addr <= IRAM0_SRAM_SPL_BLOCK_HIGH);
assert(addr % 0x4 == 0);
//find possible split.address in low region blocks
int uni_blocks_low = -1;
@ -339,11 +344,7 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw
uint32_t reg_split_addr = 0;
if (addr >= IRAM0_SRAM_SPL_BLOCK_LOW) {
//[16:0]
reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr &= DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_M;
reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG( addr ); //cfg reg - [16:0]
}
//prepare high & low permission mask (bits: [22:20] high range, [19:17] low range)
@ -406,9 +407,11 @@ static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx)
* === IRAM0 RTC FAST
* ========================================================================================
*/
#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000
#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF
#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant)
#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000
#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF
#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant)
#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S)
static inline uint32_t *esp_memprot_iram0_rtcfast_get_fault_address(void)
@ -434,14 +437,10 @@ static inline uint32_t esp_memprot_iram0_rtcfast_get_perm_split_reg(void)
static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx)
{
uint32_t addr = (uint32_t)split_addr;
assert( addr % 0x4 == 0 );
//if splt.ddr not set yet, do required normalization to make the addr writeble into splt.mgmt cfg register
uint32_t reg_split_addr = 0;
//[10:0]
reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr &= DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_M;
//conf reg [10:0]
uint32_t reg_split_addr = IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr);
//prepare high & low permission mask (bits: [16:14] high range, [13:11] low range)
uint32_t permission_mask = 0;
@ -531,6 +530,7 @@ static inline bool esp_memprot_dram0_is_assoc_intr(void)
static inline void esp_memprot_dram0_clear_intr(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR);
}
static inline uint32_t esp_memprot_dram0_get_intr_ena_bit(void)
@ -606,6 +606,8 @@ static inline void esp_memprot_dram0_get_fault_op_type(uint32_t *op_type, uint32
#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high
#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant
#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S)
static inline uint32_t *esp_memprot_dram0_sram_get_fault_address(void)
{
@ -716,6 +718,7 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw
//low boundary check provided by LD script. see comment in esp_memprot_iram0_sram_set_prot()
assert( addr <= DRAM0_SRAM_SPL_BLOCK_HIGH );
assert( addr % 0x4 == 0 );
//set low region
int uni_blocks_low = -1;
@ -753,10 +756,8 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw
}
}
//[24:8]
uint32_t reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr = (reg_split_addr & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_V) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S;
//conf reg [24:8]
uint32_t reg_split_addr = DRAM0_SRAM_ADDR_TO_CONF_REG(addr);
//prepare high & low permission mask
uint32_t permission_mask = 0;
@ -803,9 +804,10 @@ static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw)
* === DRAM0 RTC FAST
* ========================================================================================
*/
#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000
#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF
#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant
#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000
#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF
#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant
#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S)
static inline uint32_t *esp_memprot_dram0_rtcfast_get_fault_address(void)
@ -826,11 +828,10 @@ static inline bool esp_memprot_dram0_rtcfast_is_intr_mine(void)
static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr)
{
uint32_t addr = (uint32_t)split_addr;
assert( addr % 0x4 == 0 );
//[10:0]
uint32_t reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr &= DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_M;
//conf reg [10:0]
uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG( addr );
//prepare high & low permission mask
uint32_t permission_mask = 0;

View File

@ -31,9 +31,11 @@ extern "C" {
#define PERI1_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg)
#define PERI1_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address)
static inline void esp_memprot_peri1_clear_intr(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR);
}
static inline uint32_t esp_memprot_peri1_get_intr_source_num(void)
@ -116,6 +118,7 @@ static inline uint32_t esp_memprot_peri1_get_lock_bit(void)
#define PERI1_RTCSLOW_ADDRESS_HIGH PERI1_RTCSLOW_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE
#define PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 0x3F400000
#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S)
static inline uint32_t *esp_memprot_peri1_rtcslow_get_fault_address(void)
{
@ -137,11 +140,9 @@ static inline bool esp_memprot_peri1_rtcslow_is_intr_mine(void)
static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr)
{
uint32_t addr = (uint32_t)split_addr;
assert( addr % 0x4 == 0 );
//check split address is WORD aligned
uint32_t reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr &= DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_M;
uint32_t reg_split_addr = PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr);
//prepare high & low permission mask
uint32_t permission_mask = 0;
@ -201,6 +202,7 @@ static inline uint32_t esp_memprot_peri1_rtcslow_get_conf_reg(void)
static inline void esp_memprot_peri2_clear_intr(void)
{
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR);
}
static inline uint32_t esp_memprot_peri2_get_intr_source_num(void)
@ -286,6 +288,8 @@ static inline uint32_t *esp_memprot_peri2_rtcslow_get_fault_address(void)
#define PERI2_RTCSLOW_0_ADDRESS_LOW PERI2_RTCSLOW_0_ADDRESS_BASE
#define PERI2_RTCSLOW_0_ADDRESS_HIGH PERI2_RTCSLOW_0_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE
#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S)
static inline bool esp_memprot_peri2_rtcslow_0_is_intr_mine(void)
{
if (esp_memprot_peri2_is_assoc_intr()) {
@ -298,11 +302,9 @@ static inline bool esp_memprot_peri2_rtcslow_0_is_intr_mine(void)
static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx)
{
uint32_t addr = (uint32_t)split_addr;
assert( addr % 0x4 == 0 );
//check split address is WORD aligned
uint32_t reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr &= DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_M;
uint32_t reg_split_addr = PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr);
//prepare high & low permission mask
uint32_t permission_mask = 0;
@ -371,6 +373,7 @@ static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void)
#define PERI2_RTCSLOW_1_ADDRESS_LOW PERI2_RTCSLOW_1_ADDRESS_BASE
#define PERI2_RTCSLOW_1_ADDRESS_HIGH PERI2_RTCSLOW_1_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE
#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S)
static inline bool esp_memprot_peri2_rtcslow_1_is_intr_mine(void)
{
@ -384,11 +387,9 @@ static inline bool esp_memprot_peri2_rtcslow_1_is_intr_mine(void)
static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx)
{
uint32_t addr = (uint32_t)split_addr;
assert( addr % 0x4 == 0 );
//check split address is WORD aligned
uint32_t reg_split_addr = addr >> 2;
assert(addr == (reg_split_addr << 2));
reg_split_addr &= DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_M;
uint32_t reg_split_addr = PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr);
//prepare high & low permission mask
uint32_t permission_mask = 0;

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.5)
if(IDF_TARGET STREQUAL "esp32s2")
if((IDF_TARGET STREQUAL "esp32s2") OR (IDF_TARGET STREQUAL "esp32c3"))
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(test_memprot)

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32-S2 |
| ----------------- | -------- |
| Supported Targets | ESP32-S2 | ESP32-C3 |
| ----------------- | -------- | -------- |

View File

@ -3,7 +3,7 @@
import ttfw_idf
from tiny_test_fw import Utility
mem_test = [
MEM_TEST_S2 = [
['IRAM0_SRAM', 'WRX'],
['IRAM0_RTCFAST', 'WRX'],
['DRAM0_SRAM', 'WR'],
@ -13,14 +13,29 @@ mem_test = [
['PERI2_RTCSLOW_1', 'WRX']
]
MEM_TEST_C3 = [
['IRAM0_SRAM', 'WRX'],
['DRAM0_SRAM', 'WR']
]
@ttfw_idf.idf_custom_test(env_tag='Example_GENERIC', target='esp32s2', group='test-apps')
@ttfw_idf.idf_custom_test(env_tag='Example_GENERIC', target=['esp32c3', 'esp32s2'], group='test-apps')
def test_memprot(env, extra_data):
dut = env.get_dut('memprot', 'tools/test_apps/system/memprot')
dut.start_app()
for i in mem_test:
mem_test_cfg = []
current_target = dut.app.get_sdkconfig()['CONFIG_IDF_TARGET'].replace('"','').lower()
if current_target == 'esp32c3':
mem_test_cfg = MEM_TEST_C3
elif current_target == 'esp32s2':
mem_test_cfg = MEM_TEST_S2
Utility.console_log('Test cfg: ' + current_target)
for i in mem_test_cfg:
if 'R' in i[1]:
dut.expect(i[0] + ' read low: OK')
dut.expect(i[0] + ' read high: OK')

View File

@ -1,2 +1,7 @@
idf_component_register(SRCS "test_memprot_main.c" "test_panic.c"
if( IDF_TARGET STREQUAL "esp32s2" )
idf_component_register(SRCS "esp32s2/test_memprot_main.c" "esp32s2/test_panic.c"
INCLUDE_DIRS "")
elseif( IDF_TARGET STREQUAL "esp32c3" )
idf_component_register(SRCS "esp32c3/test_memprot_main.c" "esp32c3/test_panic.c" "esp32c3/return_from_panic.S"
INCLUDE_DIRS "")
endif()

View File

@ -0,0 +1,4 @@
config ESP_SYSTEM_MEMPROT_IRAM_TESTBUF
bool
default y if IDF_TARGET_ESP32C3
default n if !IDF_TARGET_ESP32C3

View File

@ -0,0 +1,71 @@
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "riscv/rvruntime-frames.h"
/* The riscv panic handler in components/riscv/vectors.S doesn't allow the panic
handler function to return.
However, for the purposes of this test we want to allow the panic handler to return.
There is functionality in vectors.S restore the CPU state, but it only
restores when CONTEXT_SIZE registers are
pushed onto the stack not RV_STK_FRMSZ registers
Instead of messing with that, implement a full "restore from RvExcFrame"
function here which restores the CPU and then
returns from exception.
Called as return_from_panic_handler(RvExcFrame *frame)
*/
.global return_from_panic_handler
return_from_panic_handler:
or t0, a0, a0 /* use t0 as the working register */
/* save general registers */
lw ra, RV_STK_RA(t0)
lw sp, RV_STK_SP(t0)
lw gp, RV_STK_GP(t0)
lw tp, RV_STK_TP(t0)
lw s0, RV_STK_S0(t0)
lw s1, RV_STK_S1(t0)
lw a0, RV_STK_A0(t0)
lw a1, RV_STK_A1(t0)
lw a2, RV_STK_A2(t0)
lw a3, RV_STK_A3(t0)
lw a4, RV_STK_A4(t0)
lw a5, RV_STK_A5(t0)
lw a6, RV_STK_A6(t0)
lw a7, RV_STK_A7(t0)
lw s2, RV_STK_S2(t0)
lw s3, RV_STK_S3(t0)
lw s4, RV_STK_S4(t0)
lw s5, RV_STK_S5(t0)
lw s6, RV_STK_S6(t0)
lw s7, RV_STK_S7(t0)
lw s8, RV_STK_S8(t0)
lw s9, RV_STK_S9(t0)
lw s10, RV_STK_S10(t0)
lw s11, RV_STK_S11(t0)
lw t3, RV_STK_T3(t0)
lw t4, RV_STK_T4(t0)
lw t5, RV_STK_T5(t0)
lw t6, RV_STK_T6(t0)
lw t2, RV_STK_MEPC(t0)
csrw mepc, t2
lw t1, RV_STK_T1(t0)
lw t2, RV_STK_T2(t0)
lw t0, RV_STK_T0(t0)
mret

View File

@ -0,0 +1,392 @@
/* MEMPROT (PMS) testing code */
#include <stdio.h>
#include "sdkconfig.h"
#include "esp32c3/memprot.h"
#include "esp_rom_sys.h"
#include <string.h>
/**
* ESP32C3 MEMORY PROTECTION MODULE TEST
* =====================================
*
* In order to safely test all the memprot features, this test application uses memprot default settings
* plus proprietary testing buffers:
* - iram_test_buffer (.iram_end_test, 1kB) - all low region operations
* - dram_test_buffer (.dram0.data, 1kB) - all high region operations
* Testing addresses are set to the middle of the testing buffers:
* - test_ptr_low = iram_test_buffer + 0x200
* - test_ptr_high = dram_test_buffer + 0x200
* Each operation is tested at both low & high region addresses.
* Each test result checked against expected status of PMS violation interrupt status and
* against expected value stored in the memory tested (where applicable)
*
* Testing scheme is depicted below:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
* | DRam0_PMS_0 |
* | |
* | |
* | - - - - - - - iram_test_buffer - - - - - - -| IRam0_line1_Split_addr
* DRam0_DMA_line0_Split_addr | -- test_ptr_low -- | =
* = =============================================== IRam0_line0_Split_addr
* DRam0_DMA_line1_Split_addr | | =
* | - - - - - - - dram_test_buffer - - - - - - -| IRam0_DRam0_Split_addr (main I/D)
* | -- test_ptr_high -- |
* | - - - - - - - - - - - - - - - - - - - - - - |
* | |
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 |
* | IRam0_PMS_3 |
* -----------------------------------------------
*
* For more details on PMS memprot settings see 'esp_memprot_set_prot_int' function in esp32c3/memprot.h
*/
/* Binary code for the following asm [int func(int x) { return x+x; }]
slli a0,a0,0x1
ret
*/
static uint8_t fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 };
typedef int (*fnc_ptr)(int);
#define SRAM_TEST_BUFFER_SIZE 0x400
#define SRAM_TEST_OFFSET 0x200
static uint8_t __attribute__((section(".iram_end_test"))) iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
extern volatile bool g_override_illegal_instruction;
static void *test_memprot_addr_low(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return (void*)((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_SRAM:
return (void*)MAP_IRAM_TO_DRAM((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
default:
abort();
}
}
static void *test_memprot_addr_high(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return (void*)MAP_DRAM_TO_IRAM((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_SRAM:
return (void*)((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
default:
abort();
}
}
static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_type)
{
char operation = 0;
// IRAM fault: check instruction-fetch flag
if ( mem_type == MEMPROT_IRAM0_SRAM ) {
if ( esp_memprot_get_violate_loadstore(mem_type) ) {
operation = 'X';
}
}
// W/R - common
if ( operation == 0 ) {
operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R';
}
esp_rom_printf(
" FAULT [ world: %u, fault addr: 0x%08X, operation: %c",
esp_memprot_get_violate_world(mem_type),
esp_memprot_get_violate_addr(mem_type),
operation
);
// DRAM/DMA fault: check byte-enables
if ( mem_type == MEMPROT_DRAM0_SRAM ) {
esp_rom_printf( ", byte en: 0x%08X", esp_memprot_get_violate_byte_en(mem_type) );
}
esp_rom_printf( " ]\n" );
}
static void check_test_result(mem_type_prot_t mem_type, bool expected_status)
{
bool test_result =
expected_status ?
!esp_memprot_get_violate_intr_on(mem_type) :
esp_memprot_get_violate_intr_on(mem_type);
if ( test_result ) {
esp_rom_printf("OK\n");
} else {
dump_status_register(mem_type);
}
}
static void test_memprot_get_permissions(bool low, mem_type_prot_t mem_type, bool *read, bool *write, bool *exec )
{
bool _r, _w, _x;
pms_area_t area = MEMPROT_PMS_AREA_NONE;
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
area = low ? MEMPROT_IRAM0_PMS_AREA_2 : MEMPROT_IRAM0_PMS_AREA_3;
esp_memprot_iram_get_pms_area(area, &_r, &_w, &_x);
break;
case MEMPROT_DRAM0_SRAM:
area = low ? MEMPROT_DRAM0_PMS_AREA_0 : MEMPROT_DRAM0_PMS_AREA_1;
esp_memprot_dram_get_pms_area(area, &_r, &_w);
break;
default:
abort();
}
if ( read ) {
*read = _r;
}
if ( write ) {
*write = _w;
}
if ( exec ) {
*exec = _x;
}
}
static void test_memprot_set_permissions(bool low, mem_type_prot_t mem_type, bool read, bool write, bool *exec)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM: {
bool _ex;
if (!exec) {
test_memprot_get_permissions( low, mem_type, NULL, NULL, &_ex);
exec = &_ex;
}
if (low) {
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, read, write, *exec);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, read, write, *exec);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, read, write, *exec);
} else {
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, read, write, *exec);
}
}
break;
case MEMPROT_DRAM0_SRAM: {
if (low) {
esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, read, write );
} else {
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, read, write);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, read, write);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, read, write);
}
}
break;
default:
abort();
}
}
static void test_memprot_read(mem_type_prot_t mem_type)
{
//get current READ & WRITE permission settings
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
//get testing pointers for low & high regions
volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
const uint32_t test_val = 100;
//temporarily allow WRITE for setting the test values
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, read_perm_low, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
test_memprot_set_permissions(false, mem_type, read_perm_high, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
*ptr_low = test_val;
*ptr_high = test_val + 1;
test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
esp_memprot_set_monitor_en(mem_type, true);
//perform READ test in low region
esp_rom_printf("%s read low: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
volatile uint32_t val = *ptr_low;
if ( read_perm_low && val != test_val ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val );
dump_status_register(mem_type);
} else {
check_test_result(mem_type, read_perm_low);
}
//perform READ in high region
esp_rom_printf("%s read high: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
val = *ptr_high;
if ( read_perm_high && val != (test_val + 1) ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
} else {
check_test_result(mem_type, read_perm_high);
}
}
static void test_memprot_write(mem_type_prot_t mem_type)
{
//get current READ & WRITE permission settings
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, NULL);
test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, NULL);
//ensure READ enabled
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, true, write_perm_low, NULL);
test_memprot_set_permissions(false, mem_type, true, write_perm_high, NULL);
esp_memprot_set_monitor_en(mem_type, true);
//get testing pointers for low & high regions
volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
const uint32_t test_val = 10;
//perform WRITE in low region
esp_rom_printf("%s write low: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
volatile uint32_t val = 0;
*ptr_low = test_val;
val = *ptr_low;
if ( val != test_val && write_perm_low ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
} else {
check_test_result(mem_type, write_perm_low);
}
//perform WRITE in high region
esp_rom_printf("%s write high: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
val = 0;
*ptr_high = test_val + 1;
val = *ptr_high;
if ( val != (test_val + 1) && write_perm_high ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
} else {
check_test_result(mem_type, write_perm_high);
}
//restore original permissions
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, true, read_perm_low, NULL);
test_memprot_set_permissions(false, mem_type, true, read_perm_high, NULL);
esp_memprot_set_monitor_en(mem_type, true);
}
static void test_memprot_exec(mem_type_prot_t mem_type)
{
if ( mem_type != MEMPROT_IRAM0_SRAM ) {
esp_rom_printf("Error: EXEC test available only for IRAM access.\n" );
return;
}
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
//temporarily enable READ/WRITE
test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low);
test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high);
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, true, true, &exec_perm_low);
test_memprot_set_permissions(false, mem_type, true, true, &exec_perm_high);
esp_memprot_set_monitor_en(mem_type, true);
//get testing pointers for low & high regions, zero 8B slot
void *fnc_ptr_low = test_memprot_addr_low(mem_type);
void *fnc_ptr_high = test_memprot_addr_high(mem_type);
memset( fnc_ptr_low, 0, 8);
memset( fnc_ptr_high, 0, 8);
//inject the code to both low & high segments
memcpy( (void *)fnc_ptr_low, (const void *)fnc_buff, sizeof(fnc_buff) );
memcpy( (void *)fnc_ptr_high, (const void *)fnc_buff, sizeof(fnc_buff) );
uint32_t res = 0;
//LOW REGION: clear the intr flag & try to execute the code injected
esp_rom_printf("%s exec low: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
fnc_ptr fnc = (fnc_ptr)fnc_ptr_low;
g_override_illegal_instruction = true;
res = fnc( 5 );
g_override_illegal_instruction = false;
//check results
bool fnc_call_ok = res == 10;
if ( fnc_call_ok ) {
check_test_result(mem_type, exec_perm_low);
} else {
if ( !exec_perm_low ) {
check_test_result(mem_type, false);
} else {
esp_rom_printf(" FAULT [injected code not executed]\n");
}
}
//HIGH REGION: clear the intr-on flag & try to execute the code injected
esp_rom_printf("%s exec high: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
fnc = (fnc_ptr)fnc_ptr_high;
g_override_illegal_instruction = true;
res = fnc( 6 );
g_override_illegal_instruction = false;
fnc_call_ok = res == 12;
if ( fnc_call_ok ) {
check_test_result(mem_type, exec_perm_high);
} else {
if ( !exec_perm_high ) {
check_test_result(mem_type, false);
} else {
esp_rom_printf(" FAULT [injected code not executed]\n");
}
}
//restore original permissions
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low);
test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high);
esp_memprot_set_monitor_en(mem_type, true);
}
/* ********************************************************************************************
* main test runner
*/
void app_main(void)
{
esp_memprot_set_prot_int(false, false, NULL, NULL);
test_memprot_read(MEMPROT_IRAM0_SRAM);
test_memprot_write(MEMPROT_IRAM0_SRAM);
test_memprot_exec(MEMPROT_IRAM0_SRAM);
test_memprot_read(MEMPROT_DRAM0_SRAM);
test_memprot_write(MEMPROT_DRAM0_SRAM);
}

View File

@ -0,0 +1,52 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 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.
#include "riscv/rvruntime-frames.h"
#include "esp_private/panic_internal.h"
#define MCAUSE_ILLEGAL_INSTRUCTION 2
extern void esp_panic_handler(panic_info_t *info);
volatile bool g_override_illegal_instruction = false;
void __real_esp_panic_handler(panic_info_t *info);
void return_from_panic_handler(RvExcFrame *frm) __attribute__((noreturn));
/* Memprot test specific IllegalInstruction exception handler:
* when testing the protection against a code execution, sample code
* is being injected into various memory regions which produces
* Illegal instruction on execution attempt. Such a result is expected
* but it causes system reboot in the standard panic handler.
* The following variant of panic handling simply returns back to the
* next instruction and continues normal execution.
*
* NOTE: if Illegal instruction comes from a different source than the testing code
* the behavior is undefined
* */
void __wrap_esp_panic_handler(panic_info_t *info)
{
RvExcFrame *frm = (RvExcFrame *)info->frame;
if ( frm->mcause == MCAUSE_ILLEGAL_INSTRUCTION && g_override_illegal_instruction == true ) {
/* Return from exception to the return address that called the faulting function.
*/
frm->mepc = frm->ra;
/* Restore the CPU state and return from the exception.
*/
return_from_panic_handler(frm);
} else {
__real_esp_panic_handler(info);
}
}

View File

@ -10,51 +10,53 @@
* ESP32S2 MEMORY PROTECTION MODULE TEST
* =====================================
*
* In order to safely test all the mem_prot features, this test uses a proprietary setting
* for all splitting addresses, ie it partially overrides production settings.
* Each operation is tested at [test-splitting-addr - 16B] (low region) and
* [test-splitting-addr + 16B] (high region). Complete testing scheme
* is depicted below, the addresses used come from this application binary:
* In order to safely test all the mem_prot features configuration, this test uses a combination of
* proprietary settings and ESP-IDF defaults.
* Each operation is tested at both low region and high region testing address.
* Complete testing scheme is depicted below:
*
* ********************************************************************************************
*
* IRAM0 SRAM (320kB) DRAM0
* ===========================
* (_iram_text_end) | | (_data_start)
* 0x4002B51C(!) <-------- real splt.addr --------> 0x3FFBB520
* | |
* 0x4002DA30 <---|-------------------------|--> 0x3FFBDA30
* | test buffer (64 kB) |
* | ... |
* 0x40035A30 <-------- test splt.addr --------> 0x3FFC5A30
* |-------------------------|
* | iram_test_buffer (1kB) |
* <---------- test addr low -------> iram_test_buffer + 0x200
* | |
* _iram_text_end <======== real splt.addr ========> _data_start (real splt.addr == test splt.addr)
* | |
* <---|-------------------------|-->
* | dram_test_buffer (1kB) |
* <--------- test addr high -------> dram_test_buffer + 0x200
* | ... |
* |-------------------------|
* | |
* ===========================
*
* RTC_FAST (8kB)
* (_rtc_text_end) =========================== (_rtc_dummy_end)
* 0x40070000 <-------- real splt.addr --------> 0x3FF9E000
* | |
* | test buffer (7 kB) |
* | ... |
* 0x40070E00 <-------- test splt.addr --------> 0x3FF9EE00
* | ... |
* ===========================
* _rtc_text_end <======== real splt.addr ========> _rtc_dummy_end
* | rtcfast_dummy_buffer |
* | (2kB) |
* <---------- test addr low -------> test_buffer - 0x200
* <-------- test splt.addr --------> test_buffer = rtcfast_dummy_buffer / 2
* <---------- test addr low -------> test_buffer + 0x200
* |-------------------------|
* | |
* ===========================
*
* ********************************************************************************************
*
* PERIBUS_1 RTC_SLOW (8/768kB) PERIBUS_2_0 PERIBUS_2_1
* PERIBUS_1 RTC_SLOW (8/768kB) PERIBUS_2_0 PERIBUS_2_1
* ===========================
* | |
* 0x3F421000 <-------- real splt.addr --------> 0x50000000 0x60021000
* | |
* | test buffer (7 kB) |
* | ... |
* 0x3F421E00 <-------- test splt.addr --------> 0x50000E00 0x60021E00
* | ... |
* 0x3F421000 <======== real splt.addr ========> 0x50000000 0x60021000
* | rtcslow_dummy_buffer |
* | (2kB) |
* <---------- test addr low -------> test_buffer - 0x200
* <-------- test splt.addr --------> test_buffer = rtcslow_dummy_buffer / 2
* <---------- test addr low -------> test_buffer + 0x200
* |-------------------------|
* | |
* ===========================
@ -90,39 +92,30 @@
*/
static uint8_t fnc_call0_buff[] = {0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00};
#define SRAM_DUMMY_BUFFER_SIZE 64*1024
#define RTCFAST_DUMMY_BUFFER_SIZE 7*1024
#define RTCSLOW_DUMMY_BUFFER_SIZE 7*1024
volatile bool g_override_illegal_instruction = false;
static uint8_t sram_dummy_buffer[SRAM_DUMMY_BUFFER_SIZE] = {0};
static uint8_t RTC_FAST_ATTR rtcfast_dummy_buffer[RTCFAST_DUMMY_BUFFER_SIZE] = {0};
static uint8_t RTC_SLOW_ATTR rtcslow_dummy_buffer[RTCSLOW_DUMMY_BUFFER_SIZE] = {0};
#define MAP_DRAM_TO_IRAM(addr) (addr - SOC_DIRAM_DRAM_LOW + SOC_DIRAM_IRAM_LOW)
#define MAP_IRAM_TO_DRAM(addr) (addr - SOC_DIRAM_IRAM_LOW + SOC_DIRAM_DRAM_LOW)
#define SRAM_TEST_BUFFER_SIZE 0x400
#define SRAM_TEST_OFFSET 0x200
static uint8_t __attribute__((section(".iram_end_test"))) iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t RTC_FAST_ATTR rtcfast_dummy_buffer[2 * SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t RTC_SLOW_ATTR rtcslow_dummy_buffer[2 * SRAM_TEST_BUFFER_SIZE] = {0};
/* ********************************************************************************************
* testing regions and splitting address scheme
*
*/
static uint32_t *test_memprot_dram0_sram_get_min_split_addr(void)
{
return (uint32_t *)(sram_dummy_buffer + sizeof(sram_dummy_buffer) / 2);
}
static uint32_t *test_memprot_dram0_rtcfast_get_min_split_addr(void)
{
return (uint32_t *)(rtcfast_dummy_buffer + sizeof(rtcfast_dummy_buffer) / 2);
}
static uint32_t *test_memprot_iram0_sram_get_min_split_addr(void)
{
return (uint32_t *)
((uint32_t)test_memprot_dram0_sram_get_min_split_addr() +
+ esp_memprot_get_low_limit(MEMPROT_IRAM0_SRAM)
- esp_memprot_get_low_limit(MEMPROT_DRAM0_SRAM));
}
static uint32_t *test_memprot_iram0_rtcfast_get_min_split_addr(void)
{
return (uint32_t *)
@ -152,13 +145,58 @@ static uint32_t *test_memprot_peri2_rtcslow_1_get_min_split_addr(void)
- esp_memprot_get_low_limit(MEMPROT_PERI2_RTCSLOW_0));
}
static uint32_t *test_memprot_addr_low(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return (uint32_t *)((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_SRAM:
return (uint32_t *)MAP_IRAM_TO_DRAM((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_IRAM0_RTCFAST:
return (uint32_t *)((uint32_t)test_memprot_iram0_rtcfast_get_min_split_addr() - SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_RTCFAST:
return (uint32_t *)((uint32_t)test_memprot_dram0_rtcfast_get_min_split_addr() - SRAM_TEST_OFFSET);
case MEMPROT_PERI1_RTCSLOW:
return (uint32_t *)((uint32_t)test_memprot_peri1_rtcslow_get_min_split_addr() - SRAM_TEST_OFFSET);
case MEMPROT_PERI2_RTCSLOW_0:
return (uint32_t *)((uint32_t)test_memprot_peri2_rtcslow_0_get_min_split_addr() - SRAM_TEST_OFFSET);
case MEMPROT_PERI2_RTCSLOW_1:
return (uint32_t *)((uint32_t)test_memprot_peri2_rtcslow_1_get_min_split_addr() - SRAM_TEST_OFFSET);
default:
abort();
}
}
static uint32_t *test_memprot_addr_high(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return (uint32_t *)MAP_DRAM_TO_IRAM((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_SRAM:
return (uint32_t *)((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_IRAM0_RTCFAST:
return (uint32_t *)((uint32_t)test_memprot_iram0_rtcfast_get_min_split_addr() + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_RTCFAST:
return (uint32_t *)((uint32_t)test_memprot_dram0_rtcfast_get_min_split_addr() + SRAM_TEST_OFFSET);
case MEMPROT_PERI1_RTCSLOW:
return (uint32_t *)((uint32_t)test_memprot_peri1_rtcslow_get_min_split_addr() + SRAM_TEST_OFFSET);
case MEMPROT_PERI2_RTCSLOW_0:
return (uint32_t *)((uint32_t)test_memprot_peri2_rtcslow_0_get_min_split_addr() + SRAM_TEST_OFFSET);
case MEMPROT_PERI2_RTCSLOW_1:
return (uint32_t *)((uint32_t)test_memprot_peri2_rtcslow_1_get_min_split_addr() + SRAM_TEST_OFFSET);
default:
abort();
}
}
static uint32_t *test_memprot_get_split_addr(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
return test_memprot_iram0_sram_get_min_split_addr();
return esp_memprot_get_split_addr(MEMPROT_IRAM0_SRAM);
case MEMPROT_DRAM0_SRAM:
return test_memprot_dram0_sram_get_min_split_addr();
return esp_memprot_get_split_addr(MEMPROT_DRAM0_SRAM);
case MEMPROT_IRAM0_RTCFAST:
return test_memprot_iram0_rtcfast_get_min_split_addr();
case MEMPROT_DRAM0_RTCFAST:
@ -218,25 +256,25 @@ static void test_memprot_set_prot(uint32_t *mem_type_mask, bool use_panic_handle
//set permissions
if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, test_memprot_iram0_sram_get_min_split_addr(), true, true, true, true, true, false);
esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_IRAM0_RTCFAST) {
esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, test_memprot_iram0_rtcfast_get_min_split_addr(), false, true, true, true, true, false);
esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, test_memprot_iram0_rtcfast_get_min_split_addr(), WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, test_memprot_dram0_sram_get_min_split_addr(), true, true, true, true);
esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA);
}
if (required_mem_prot & MEMPROT_DRAM0_RTCFAST) {
esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, test_memprot_dram0_rtcfast_get_min_split_addr(), false, true, true, true);
esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, test_memprot_dram0_rtcfast_get_min_split_addr(), WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA);
}
if (required_mem_prot & MEMPROT_PERI1_RTCSLOW) {
esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, test_memprot_peri1_rtcslow_get_min_split_addr(), true, true, true, true);
esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, test_memprot_peri1_rtcslow_get_min_split_addr(), WR_LOW_DIS, RD_LOW_DIS, RD_HIGH_DIS, WR_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_0) {
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, test_memprot_peri2_rtcslow_0_get_min_split_addr(), true, true, false, true, true, false);
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, test_memprot_peri2_rtcslow_0_get_min_split_addr(), WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS);
}
if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_1) {
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, test_memprot_peri2_rtcslow_1_get_min_split_addr(), true, true, false, true, true, false);
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, test_memprot_peri2_rtcslow_1_get_min_split_addr(), WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS);
}
//reenable protection (bus based)
@ -304,23 +342,25 @@ static void test_memprot_read(mem_type_prot_t mem_type)
{
//get current READ & WRITE permission settings
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
esp_memprot_get_perm_read(mem_type, &write_perm_low, &write_perm_high);
esp_memprot_get_perm_write(mem_type, &write_perm_low, &write_perm_high);
esp_memprot_get_perm_read(mem_type, &read_perm_low, &read_perm_high);
//get current splitting address
volatile uint32_t *ptr = test_memprot_get_split_addr(mem_type);
volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
//temporarily allow WRITE for setting the test values
const uint32_t test_val = 100;
esp_memprot_set_write_perm(mem_type, true, true);
*(ptr - 4) = test_val;
*(ptr + 4) = test_val + 1;
const uint32_t test_val = 100;
*ptr_low = test_val;
*ptr_high = test_val + 1;
esp_memprot_set_write_perm(mem_type, write_perm_low, write_perm_high);
//perform READ in low region
esp_rom_printf("%s read low: ", esp_memprot_type_to_str(mem_type));
esp_memprot_clear_intr(mem_type);
volatile uint32_t val = *(ptr - 4);
volatile uint32_t val = *ptr_low;
if ( val != 0 && val != test_val ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val );
dump_status_register(mem_type);
@ -331,7 +371,7 @@ static void test_memprot_read(mem_type_prot_t mem_type)
//perform read in high region
esp_rom_printf("%s read high: ", esp_memprot_type_to_str(mem_type));
esp_memprot_clear_intr(mem_type);
val = *(ptr + 4);
val = *ptr_high;
if ( val != 0 && val != (test_val + 1) ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
@ -344,14 +384,14 @@ static void test_memprot_write(mem_type_prot_t mem_type)
{
//get current READ & WRITE permission settings
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
esp_memprot_get_perm_read(mem_type, &write_perm_low, &write_perm_high);
esp_memprot_get_perm_write(mem_type, &write_perm_low, &write_perm_high);
esp_memprot_get_perm_read(mem_type, &read_perm_low, &read_perm_high);
//temporarily allow READ operation
esp_memprot_set_read_perm(mem_type, true, true);
//get current splitting address
volatile uint32_t *ptr = test_memprot_get_split_addr(mem_type);
volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
//perform WRITE in low region
const uint32_t test_val = 10;
@ -359,8 +399,8 @@ static void test_memprot_write(mem_type_prot_t mem_type)
esp_memprot_clear_intr(mem_type);
volatile uint32_t val = 0;
*(ptr - 4) = test_val;
val = *(ptr - 4);
*ptr_low = test_val;
val = *ptr_low;
if ( val != test_val && write_perm_low ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
@ -373,8 +413,8 @@ static void test_memprot_write(mem_type_prot_t mem_type)
esp_rom_printf("%s write high: ", esp_memprot_type_to_str(mem_type));
esp_memprot_clear_intr(mem_type);
val = 0;
*(ptr + 4) = test_val + 1;
val = *(ptr + 4);
*ptr_high = test_val + 1;
val = *ptr_high;
if ( val != (test_val + 1) && write_perm_high ) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
@ -382,6 +422,8 @@ static void test_memprot_write(mem_type_prot_t mem_type)
} else {
check_test_result(mem_type, write_perm_high);
}
esp_memprot_set_read_perm(mem_type, read_perm_low, read_perm_high);
}
static void test_memprot_exec(mem_type_prot_t mem_type)
@ -394,8 +436,8 @@ static void test_memprot_exec(mem_type_prot_t mem_type)
bool exec_perm_low, exec_perm_high;
esp_memprot_get_perm_exec(mem_type, &exec_perm_low, &exec_perm_high);
volatile uint32_t *fnc_ptr_low = (uint32_t *)(test_memprot_get_split_addr(mem_type) - 4);
volatile uint32_t *fnc_ptr_high = (uint32_t *)(test_memprot_get_split_addr(mem_type) + 4);
volatile uint32_t *fnc_ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *fnc_ptr_high = test_memprot_addr_high(mem_type);
//enable WRITE permission for both segments
esp_memprot_set_write_perm(mem_type, true, true);
@ -423,7 +465,7 @@ static void test_memprot_exec(mem_type_prot_t mem_type)
check_test_result(mem_type, exec_perm_low);
} else {
if ( !exec_perm_low ) {
check_test_result(mem_type, true);
check_test_result(mem_type, false);
} else {
esp_rom_printf(" FAULT [injected code not executed]\n");
}
@ -442,14 +484,13 @@ static void test_memprot_exec(mem_type_prot_t mem_type)
check_test_result(mem_type, exec_perm_high);
} else {
if ( !exec_perm_high ) {
check_test_result(mem_type, true);
check_test_result(mem_type, false);
} else {
esp_rom_printf(" FAULT [injected code not executed]\n");
}
}
}
/* ********************************************************************************************
* main test runner
*/

View File

@ -1,5 +1,5 @@
# Esp32S2 only
CONFIG_IDF_TARGET="esp32s2"
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
# Disable automatic memory protection
CONFIG_ESP32S2_MEMPROT_FEATURE=n
# IDF-3090
CONFIG_ESP32C3_REV_MIN_0=y
CONFIG_ESP32C3_REV_MIN=0