• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PMP_H__
19 #define __CORE_FEATURE_PMP_H__
20 /*!
21  * @file     core_feature_pmp.h
22  * @brief    PMP feature API header file for Nuclei N/NX Core
23  */
24 /*
25  * PMP Feature Configuration Macro:
26  * 1. __PMP_PRESENT:  Define whether Physical Memory Protection(PMP) is present or not
27  *   * 0: Not present
28  *   * 1: Present
29  * 2. __PMP_ENTRY_NUM:  Define the number of PMP entries, only 8 or 16 is configurable.
30  */
31 #ifdef __cplusplus
32  extern "C" {
33 #endif
34 
35 #if defined(__PMP_PRESENT) && (__PMP_PRESENT == 1)
36 /* ===== PMP Operations ===== */
37 /**
38  * \defgroup NMSIS_Core_PMP_Functions   PMP Functions
39  * \ingroup  NMSIS_Core
40  * \brief    Functions that related to the RISCV Phyiscal Memory Protection.
41  * \details
42  * Optional physical memory protection (PMP) unit provides per-hart machine-mode
43  * control registers to allow physical memory access privileges (read, write, execute)
44  * to be specified for each physical memory region.
45  *
46  * The PMP can supports region access control settings as small as four bytes.
47  *
48  *   @{
49  */
50 #ifndef __PMP_ENTRY_NUM
51 /* numbers of PMP entries(__PMP_ENTRY_NUM) should be defined in <Device.h> */
52 #error "__PMP_ENTRY_NUM is not defined, please check!"
53 #endif
54 
55 /**
56  * \brief   Get 8bit PMPxCFG Register by PMP entry index
57  * \details Return the content of the PMPxCFG Register.
58  * \param [in]    idx    PMP region index(0-15)
59  * \return               PMPxCFG Register value
60  */
__get_PMPxCFG(uint32_t idx)61 __STATIC_INLINE uint8_t __get_PMPxCFG(uint32_t idx)
62 {
63     rv_csr_t pmpcfg = 0;
64 
65     if (idx >= __PMP_ENTRY_NUM) return 0;
66 #if __RISCV_XLEN == 32
67     if (idx < 4) {
68         pmpcfg = __RV_CSR_READ(CSR_PMPCFG0);
69     } else if ((idx >=4) && (idx < 8)) {
70         idx -= 4;
71         pmpcfg = __RV_CSR_READ(CSR_PMPCFG1);
72     } else if ((idx >=8) && (idx < 12)) {
73         idx -= 8;
74         pmpcfg = __RV_CSR_READ(CSR_PMPCFG2);
75     } else {
76         idx -= 12;
77         pmpcfg = __RV_CSR_READ(CSR_PMPCFG3);
78     }
79 
80     idx = idx << 3;
81     return (uint8_t)((pmpcfg>>idx) & 0xFF);
82 #elif __RISCV_XLEN == 64
83     if (idx < 8) {
84         pmpcfg = __RV_CSR_READ(CSR_PMPCFG0);
85     } else {
86         idx -= 8;
87         pmpcfg = __RV_CSR_READ(CSR_PMPCFG2);
88     }
89     idx = idx << 3;
90     return (uint8_t)((pmpcfg>>idx) & 0xFF);
91 #else
92     // TODO Add RV128 Handling
93     return 0;
94 #endif
95 }
96 
97 /**
98  * \brief   Set 8bit PMPxCFG by pmp entry index
99  * \details Set the given pmpxcfg value to the PMPxCFG Register.
100  * \param [in]    idx      PMPx region index(0-15)
101  * \param [in]    pmpxcfg  PMPxCFG register value to set
102  */
__set_PMPxCFG(uint32_t idx,uint8_t pmpxcfg)103 __STATIC_INLINE void __set_PMPxCFG(uint32_t idx, uint8_t pmpxcfg)
104 {
105     rv_csr_t pmpcfgx = 0;
106     if (idx >= __PMP_ENTRY_NUM) return;
107 
108 #if __RISCV_XLEN == 32
109     if (idx < 4) {
110         pmpcfgx = __RV_CSR_READ(CSR_PMPCFG0);
111         idx = idx << 3;
112         pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
113         __RV_CSR_WRITE(CSR_PMPCFG0, pmpcfgx);
114     } else if ((idx >=4) && (idx < 8)) {
115         idx -= 4;
116         pmpcfgx = __RV_CSR_READ(CSR_PMPCFG1);
117         idx = idx << 3;
118         pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
119         __RV_CSR_WRITE(CSR_PMPCFG1, pmpcfgx);
120     } else if ((idx >=8) && (idx < 12)) {
121         idx -= 8;
122         pmpcfgx = __RV_CSR_READ(CSR_PMPCFG2);
123         idx = idx << 3;
124         pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
125         __RV_CSR_WRITE(CSR_PMPCFG2, pmpcfgx);
126     } else {
127         idx -= 12;
128         pmpcfgx = __RV_CSR_READ(CSR_PMPCFG3);
129         idx = idx << 3;
130         pmpcfgx = (pmpcfgx & ~(0xFFUL << idx)) | ((rv_csr_t)pmpxcfg << idx);
131         __RV_CSR_WRITE(CSR_PMPCFG3, pmpcfgx);
132     }
133 #elif __RISCV_XLEN == 64
134     if (idx < 8) {
135         pmpcfgx = __RV_CSR_READ(CSR_PMPCFG0);
136         idx = idx << 3;
137         pmpcfgx = (pmpcfgx & ~(0xFFULL << idx)) | ((rv_csr_t)pmpxcfg << idx);
138         __RV_CSR_WRITE(CSR_PMPCFG0, pmpcfgx);
139     } else {
140         idx -= 8;
141         pmpcfgx = __RV_CSR_READ(CSR_PMPCFG2);
142         idx = idx << 3;
143         pmpcfgx = (pmpcfgx & ~(0xFFULL << idx)) | ((rv_csr_t)pmpxcfg << idx);
144         __RV_CSR_WRITE(CSR_PMPCFG2, pmpcfgx);
145     }
146 #else
147     // TODO Add RV128 Handling
148 #endif
149 }
150 
151 /**
152  * \brief   Get PMPCFGx Register by index
153  * \details Return the content of the PMPCFGx Register.
154  * \param [in]    idx    PMPCFG CSR index(0-3)
155  * \return               PMPCFGx Register value
156  * \remark
157  * - For RV64, only idx = 0 and idx = 2 is allowed.
158  *   pmpcfg0 and pmpcfg2 hold the configurations
159  *   for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
160  * - For RV32, pmpcfg0–pmpcfg3, hold the configurations
161  *   pmp0cfg–pmp15cfg for the 16 PMP entries
162  */
__get_PMPCFGx(uint32_t idx)163 __STATIC_INLINE rv_csr_t __get_PMPCFGx(uint32_t idx)
164 {
165     switch (idx) {
166         case 0: return __RV_CSR_READ(CSR_PMPCFG0);
167         case 1: return __RV_CSR_READ(CSR_PMPCFG1);
168         case 2: return __RV_CSR_READ(CSR_PMPCFG2);
169         case 3: return __RV_CSR_READ(CSR_PMPCFG3);
170         default: return 0;
171     }
172 }
173 
174 /**
175  * \brief   Set PMPCFGx by index
176  * \details Write the given value to the PMPCFGx Register.
177  * \param [in]    idx      PMPCFG CSR index(0-3)
178  * \param [in]    pmpcfg   PMPCFGx Register value to set
179  * \remark
180  * - For RV64, only idx = 0 and idx = 2 is allowed.
181  *   pmpcfg0 and pmpcfg2 hold the configurations
182  *   for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
183  * - For RV32, pmpcfg0–pmpcfg3, hold the configurations
184  *   pmp0cfg–pmp15cfg for the 16 PMP entries
185  */
__set_PMPCFGx(uint32_t idx,rv_csr_t pmpcfg)186 __STATIC_INLINE void __set_PMPCFGx(uint32_t idx, rv_csr_t pmpcfg)
187 {
188     switch (idx) {
189         case 0: __RV_CSR_WRITE(CSR_PMPCFG0, pmpcfg); break;
190         case 1: __RV_CSR_WRITE(CSR_PMPCFG1, pmpcfg); break;
191         case 2: __RV_CSR_WRITE(CSR_PMPCFG2, pmpcfg); break;
192         case 3: __RV_CSR_WRITE(CSR_PMPCFG3, pmpcfg); break;
193         default: return;
194     }
195 }
196 
197 /**
198  * \brief   Get PMPADDRx Register by index
199  * \details Return the content of the PMPADDRx Register.
200  * \param [in]    idx    PMP region index(0-15)
201  * \return               PMPADDRx Register value
202  */
__get_PMPADDRx(uint32_t idx)203 __STATIC_INLINE rv_csr_t __get_PMPADDRx(uint32_t idx)
204 {
205     switch (idx) {
206         case 0: return __RV_CSR_READ(CSR_PMPADDR0);
207         case 1: return __RV_CSR_READ(CSR_PMPADDR1);
208         case 2: return __RV_CSR_READ(CSR_PMPADDR2);
209         case 3: return __RV_CSR_READ(CSR_PMPADDR3);
210         case 4: return __RV_CSR_READ(CSR_PMPADDR4);
211         case 5: return __RV_CSR_READ(CSR_PMPADDR5);
212         case 6: return __RV_CSR_READ(CSR_PMPADDR6);
213         case 7: return __RV_CSR_READ(CSR_PMPADDR7);
214         case 8: return __RV_CSR_READ(CSR_PMPADDR8);
215         case 9: return __RV_CSR_READ(CSR_PMPADDR9);
216         case 10: return __RV_CSR_READ(CSR_PMPADDR10);
217         case 11: return __RV_CSR_READ(CSR_PMPADDR11);
218         case 12: return __RV_CSR_READ(CSR_PMPADDR12);
219         case 13: return __RV_CSR_READ(CSR_PMPADDR13);
220         case 14: return __RV_CSR_READ(CSR_PMPADDR14);
221         case 15: return __RV_CSR_READ(CSR_PMPADDR15);
222         default: return 0;
223     }
224 }
225 
226 /**
227  * \brief   Set PMPADDRx by index
228  * \details Write the given value to the PMPADDRx Register.
229  * \param [in]    idx      PMP region index(0-15)
230  * \param [in]    pmpaddr  PMPADDRx Register value to set
231  */
__set_PMPADDRx(uint32_t idx,rv_csr_t pmpaddr)232 __STATIC_INLINE void __set_PMPADDRx(uint32_t idx, rv_csr_t pmpaddr)
233 {
234     switch (idx) {
235         case 0: __RV_CSR_WRITE(CSR_PMPADDR0, pmpaddr); break;
236         case 1: __RV_CSR_WRITE(CSR_PMPADDR1, pmpaddr); break;
237         case 2: __RV_CSR_WRITE(CSR_PMPADDR2, pmpaddr); break;
238         case 3: __RV_CSR_WRITE(CSR_PMPADDR3, pmpaddr); break;
239         case 4: __RV_CSR_WRITE(CSR_PMPADDR4, pmpaddr); break;
240         case 5: __RV_CSR_WRITE(CSR_PMPADDR5, pmpaddr); break;
241         case 6: __RV_CSR_WRITE(CSR_PMPADDR6, pmpaddr); break;
242         case 7: __RV_CSR_WRITE(CSR_PMPADDR7, pmpaddr); break;
243         case 8: __RV_CSR_WRITE(CSR_PMPADDR8, pmpaddr); break;
244         case 9: __RV_CSR_WRITE(CSR_PMPADDR9, pmpaddr); break;
245         case 10: __RV_CSR_WRITE(CSR_PMPADDR10, pmpaddr); break;
246         case 11: __RV_CSR_WRITE(CSR_PMPADDR11, pmpaddr); break;
247         case 12: __RV_CSR_WRITE(CSR_PMPADDR12, pmpaddr); break;
248         case 13: __RV_CSR_WRITE(CSR_PMPADDR13, pmpaddr); break;
249         case 14: __RV_CSR_WRITE(CSR_PMPADDR14, pmpaddr); break;
250         case 15: __RV_CSR_WRITE(CSR_PMPADDR15, pmpaddr); break;
251         default: return;
252     }
253 }
254 /** @} */ /* End of Doxygen Group NMSIS_Core_PMP_Functions */
255 #endif /* defined(__PMP_PRESENT) && (__PMP_PRESENT == 1) */
256 
257 #ifdef __cplusplus
258 }
259 #endif
260 #endif /** __CORE_FEATURE_PMP_H__  */
261