1 /*
2  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /////////////////////////////////////////////////////////////////////////////////////////
8 // ESP Memory Protection API (PMS)
9 // - allows configuration and violation-interrupt handling of the PMS module operations
10 // - not intended for public use.
11 
12 #pragma once
13 
14 #include "sdkconfig.h"
15 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST
16 
17 #include <stdbool.h>
18 #include <stdint.h>
19 #include "esp_err.h"
20 #include "esp_memprot_err.h"
21 #include "soc_memprot_types.h"
22 #include "esp_memprot_types.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 #define ESP_MEMPROT_ERR_CHECK(retval, fnc) if ((retval=fnc) != ESP_OK) { return retval; }
29 
30 /**
31 * @brief Basic PMS interrupt source info
32 */
33 typedef struct {
34     esp_mprot_mem_t mem_type;   /*!< Memory type containing the faulting address  */
35     int core;                   /*!< CPU/Core ID running the faulting instruction  */
36 } esp_memp_intr_source_t;
37 
38 /**
39  * @brief Clears current interrupt ON flag for given Memory type and CPU/Core ID
40  *
41  * This operation is non-atomic for some chips by PMS module design
42  * In such a case the interrupt clearing happens in two steps:
43  *      1. Interrupt CLR flag is set (clears interrupt-ON status and inhibits linked interrupt processing)
44  *      2. Interrupt CLR flag is reset (resumes the interrupt monitoring)
45  *
46  * @param mem_type Memory type (see esp_mprot_mem_t enum)
47  * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
48  *
49  * @return ESP_OK on success
50  *         ESP_ERR_INVALID_ARG on passing invalid pointer
51  *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
52  */
53 esp_err_t esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core);
54 
55 /**
56  * @brief Checks whether any of the PMS settings is locked
57  *
58  * @param[out] locked Any lock on? (true/false)
59  *
60  * @return ESP_OK on success
61  *         ESP_ERR_INVALID_ARG on invalid locked ptr
62  *         Other failures: error code of any failing esp_mprot_get_*_lock() routine (called internally)
63  */
64 esp_err_t esp_mprot_is_conf_locked_any(bool *locked);
65 
66 /**
67  * @brief Checks whether any PMS violation-interrupt monitoring is enabled
68  *
69  * @param[out] locked Any PMS violation interrupt monitor is enabled (true/false)
70  *
71  * @return ESP_OK on success
72  *         ESP_ERR_INVALID_ARG on invalid enabled ptr
73  *         Other failures: error code of esp_mprot_get_monitor_en() routine (called internally for all Memory types)
74  */
75 esp_err_t esp_mprot_is_intr_ena_any(bool *enabled);
76 
77 /**
78  * @brief Returns active PMS violation-interrupt Memory type if any (MEMPROT_TYPE_NONE when none detected)
79  * and the CPU/CoreID which was running the faulty code (-1 when no interrupt available)
80  *
81  * If there are more interrupts indicated on (shouldn't happen), the order of precedence is given by 'esp_mprot_mem_t' enum definition (low->high)
82  *
83  * @param[out] mem_type Out-pointer for Memory type given by the faulting address (see esp_mprot_mem_t enum)
84  * @param[out] core Out-pointer for CPU/Core ID (see *_CPU_NUM defs in soc.h)
85  *
86  * @return ESP_OK on success
87  *         ESP_ERR_INVALID_ARG on passing invalid pointer(s)
88  */
89 esp_err_t esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr);
90 
91 /**
92  * @brief Returns the address which caused the violation interrupt for given Memory type and CPU/Core ID.
93  * This function is to be called after a basic resolving of (current) interrupt's parameters (ie corresponding
94  * Memory type and CPU ID see esp_mprot_get_active_intr()). This is to minimize processing time of actual exception
95  * as this API is typicaly used in a panic-handling code.
96  * If there is no active interrupt available for the Memory type/CPU ID required, fault_addr is set to NULL.
97  *
98  * @param mem_type memory type
99  * @param[out] fault_addr Address of the operation which caused the PMS violation interrupt
100  * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
101  *
102  * @return ESP_OK on success
103  *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
104  *         ESP_ERR_INVALID_ARG on invalid fault_addr pointer
105  */
106 esp_err_t esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core);
107 
108 /**
109  * @brief Returns PMS World identifier of the code causing the violation interrupt
110  *
111  * The value is read from appropriate PMS violation status register and thus might be 0 if the interrupt is not currently active.
112  *
113  * @param mem_type Memory type
114  * @param[out] world PMS World type (see esp_mprot_pms_world_t)
115  * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
116  *
117  * @return ESP_OK on success
118  *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
119  *         ESP_ERR_INVALID_ARG on passing invalid pointer(s)
120  *         ESP_ERR_MEMPROT_WORLD_INVALID on invalid World identifier fetched from the register
121  */
122 esp_err_t esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core);
123 
124 /**
125  * @brief Returns an operation type which caused the violation interrupt
126  *
127  * The operation resolving is processed over various PMS status register flags, according to given Memory type argument.
128  * If the interrupt is not active the result returned is irrelevant (likely evaluated to MEMPROT_OP_READ).
129  *
130  * @param mem_type Memory type
131  * @param[out] oper Operation type (see MEMPROT_OP_* defines)
132  * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
133  *
134  * @return ESP_OK on success
135  *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
136  *         ESP_ERR_INVALID_ARG on invalid oper pointer
137  */
138 esp_err_t esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core);
139 
140 /**
141  * @brief Checks whether given memory type supports byte-enables info
142  *
143  * Byte-enables status is available only for DMA/DRAM operations
144   *
145  * @param mem_type memory type
146  *
147  * @return byte-enables info available true/false
148  */
149 bool esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type);
150 
151 /**
152  * @brief Returns byte-enables for the address which caused the violation interrupt
153  *
154  * The value is taken from appropriate PMS violation status register, based on given Memory type
155  *
156  * @param mem_type Memory type (MEMPROT_TYPE_DRAM0_SRAM)
157  * @param[out] byte_en Byte-enables bits
158  * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
159  *
160  * @return ESP_OK on success
161  *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
162  *         ESP_ERR_INVALID_ARGUMENT on invalid byte_en pointer
163  */
164 esp_err_t esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core);
165 
166 /**
167  * @brief Convenient routine for setting the PMS defaults
168  *
169  * Called on system startup, depending on ESP_SYSTEM_MEMPROT_FEATURE Kconfig value
170  *
171  * @param memp_config pointer to Memprot configuration structure (esp_memp_config_t). The structure si chip-specific,
172  * for details and defaults see appropriate [target-chip]/soc_memprot_types.h
173  *
174  * @return ESP_OK on success
175  *         Other failures: error code of the failing routine called internally. No specific error processing provided in such a case
176  *         due to large number of embedded calls (ie no global unique error table is provided and thus one error code can have different meanings,
177  *         depending on the routine issuing the error)
178  */
179 esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config);
180 
181 /**
182  * @brief Generates PMS configuration string of actual device (diagnostics)
183  *
184  * The functions generates a string from current configuration, control and status registers of the PMS (or similar) module of actual device.
185  * The values are fetched using HAL LL calls to help finding possible errors in the Memprot API implementation
186  *
187  * @param[out] dump_info_string configuration string buffer pointer. The string is allocated by the callee and must be freed by the caller.
188  *
189  * @return ESP_OK on success
190  *         ESP_ERR_NO_MEM on buffer allocation failure
191  *         ESP_ERR_INVALID_ARGUMENT on invalid dump_info_string pointer
192  */
193 esp_err_t esp_mprot_dump_configuration(char **dump_info_string);
194 
195 #ifdef __cplusplus
196 }
197 #endif
198 
199 #endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST
200