memprot.h 15 KB

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