1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
10 * @brief API for Configuring Physical Memory Protection on RISC-V Cores
12 * The Physical Memory Protection (PMP) interface on RISC-V cores
13 * is a form of memory protection unit which allows for a finite number
14 * of physical memory regions to be configured with certain access
17 * Additional information about the use and configuration rules for PMPs
18 * can be found by reading the RISC-V Privileged Architecture Specification.
22 #include <metal/machine.h>
27 * @brief Set of available PMP addressing modes
29 enum metal_pmp_address_mode {
30 /*! @brief Disable the PMP region */
32 /*! @brief Use Top-of-Range mode */
34 /*! @brief Use naturally-aligned 4-byte region mode */
36 /*! @brief Use naturally-aligned power-of-two mode */
41 * @brief Configuration for a PMP region
43 struct metal_pmp_config {
44 /*! @brief Sets whether reads to the PMP region succeed */
46 /*! @brief Sets whether writes to the PMP region succeed */
48 /*! @brief Sets whether the PMP region is executable */
51 /*! @brief Sets the addressing mode of the PMP region */
52 enum metal_pmp_address_mode A : 2;
56 /*! @brief Sets whether the PMP region is locked */
57 enum metal_pmp_locked {
58 METAL_PMP_UNLOCKED = 0,
64 * @brief A handle for the PMP device
67 /* The minimum granularity of the PMP region. Set by metal_pmp_init */
68 uintptr_t _granularity[METAL_MAX_CORES];
72 * @brief Get the PMP device handle
74 struct metal_pmp *metal_pmp_get_device(void);
77 * @brief Get the number of pmp regions for the hartid
79 int metal_pmp_num_regions(int hartid);
82 * @brief Initialize the PMP
83 * @param pmp The PMP device handle to be initialized
85 * The PMP initialization routine is optional and may be called as many times
86 * as is desired. The effect of the initialization routine is to attempt to set
87 * all regions to unlocked and disabled, as well as to clear the X, W, and R
88 * bits. Only the pmp configuration of the hart which executes the routine will
91 * If any regions are fused to preset values by the implementation or locked,
92 * those PMP regions will silently remain uninitialized.
94 void metal_pmp_init(struct metal_pmp *pmp);
97 * @brief Configure a PMP region
98 * @param pmp The PMP device handle
99 * @param region The PMP region to configure
100 * @param config The desired configuration of the PMP region
101 * @param address The desired address of the PMP region
102 * @return 0 upon success
104 int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address);
107 * @brief Get the configuration for a PMP region
108 * @param pmp The PMP device handle
109 * @param region The PMP region to read
110 * @param config Variable to store the PMP region configuration
111 * @param address Variable to store the PMP region address
112 * @return 0 if the region is read successfully
114 int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address);
117 * @brief Lock a PMP region
118 * @param pmp The PMP device handle
119 * @param region The PMP region to lock
120 * @return 0 if the region is successfully locked
122 int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region);
125 * @brief Set the address for a PMP region
126 * @param pmp The PMP device handle
127 * @param region The PMP region to set
128 * @param address The desired address of the PMP region
129 * @return 0 if the address is successfully set
131 int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address);
134 * @brief Get the address of a PMP region
135 * @param pmp The PMP device handle
136 * @param region The PMP region to read
137 * @return The address of the PMP region, or 0 if the region could not be read
139 size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region);
142 * @brief Set the addressing mode of a PMP region
143 * @param pmp The PMP device handle
144 * @param region The PMP region to set
145 * @param mode The PMP addressing mode to set
146 * @return 0 if the addressing mode is successfully set
148 int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode);
151 * @brief Get the addressing mode of a PMP region
152 * @param pmp The PMP device handle
153 * @param region The PMP region to read
154 * @return The address mode of the PMP region
156 enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region);
159 * @brief Set the executable bit for a PMP region
160 * @param pmp The PMP device handle
161 * @param region The PMP region to set
162 * @param X The desired value of the executable bit
163 * @return 0 if the executable bit is successfully set
165 int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X);
168 * @brief Get the executable bit for a PMP region
169 * @param pmp The PMP device handle
170 * @param region The PMP region to read
171 * @return the value of the executable bit
173 int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region);
176 * @brief Set the writable bit for a PMP region
177 * @param pmp The PMP device handle
178 * @param region The PMP region to set
179 * @param W The desired value of the writable bit
180 * @return 0 if the writable bit is successfully set
182 int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W);
185 * @brief Get the writable bit for a PMP region
186 * @param pmp The PMP device handle
187 * @param region The PMP region to read
188 * @return the value of the writable bit
190 int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region);
193 * @brief Set the readable bit for a PMP region
194 * @param pmp The PMP device handle
195 * @param region The PMP region to set
196 * @param R The desired value of the readable bit
197 * @return 0 if the readable bit is successfully set
199 int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R);
202 * @brief Set the readable bit for a PMP region
203 * @param pmp The PMP device handle
204 * @param region The PMP region to read
205 * @return the value of the readable bit
207 int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region);