memprot.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /* INTERNAL API
  7. * generic interface to PMS memory protection features
  8. */
  9. #pragma once
  10. #include <stdbool.h>
  11. #include <stdint.h>
  12. #include "esp_attr.h"
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. #ifndef IRAM_SRAM_START
  17. #define IRAM_SRAM_START 0x4037C000
  18. #endif
  19. #ifndef DRAM_SRAM_START
  20. #define DRAM_SRAM_START 0x3FC7C000
  21. #endif
  22. typedef enum {
  23. MEMPROT_NONE = 0x00000000,
  24. MEMPROT_IRAM0_SRAM = 0x00000001,
  25. MEMPROT_DRAM0_SRAM = 0x00000002,
  26. MEMPROT_ALL = 0xFFFFFFFF
  27. } mem_type_prot_t;
  28. typedef enum {
  29. MEMPROT_SPLITLINE_NONE = 0,
  30. MEMPROT_IRAM0_DRAM0_SPLITLINE,
  31. MEMPROT_IRAM0_LINE_0_SPLITLINE,
  32. MEMPROT_IRAM0_LINE_1_SPLITLINE,
  33. MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
  34. MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE
  35. } split_line_t;
  36. typedef enum {
  37. MEMPROT_PMS_AREA_NONE = 0,
  38. MEMPROT_IRAM0_PMS_AREA_0,
  39. MEMPROT_IRAM0_PMS_AREA_1,
  40. MEMPROT_IRAM0_PMS_AREA_2,
  41. MEMPROT_IRAM0_PMS_AREA_3,
  42. MEMPROT_DRAM0_PMS_AREA_0,
  43. MEMPROT_DRAM0_PMS_AREA_1,
  44. MEMPROT_DRAM0_PMS_AREA_2,
  45. MEMPROT_DRAM0_PMS_AREA_3
  46. } pms_area_t;
  47. typedef enum
  48. {
  49. MEMPROT_PMS_WORLD_0 = 0,
  50. MEMPROT_PMS_WORLD_1,
  51. MEMPROT_PMS_WORLD_2,
  52. MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
  53. } pms_world_t;
  54. typedef enum
  55. {
  56. MEMPROT_PMS_OP_READ = 0,
  57. MEMPROT_PMS_OP_WRITE,
  58. MEMPROT_PMS_OP_FETCH,
  59. MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
  60. } pms_operation_type_t;
  61. /**
  62. * @brief Converts Memory protection type to string
  63. *
  64. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  65. */
  66. const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
  67. /**
  68. * @brief Converts Split line type to string
  69. *
  70. * @param line_type Split line type (see split_line_t enum)
  71. */
  72. const char *esp_memprot_split_line_to_str(split_line_t line_type);
  73. /**
  74. * @brief Converts PMS Area type to string
  75. *
  76. * @param area_type PMS Area type (see pms_area_t enum)
  77. */
  78. const char *esp_memprot_pms_to_str(pms_area_t area_type);
  79. /**
  80. * @brief Returns PMS splitting address for given Split line type
  81. *
  82. * The value is taken from PMS configuration registers (IRam0 range)
  83. * For details on split lines see 'esp_memprot_set_prot_int' function description
  84. *
  85. * @param line_type Split line type (see split_line_t enum)
  86. *
  87. * @return appropriate split line address
  88. */
  89. uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
  90. /**
  91. * @brief Returns default main IRAM/DRAM splitting address
  92. *
  93. * The address value is given by _iram_text_end global (IRam0 range)
  94. * @return Main I/D split line (IRam0_DRam0_Split_Addr)
  95. */
  96. void *esp_memprot_get_default_main_split_addr(void);
  97. /**
  98. * @brief Sets a lock for the main IRAM/DRAM splitting address
  99. *
  100. * Locks can be unlocked only by digital system reset
  101. */
  102. void esp_memprot_set_split_line_lock(void);
  103. /**
  104. * @brief Gets a lock status for the main IRAM/DRAM splitting address
  105. *
  106. * @return true/false (locked/unlocked)
  107. */
  108. bool esp_memprot_get_split_line_lock(void);
  109. /**
  110. * @brief Sets required split line address
  111. *
  112. * @param line_type Split line type (see split_line_t enum)
  113. * @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
  114. */
  115. void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
  116. /**
  117. * @brief Sets a lock for PMS Area settings of required Memory type
  118. *
  119. * Locks can be unlocked only by digital system reset
  120. *
  121. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  122. */
  123. void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
  124. /**
  125. * @brief Gets a lock status for PMS Area settings of required Memory type
  126. *
  127. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  128. *
  129. * @return true/false (locked/unlocked)
  130. */
  131. bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
  132. /**
  133. * @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
  134. *
  135. * @param area_type IRam0 PMS Area type (see pms_area_t enum)
  136. * @param r Read permission flag
  137. * @param w Write permission flag
  138. * @param x Execute permission flag
  139. */
  140. void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
  141. /**
  142. * @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
  143. *
  144. * @param area_type IRam0 PMS Area type (see pms_area_t enum)
  145. * @param r Read permission flag holder
  146. * @param w Write permission flag holder
  147. * @param x Execute permission flag holder
  148. */
  149. void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
  150. /**
  151. * @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
  152. *
  153. * @param area_type DRam0 PMS Area type (see pms_area_t enum)
  154. * @param r Read permission flag
  155. * @param w Write permission flag
  156. */
  157. void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
  158. /**
  159. * @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
  160. *
  161. * @param area_type DRam0 PMS Area type (see pms_area_t enum)
  162. * @param r Read permission flag holder
  163. * @param w Write permission flag holder
  164. */
  165. void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
  166. /**
  167. * @brief Sets a lock for PMS interrupt monitor settings of required Memory type
  168. *
  169. * Locks can be unlocked only by digital system reset
  170. *
  171. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  172. */
  173. void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
  174. /**
  175. * @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
  176. *
  177. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  178. *
  179. * @return true/false (locked/unlocked)
  180. */
  181. bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
  182. /**
  183. * @brief Enable PMS violation interrupt monitoring of required Memory type
  184. *
  185. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  186. * @param enable/disable
  187. */
  188. void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
  189. /**
  190. * @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
  191. *
  192. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  193. *
  194. * @return true/false (enabled/disabled)
  195. */
  196. bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
  197. /**
  198. * @brief Gets CPU ID for currently active PMS violation interrupt
  199. *
  200. * @return CPU ID (CPU_PRO for ESP32-C2)
  201. */
  202. int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
  203. /**
  204. * @brief Clears current interrupt ON flag for given Memory type
  205. *
  206. * Interrupt clearing happens in two steps:
  207. * 1. Interrupt CLR flag is set (to clear the interrupt ON status)
  208. * 2. Interrupt CLR flag is reset (to allow further monitoring)
  209. * This operation is non-atomic by PMS module design
  210. *
  211. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  212. */
  213. void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
  214. /**
  215. * @brief Returns active PMS violation interrupt (if any)
  216. *
  217. * This function iterates through supported Memory type status registers
  218. * and returns the first interrupt-on flag. If none is found active,
  219. * MEMPROT_NONE is returned.
  220. * Order of checking (in current version):
  221. * 1. MEMPROT_IRAM0_SRAM
  222. * 2. MEMPROT_DRAM0_SRAM
  223. *
  224. * @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
  225. */
  226. mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
  227. /**
  228. * @brief Checks whether any violation interrupt is active
  229. *
  230. * @return true/false (yes/no)
  231. */
  232. bool IRAM_ATTR esp_memprot_is_locked_any(void);
  233. /**
  234. * @brief Checks whether any violation interrupt is enabled
  235. *
  236. * @return true/false (yes/no)
  237. */
  238. bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
  239. /**
  240. * @brief Checks whether any violation interrupt is enabled
  241. *
  242. * @return true/false (yes/no)
  243. */
  244. bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
  245. /**
  246. * @brief Returns the address which caused the violation interrupt (if any)
  247. *
  248. * The address is taken from appropriate PMS violation status register, based given Memory type
  249. *
  250. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  251. *
  252. * @return faulting address
  253. */
  254. uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
  255. /**
  256. * @brief Returns the World identifier of the code causing the violation interrupt (if any)
  257. *
  258. * The value is taken from appropriate PMS violation status register, based given Memory type
  259. *
  260. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  261. *
  262. * @return World identifier (see pms_world_t enum)
  263. */
  264. pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
  265. /**
  266. * @brief Returns Read or Write operation type which caused the violation interrupt (if any)
  267. *
  268. * The value (bit) is taken from appropriate PMS violation status register, based given Memory type
  269. *
  270. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  271. *
  272. * @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
  273. */
  274. pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
  275. /**
  276. * @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
  277. *
  278. * The value (bit) is taken from appropriate PMS violation status register, based given Memory type
  279. * Effective only on IRam0 access
  280. *
  281. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  282. *
  283. * @return true/false (LoadStore bit on/off)
  284. */
  285. bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
  286. /**
  287. * @brief Returns byte-enables for the address which caused the violation interrupt (if any)
  288. *
  289. * The value is taken from appropriate PMS violation status register, based given Memory type
  290. *
  291. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  292. *
  293. * @return byte-enables
  294. */
  295. uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
  296. /**
  297. * @brief Returns raw contents of DRam0 status register 1
  298. *
  299. * @return 32-bit register value
  300. */
  301. uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
  302. /**
  303. * @brief Returns raw contents of DRam0 status register 2
  304. *
  305. * @return 32-bit register value
  306. */
  307. uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
  308. /**
  309. * @brief Returns raw contents of IRam0 status register
  310. *
  311. * @return 32-bit register value
  312. */
  313. uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
  314. /**
  315. * @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
  316. *
  317. * Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
  318. * The registration makes the panic-handler routine being called when the interrupt appears
  319. *
  320. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  321. */
  322. void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
  323. /**
  324. * @brief Convenient routine for setting the PMS defaults
  325. *
  326. * Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
  327. * For implementation details see 'esp_memprot_set_prot_int' description
  328. *
  329. * @param invoke_panic_handler register all interrupts for panic handling (true/false)
  330. * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
  331. * @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
  332. */
  333. void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
  334. /**
  335. * @brief Internal routine for setting the PMS defaults
  336. *
  337. * Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
  338. * (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
  339. * is used (&_iram_text_end) and all the remaining lines share the same address.
  340. * The function sets all the split lines and PMS areas to the same space,
  341. * ie there is a single instruction space and single data space at the end.
  342. * The PMS split lines and permission areas scheme described below:
  343. *
  344. * DRam0/DMA IRam0
  345. * -----------------------------------------------
  346. * ... | IRam0_PMS_0 |
  347. * DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr
  348. * ... | IRam0_PMS_1 |
  349. * ... ----------------------------------------------- IRam0_line0_Split_addr
  350. * | IRam0_PMS_2 |
  351. * =============================================== IRam0_DRam0_Split_addr (main I/D)
  352. * | DRam0_PMS_1 |
  353. * DRam0_DMA_line0_Split_addr ----------------------------------------------- ...
  354. * | DRam0_PMS_2 | ...
  355. * DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3
  356. * | DRam0_PMS_3 | ...
  357. * -----------------------------------------------
  358. *
  359. * Default settings provided by 'esp_memprot_set_prot_int' are as follows:
  360. *
  361. * DRam0/DMA IRam0
  362. * -----------------------------------------------
  363. * | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
  364. * | DRam0_PMS_0 | IRam0_line1_Split_addr
  365. * DRam0_DMA_line0_Split_addr | | =
  366. * = =============================================== IRam0_line0_Split_addr
  367. * DRam0_DMA_line1_Split_addr | | =
  368. * | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D)
  369. * | IRam0_PMS_3 |
  370. * -----------------------------------------------
  371. *
  372. * Once the memprot feature is locked, it can be unlocked only by digital system reset
  373. *
  374. * @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
  375. * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
  376. * @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
  377. * @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
  378. */
  379. void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
  380. /**
  381. * @brief Returns raw contents of PMS interrupt monitor register for given Memory type
  382. *
  383. * @param mem_type Memory protection type (see mem_type_prot_t enum)
  384. *
  385. * @return 32-bit register value
  386. */
  387. uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
  388. #ifdef __cplusplus
  389. }
  390. #endif