| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- /*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /* INTERNAL API
- * generic interface to PMS memory protection features
- */
- #pragma once
- #include <stdbool.h>
- #include <stdint.h>
- #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
- *
- * @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);
- /**
- * @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
|