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