mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
ec01a66557
@ -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
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-S2 |
|
||||
| ----------------- | -------- |
|
||||
| Supported Targets | ESP32-S2 | ESP32-C3 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
@ -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')
|
||||
|
@ -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()
|
||||
|
4
tools/test_apps/system/memprot/main/Kconfig.projbuild
Normal file
4
tools/test_apps/system/memprot/main/Kconfig.projbuild
Normal file
@ -0,0 +1,4 @@
|
||||
config ESP_SYSTEM_MEMPROT_IRAM_TESTBUF
|
||||
bool
|
||||
default y if IDF_TARGET_ESP32C3
|
||||
default n if !IDF_TARGET_ESP32C3
|
@ -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
|
392
tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c
Normal file
392
tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c
Normal 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);
|
||||
}
|
52
tools/test_apps/system/memprot/main/esp32c3/test_panic.c
Normal file
52
tools/test_apps/system/memprot/main/esp32c3/test_panic.c
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user