core_feature_pma.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright (c) 2019 Nuclei Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #ifndef __CORE_FEATURE_PMA_H__
  19. #define __CORE_FEATURE_PMA_H__
  20. /*!
  21. * @file core_feature_pma.h
  22. * @brief Physical memory attribute feature API header file
  23. */
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. #include "core_compatiable.h"
  28. #if defined(__PMA_PRESENT) && (__PMA_PRESENT==1)
  29. /* ===== PMA functions ===== */
  30. /**
  31. * \defgroup NMSIS_Core_PMA_Functions PMA Functions
  32. * \ingroup NMSIS_Core
  33. * \brief Functions that set/disable/enable different attribute type(Device/Non-Cacheable/Cacheable) memory regions, or get region info.
  34. * \details
  35. * Nuclei provide Physical Memory Attribute(PMA) to define the attribute of memory.PMA will affect CPU access memory behavior.
  36. *
  37. * PMA are split into three attributes:
  38. * * Device(abbreviated as 'DEV') Attribute
  39. * * Non-Cacheable(abbreviated as 'NC') Attribute
  40. * * Cacheable(abbreviated as 'CA') Attribute
  41. * And correspondingly, the whole memory region are split into three regions: DEV Region/NC Region/CA Region
  42. *
  43. * Hardware provide some software CSR to set the pma by mattri(n)_base/mattri(n)_mask/sattri(n)_base/sattri(n)_mask
  44. *
  45. * Hardware defined PMA regions(up to 8 DEV/NC/CA regions) can be disable or enable by CSR mmacro_dev_en/mmacro_noc_en/mmacro_ca_en
  46. * @{
  47. */
  48. #define PMA_REGION_TYPE_SECSHARE (1UL << 3) /*!< Set this region shareable between secure world and non-secure world, or else default is invalid */
  49. #define PMA_REGION_TYPE_NC (1UL << 2) /*!< Set this region Non-Cacheable, or else default is invalid */
  50. #define PMA_REGION_TYPE_DEV (1UL << 1) /*!< Set this region Device, or else default is invalid */
  51. #define PMA_REGION_TYPE_CA (0) /*!< Set this region Cacheable, which is default */
  52. #define PMA_REGION_ENA (1UL << 0) /*!< Enable this region, then the region type will take effect */
  53. #define PMA_REGION_DIS (0) /*!< Disable this region */
  54. typedef struct PMA_CONFIG {
  55. /**
  56. * Base physical address, which needs to be 4K byte aligned
  57. */
  58. unsigned long region_base;
  59. /**
  60. * Region size, which needs to be 4K byte aligned; the \ref region_base should be aligined by \ref region_size
  61. */
  62. unsigned long region_size;
  63. /**
  64. * Type could be \ref PMA_REGION_TYPE_SECSHARE, \ref PMA_REGION_TYPE_NC, \ref PMA_REGION_TYPE_DEV, \ref PMA_REGION_TYPE_CA
  65. * \ref PMA_REGION_TYPE_SECSHARE could be combined with one of \ref PMA_REGION_TYPE_NC \ref PMA_REGION_TYPE_DEV \ref PMA_REGION_TYPE_CA
  66. * such as \ref PMA_REGION_TYPE_SECSHARE | \ref PMA_REGION_TYPE_NC
  67. * Reserved for sattri(n)_base
  68. */
  69. uint16_t region_type;
  70. /**
  71. * Enable or disable the region, could be \ref PMA_REGION_ENA, \ref PMA_REGION_DIS
  72. */
  73. uint16_t region_enable;
  74. } pma_config;
  75. /**
  76. * \brief Configure one region in machine mode
  77. * \details Set the region(0-n) info of base address/region type/region size/enable status
  78. * \param [in] entry_idx Index(0-n) of paired mattri(n)_mask and mattri(n)_base
  79. * \param [in] pma_cfg Region info to configure
  80. * \return -1 failure, else 0 success
  81. * \remarks
  82. * - The entry_idx(0-n) depends on number of paired mattri(n)_mask and mattri(n)_base, refer to
  83. Nuclei ISA specifications
  84. * - Not all the entry_idx(0-n) could set to all the types freely, refer to Nuclei ISA specifications
  85. * - The mattri(n)_mask must be written first, before mattri(n)_base, which the api takes care of.
  86. * - The higher bits of mattri(n)_mask should be continuously 1, the remaining lower bits should be all 0
  87. * and the number (N) of 0 means the size of this region(2^N bytes)
  88. * - Region granularity is 4KB, so the low 12-bits of mattri(n)_mask must be 0, which the api takes care of
  89. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  90. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  91. */
  92. __STATIC_INLINE long PMA_SetRegion(unsigned long entry_idx, pma_config *pma_cfg)
  93. {
  94. // 4KB aligned
  95. unsigned long size = (pma_cfg->region_size >> 12) << 12;
  96. unsigned long base_addr = (pma_cfg->region_base >> 12) << 12;
  97. if ((entry_idx + 1) > __PMA_CSR_NUM) {
  98. return -1;
  99. }
  100. rv_csr_t mask = (unsigned long)(~(size - 1));
  101. rv_csr_t base = pma_cfg->region_type | base_addr | pma_cfg->region_enable;
  102. switch (entry_idx) {
  103. // Bit[MXLEN-1:PA_SIZE] of mattri(n)_mask is reserved 0
  104. case 0: __RV_CSR_WRITE(CSR_MATTRI0_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI0_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI0_BASE, base); break;
  105. case 1: __RV_CSR_WRITE(CSR_MATTRI1_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI1_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI1_BASE, base); break;
  106. case 2: __RV_CSR_WRITE(CSR_MATTRI2_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI2_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI2_BASE, base); break;
  107. case 3: __RV_CSR_WRITE(CSR_MATTRI3_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI3_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI3_BASE, base); break;
  108. case 4: __RV_CSR_WRITE(CSR_MATTRI4_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI4_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI4_BASE, base); break;
  109. case 5: __RV_CSR_WRITE(CSR_MATTRI5_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI5_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI5_BASE, base); break;
  110. case 6: __RV_CSR_WRITE(CSR_MATTRI6_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI6_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI6_BASE, base); break;
  111. case 7: __RV_CSR_WRITE(CSR_MATTRI7_BASE, 0); __RV_CSR_WRITE(CSR_MATTRI7_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI7_BASE, base); break;
  112. default: return -1;
  113. }
  114. __FENCE_I();
  115. return 0;
  116. }
  117. /**
  118. * \brief Get the region info in machine mode
  119. * \details Read the region(0-n) info of base address/region type/region size/enable status
  120. * \param [in] entry_idx Index(0-n) of paired mattri(n)_mask and mattri(n)_base
  121. * \param [out] pma_cfg Region info read
  122. * \return 0 if success, else -1
  123. * \remarks
  124. * - entry_idx(0-n) depends on number of paired mattri(n)_mask and mattri(n)_base, refer to
  125. Nuclei ISA specifications
  126. * - Not all the entry_idx(0-n) could set to all the types freely, refer to Nuclei ISA specifications
  127. */
  128. __STATIC_INLINE long PMA_GetRegion(unsigned long entry_idx, pma_config *pma_cfg)
  129. {
  130. rv_csr_t mask, base;
  131. uint32_t mpasize = *(uint32_t *)__IINFO_MPASIZE_ADDR;
  132. if ((entry_idx + 1) > __PMA_CSR_NUM) {
  133. return -1;
  134. }
  135. switch (entry_idx) {
  136. case 0: mask = __RV_CSR_READ(CSR_MATTRI0_MASK); base = __RV_CSR_READ(CSR_MATTRI0_BASE); break;
  137. case 1: mask = __RV_CSR_READ(CSR_MATTRI1_MASK); base = __RV_CSR_READ(CSR_MATTRI1_BASE); break;
  138. case 2: mask = __RV_CSR_READ(CSR_MATTRI2_MASK); base = __RV_CSR_READ(CSR_MATTRI2_BASE); break;
  139. case 3: mask = __RV_CSR_READ(CSR_MATTRI3_MASK); base = __RV_CSR_READ(CSR_MATTRI3_BASE); break;
  140. case 4: mask = __RV_CSR_READ(CSR_MATTRI4_MASK); base = __RV_CSR_READ(CSR_MATTRI4_BASE); break;
  141. case 5: mask = __RV_CSR_READ(CSR_MATTRI5_MASK); base = __RV_CSR_READ(CSR_MATTRI5_BASE); break;
  142. case 6: mask = __RV_CSR_READ(CSR_MATTRI6_MASK); base = __RV_CSR_READ(CSR_MATTRI6_BASE); break;
  143. case 7: mask = __RV_CSR_READ(CSR_MATTRI7_MASK); base = __RV_CSR_READ(CSR_MATTRI7_BASE); break;
  144. default: return -1;
  145. }
  146. pma_cfg->region_type = (unsigned long)(base & 0x0E);
  147. pma_cfg->region_base = (unsigned long)((base >> 12) << 12);
  148. pma_cfg->region_size = (unsigned long)(1UL << (mask == 0 ? mpasize : __CTZ(mask)));
  149. pma_cfg->region_enable = (uint16_t)(base & 0x01);
  150. return 0;
  151. }
  152. /**
  153. * \brief Configure one region for Secure S-Mode world to share with Non-Secure S-Mode world
  154. * \details Set the region(0-7) info of base address/region size/enable status
  155. * \param [in] entry_idx Index(0-7) of paired sattri(n)_mask and sattri(n)_base
  156. * \param [in] pma_cfg Region info to configure
  157. * \return 0 if success, else -1
  158. * \remarks
  159. * - sattri(n)_mask must be written first, before sattri(n)_base, which the api takes care of
  160. * - The higher bits of sattri(n)_mask should be continuously 1, the remaining lower bits should be all 0
  161. * and the number (N) of 0 means the size of this region(2^N bytes)
  162. * - Region granularity is 4KB, so the low 12-bits of sattri(n)_mask must be 0, which the api takes care of
  163. * - Unlike mattri(n)_base, there's no DEV Region/NC Region/CA Region type
  164. */
  165. __STATIC_INLINE long PMA_SetRegion_S(unsigned long entry_idx, pma_config *pma_cfg)
  166. {
  167. // 4KB aligned
  168. unsigned long size = (pma_cfg->region_size >> 12) << 12;
  169. unsigned long base_addr = (pma_cfg->region_base >> 12) << 12;
  170. if ((entry_idx + 1) > __PMA_SEC_CSR_NUM) {
  171. return -1;
  172. }
  173. rv_csr_t mask = (unsigned long)(~(size - 1));
  174. rv_csr_t base = base_addr | pma_cfg->region_enable;
  175. switch (entry_idx) {
  176. // Bit[MXLEN-1:PA_SIZE] of sattri(n)_mask is reserved 0
  177. case 0: __RV_CSR_WRITE(CSR_SATTRI0_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI0_BASE, base); break;
  178. case 1: __RV_CSR_WRITE(CSR_SATTRI1_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI1_BASE, base); break;
  179. case 2: __RV_CSR_WRITE(CSR_SATTRI2_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI2_BASE, base); break;
  180. case 3: __RV_CSR_WRITE(CSR_SATTRI3_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI3_BASE, base); break;
  181. case 4: __RV_CSR_WRITE(CSR_SATTRI4_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI4_BASE, base); break;
  182. case 5: __RV_CSR_WRITE(CSR_SATTRI5_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI5_BASE, base); break;
  183. case 6: __RV_CSR_WRITE(CSR_SATTRI6_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI6_BASE, base); break;
  184. case 7: __RV_CSR_WRITE(CSR_SATTRI7_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI7_BASE, base); break;
  185. default: return -1;
  186. }
  187. return 0;
  188. }
  189. /**
  190. * \brief Get the region info of Secure S-Mode world sharing with Non-Secure S-Mode world
  191. * \details Read the region(0-7) info of base address/region size/enable status
  192. * \param [in] entry_idx Index(0-7) of paired sattri(n)_mask and sattri(n)_base
  193. * \param [out] pma_cfg Region info read
  194. * \return 0 if success, else -1
  195. * \remark
  196. * - Unlike mattri(n)_base, there's no DEV Region/NC Region/CA Region type
  197. */
  198. __STATIC_INLINE long PMA_GetRegion_S(unsigned long entry_idx, pma_config *pma_cfg)
  199. {
  200. rv_csr_t mask, base;
  201. uint32_t mpasize = *(uint32_t *)__IINFO_MPASIZE_ADDR;
  202. if ((entry_idx + 1) > __PMA_SEC_CSR_NUM) {
  203. return -1;
  204. }
  205. switch (entry_idx) {
  206. case 0: mask = __RV_CSR_READ(CSR_SATTRI0_MASK); base = __RV_CSR_READ(CSR_SATTRI0_BASE); break;
  207. case 1: mask = __RV_CSR_READ(CSR_SATTRI1_MASK); base = __RV_CSR_READ(CSR_SATTRI1_BASE); break;
  208. case 2: mask = __RV_CSR_READ(CSR_SATTRI2_MASK); base = __RV_CSR_READ(CSR_SATTRI2_BASE); break;
  209. case 3: mask = __RV_CSR_READ(CSR_SATTRI3_MASK); base = __RV_CSR_READ(CSR_SATTRI3_BASE); break;
  210. case 4: mask = __RV_CSR_READ(CSR_SATTRI4_MASK); base = __RV_CSR_READ(CSR_SATTRI4_BASE); break;
  211. case 5: mask = __RV_CSR_READ(CSR_SATTRI5_MASK); base = __RV_CSR_READ(CSR_SATTRI5_BASE); break;
  212. case 6: mask = __RV_CSR_READ(CSR_SATTRI6_MASK); base = __RV_CSR_READ(CSR_SATTRI6_BASE); break;
  213. case 7: mask = __RV_CSR_READ(CSR_SATTRI7_MASK); base = __RV_CSR_READ(CSR_SATTRI7_BASE); break;
  214. default: return -1;
  215. }
  216. pma_cfg->region_base = (unsigned long)((base >> 12) << 12);
  217. pma_cfg->region_size = (unsigned long)(1UL << (mask == 0 ? mpasize : __CTZ(mask)));
  218. pma_cfg->region_enable = (uint16_t)(base & 0x01);
  219. return 0;
  220. }
  221. #if defined(__PMA_MACRO_PRESENT) && (__PMA_MACRO_PRESENT == 1)
  222. /**
  223. * \brief Enable hardware defined Device regions
  224. * \details Enable Device region by corresponding index
  225. * \param [in] entry_idx Index(0-7)
  226. * \remarks
  227. * - This function can be called in M-Mode only.
  228. * - When there is no entry_idx, this field is tied to 0
  229. * - For each region entry's address/size/attribute detail refers to RTL Configuration Stage
  230. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  231. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  232. * \sa
  233. * - \ref PMA_DisableHwDevRegion
  234. */
  235. __STATIC_FORCEINLINE void PMA_EnableHwDevRegion(unsigned long entry_idx)
  236. {
  237. __RV_CSR_SET(CSR_MMACRO_DEV_EN, 1UL << entry_idx);
  238. }
  239. /**
  240. * \brief Disable hardware defined Device regions
  241. * \details Disable Device region by corresponding index
  242. * \param [in] entry_idx Index(0-7)
  243. * \remarks
  244. * - This function can be called in M-Mode only.
  245. * - When there is no entry_idx, this field is tied to 0
  246. * - For each region entry's address/size/attribute detail refers to RTL Configuration Stage
  247. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  248. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  249. * \sa
  250. * - \ref PMA_EnableHwDevRegion
  251. */
  252. __STATIC_FORCEINLINE void PMA_DisableHwDevRegion(unsigned long entry_idx)
  253. {
  254. __RV_CSR_CLEAR(CSR_MMACRO_DEV_EN, 1UL << entry_idx);
  255. }
  256. /**
  257. * \brief Enable hardware defined Non-Cacheable regions
  258. * \details Enable Non-Cacheable region by corresponding index
  259. * \param [in] entry_idx Index(0-7)
  260. * \remarks
  261. * - This function can be called in M-Mode only.
  262. * - When there is no entry_idx, this field is tied to 0
  263. * - For each region entry's address/size/attribute detail refers to RTL Configuration Stage
  264. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  265. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  266. * \sa
  267. * - \ref PMA_DisableHwNCRegion
  268. */
  269. __STATIC_FORCEINLINE void PMA_EnableHwNCRegion(unsigned long entry_idx)
  270. {
  271. __RV_CSR_SET(CSR_MMACRO_NOC_EN, 1UL << entry_idx);
  272. }
  273. /**
  274. * \brief Disable hardware defined Non-Cacheable regions
  275. * \details Disable Non-Cacheable region by corresponding index
  276. * \param [in] entry_idx Index(0-7)
  277. * \remarks
  278. * - This function can be called in M-Mode only.
  279. * - When there is no entry_idx, this field is tied to 0
  280. * - For each region entry's address/size/attribute detail refers to RTL Configuration Stage
  281. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  282. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  283. * \sa
  284. * - \ref PMA_EnableHwNCRegion
  285. */
  286. __STATIC_FORCEINLINE void PMA_DisableHwNCRegion(unsigned long entry_idx)
  287. {
  288. __RV_CSR_CLEAR(CSR_MMACRO_NOC_EN, 1UL << entry_idx);
  289. }
  290. /**
  291. * \brief Enable hardware defined Cacheable regions
  292. * \details Enable Cacheable region by corresponding index
  293. * \param [in] entry_idx Index(0-7)
  294. * \remarks
  295. * - This function can be called in M-Mode only.
  296. * - When there is no entry_idx, this field is tied to 0
  297. * - For each region entry's address/size/attribute detail refers to RTL Configuration Stage
  298. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  299. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  300. * \sa
  301. * - \ref PMA_DisableHwCARegion
  302. */
  303. __STATIC_FORCEINLINE void PMA_EnableHwCARegion(unsigned long entry_idx)
  304. {
  305. __RV_CSR_SET(CSR_MMACRO_CA_EN, 1UL << entry_idx);
  306. }
  307. /**
  308. * \brief Disable hardware defined Cacheable regions
  309. * \details Disable Cacheable region by corresponding index
  310. * \param [in] entry_idx Index(0-7)
  311. * \remarks
  312. * - This function can be called in M-Mode only.
  313. * - When there is no entry_idx, this field is tied to 0
  314. * - For each region entry's address/size/attribute detail refers to RTL Configuration Stage
  315. * - The regions can be overlapped as the prority: Non-Cacheable > Cacheable > Device, but especially be careful not to
  316. * overlap software's instruction/data sections by Device, or overlap Device(like uart) memory by Cacheable
  317. * \sa
  318. * - \ref PMA_EnableHwCARegion
  319. */
  320. __STATIC_FORCEINLINE void PMA_DisableHwCARegion(unsigned long entry_idx)
  321. {
  322. __RV_CSR_CLEAR(CSR_MMACRO_CA_EN, 1UL << entry_idx);
  323. }
  324. #endif /* defined(__PMA_MACRO_PRESENT) && (__PMA_MACRO_PRESENT == 1) */
  325. /** @} */ /* End of Doxygen Group NMSIS_Core_PMA_Functions */
  326. #endif /* defined(__PMA_PRESENT) && (__PMA_PRESENT==1) */
  327. #ifdef __cplusplus
  328. }
  329. #endif
  330. #endif /* __CORE_FEATURE_PMA_H__ */