1 /*
2  * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 //////////////////////////////////////////////////////////
8 // ESP32-S3 PMS memory protection types
9 //
10 
11 #pragma once
12 
13 #include <stdint.h>
14 #include <stdbool.h>
15 #include "soc/soc.h"
16 #include "freertos/FreeRTOSConfig.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /**
23  * @brief Memory types recognized by PMS
24  */
25 typedef enum {
26     MEMPROT_TYPE_NONE                           = 0x00000000,
27     MEMPROT_TYPE_IRAM0_SRAM                     = 0x00000001,
28     MEMPROT_TYPE_DRAM0_SRAM                     = 0x00000002,
29     MEMPROT_TYPE_IRAM0_RTCFAST                  = 0x00000004,
30     MEMPROT_TYPE_ALL                            = 0x7FFFFFFF,
31     MEMPROT_TYPE_INVALID                        = 0x80000000,
32     MEMPROT_TYPE_IRAM0_ANY                      = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_IRAM0_RTCFAST
33 } esp_mprot_mem_t;
34 
35 /**
36  * @brief Splitting address (line) type
37  */
38 typedef enum {
39     MEMPROT_SPLIT_ADDR_NONE                     = 0x00000000,
40     MEMPROT_SPLIT_ADDR_IRAM0_DRAM0              = 0x00000001,
41     MEMPROT_SPLIT_ADDR_IRAM0_LINE_0             = 0x00000002,
42     MEMPROT_SPLIT_ADDR_IRAM0_LINE_1             = 0x00000004,
43     MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0         = 0x00000008,
44     MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1         = 0x00000010,
45     MEMPROT_SPLIT_ADDR_ALL                      = 0x7FFFFFFF,
46     MEMPROT_SPLIT_ADDR_INVALID                  = 0x80000000,
47     MEMPROT_SPLIT_ADDR_MAIN                     = MEMPROT_SPLIT_ADDR_IRAM0_DRAM0
48 } esp_mprot_split_addr_t;
49 
50 /**
51  * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
52  */
53 typedef enum {
54     MEMPROT_PMS_AREA_NONE                       = 0x00000000,
55     MEMPROT_PMS_AREA_IRAM0_0                    = 0x00000001,
56     MEMPROT_PMS_AREA_IRAM0_1                    = 0x00000002,
57     MEMPROT_PMS_AREA_IRAM0_2                    = 0x00000004,
58     MEMPROT_PMS_AREA_IRAM0_3                    = 0x00000008,
59     MEMPROT_PMS_AREA_DRAM0_0                    = 0x00000010,
60     MEMPROT_PMS_AREA_DRAM0_1                    = 0x00000020,
61     MEMPROT_PMS_AREA_DRAM0_2                    = 0x00000040,
62     MEMPROT_PMS_AREA_DRAM0_3                    = 0x00000080,
63     MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO           = 0x00000100,
64     MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI           = 0x00000200,
65     MEMPROT_PMS_AREA_ICACHE_0                   = 0x00000400,
66     MEMPROT_PMS_AREA_ICACHE_1                   = 0x00000800,
67     MEMPROT_PMS_AREA_ALL                        = 0x7FFFFFFF,
68     MEMPROT_PMS_AREA_INVALID                    = 0x80000000
69 } esp_mprot_pms_area_t;
70 
71 /**
72 * @brief Memory protection configuration
73 */
74 typedef struct {
75     bool invoke_panic_handler;          /*!< Register PMS violation interrupt for panic-handling */
76     bool lock_feature;                  /*!< Lock all PMS settings */
77     void *split_addr;                   /*!< Main I/D splitting address */
78     uint32_t mem_type_mask;             /*!< Memory types required to protect. See esp_mprot_mem_t enum */
79     size_t target_cpu_count;            /*!< Real CPU/core count (max 2) */
80     int target_cpu[portNUM_PROCESSORS];  /*!< Array of CPU/core IDs required to receive given PMS protection */
81 } esp_memp_config_t;
82 
83 //2-CPU configuration
84 #if portNUM_PROCESSORS > 1
85 
86 //default IDF configuration (basic memory regions, split line detection, locked, panic mode on)
87 #define ESP_MEMPROT_DEFAULT_CONFIG() { \
88     .invoke_panic_handler = true, \
89     .lock_feature = true, \
90     .split_addr = NULL, \
91     .mem_type_mask = MEMPROT_TYPE_ALL, \
92     .target_cpu_count = 2, \
93     .target_cpu = {PRO_CPU_NUM, APP_CPU_NUM} \
94 }
95 //zero (no-go) configuration
96 #define ESP_MEMPROT_ZERO_CONFIG() { \
97     .target_cpu_count = 2, \
98     .target_cpu = {PRO_CPU_NUM, APP_CPU_NUM} \
99 }
100 
101 #else //1-CPU configuration
102 
103 #define ESP_MEMPROT_DEFAULT_CONFIG() { \
104     .invoke_panic_handler = true, \
105     .lock_feature = true, \
106     .split_addr = NULL, \
107     .mem_type_mask = MEMPROT_TYPE_ALL, \
108     .target_cpu_count = 1, \
109     .target_cpu = {PRO_CPU_NUM} \
110 }
111 #define ESP_MEMPROT_ZERO_CONFIG() { \
112     .target_cpu_count = 1, \
113     .target_cpu = {PRO_CPU_NUM} \
114 }
115 
116 #endif //end of CPU-count based defines
117 
118 /**
119  * @brief Converts Memory protection type to string
120  *
121  * @param mem_type Memory protection type
122  */
esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)123 static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
124 {
125     switch (mem_type) {
126     case MEMPROT_TYPE_NONE:
127         return "NONE";
128     case MEMPROT_TYPE_IRAM0_SRAM:
129         return "IRAM0_SRAM";
130     case MEMPROT_TYPE_DRAM0_SRAM:
131         return "DRAM0_SRAM";
132     case MEMPROT_TYPE_IRAM0_RTCFAST:
133         return "IRAM0_RTCFAST";
134     case MEMPROT_TYPE_IRAM0_ANY:
135         return "IRAM0_ANY";
136     case MEMPROT_TYPE_ALL:
137         return "ALL";
138     default:
139         return "INVALID";
140     }
141 }
142 
143 /**
144  * @brief Converts Splitting address type to string
145  *
146  * @param line_type Split line type
147  */
esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)148 static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
149 {
150     switch (line_type) {
151     case MEMPROT_SPLIT_ADDR_NONE:
152         return "SPLIT_ADDR_NONE";
153     case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
154         return "SPLIT_ADDR_IRAM0_DRAM0";
155     case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
156         return "SPLIT_ADDR_IRAM0_LINE_0";
157     case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
158         return "SPLIT_ADDR_IRAM0_LINE_1";
159     case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
160         return "SPLIT_ADDR_DRAM0_DMA_LINE_0";
161     case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
162         return "SPLIT_ADDR_DRAM0_DMA_LINE_1";
163     case MEMPROT_SPLIT_ADDR_ALL:
164         return "SPLIT_ADDR_ALL";
165     default:
166         return "SPLIT_ADDR_INVALID";
167     }
168 }
169 
170 /**
171  * @brief Converts PMS Area type to string
172  *
173  * @param area_type PMS Area type
174  */
esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)175 static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
176 {
177     switch (area_type) {
178     case MEMPROT_PMS_AREA_NONE:
179         return "PMS_AREA_NONE";
180     case MEMPROT_PMS_AREA_IRAM0_0:
181         return "PMS_AREA_IRAM0_0";
182     case MEMPROT_PMS_AREA_IRAM0_1:
183         return "PMS_AREA_IRAM0_1";
184     case MEMPROT_PMS_AREA_IRAM0_2:
185         return "PMS_AREA_IRAM0_2";
186     case MEMPROT_PMS_AREA_IRAM0_3:
187         return "PMS_AREA_IRAM0_3";
188     case MEMPROT_PMS_AREA_DRAM0_0:
189         return "PMS_AREA_DRAM0_0";
190     case MEMPROT_PMS_AREA_DRAM0_1:
191         return "PMS_AREA_DRAM0_1";
192     case MEMPROT_PMS_AREA_DRAM0_2:
193         return "PMS_AREA_DRAM0_2";
194     case MEMPROT_PMS_AREA_DRAM0_3:
195         return "PMS_AREA_DRAM0_3";
196     case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
197         return "PMS_AREA_IRAM0_RTCFAST_LO";
198     case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
199         return "PMS_AREA_IRAM0_RTCFAST_HI";
200     case MEMPROT_PMS_AREA_ICACHE_0:
201         return "PMS_AREA_ICACHE_0";
202     case MEMPROT_PMS_AREA_ICACHE_1:
203         return "PMS_AREA_ICACHE_1";
204     case MEMPROT_PMS_AREA_ALL:
205         return "PMS_AREA_ALL";
206     default:
207         return "PMS_AREA_INVALID";
208     }
209 }
210 
211 #ifdef __cplusplus
212 }
213 #endif
214