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 Initialize the PMP
78 * @param pmp The PMP device handle to be initialized
80 * The PMP initialization routine is optional and may be called as many times
81 * as is desired. The effect of the initialization routine is to attempt to set
82 * all regions to unlocked and disabled, as well as to clear the X, W, and R
83 * bits. Only the pmp configuration of the hart which executes the routine will
86 * If any regions are fused to preset values by the implementation or locked,
87 * those PMP regions will silently remain uninitialized.
89 void metal_pmp_init(struct metal_pmp *pmp);
92 * @brief Configure a PMP region
93 * @param pmp The PMP device handle
94 * @param region The PMP region to configure
95 * @param config The desired configuration of the PMP region
96 * @param address The desired address of the PMP region
97 * @return 0 upon success
99 int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address);
102 * @brief Get the configuration for a PMP region
103 * @param pmp The PMP device handle
104 * @param region The PMP region to read
105 * @param config Variable to store the PMP region configuration
106 * @param address Variable to store the PMP region address
107 * @return 0 if the region is read successfully
109 int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address);
112 * @brief Lock a PMP region
113 * @param pmp The PMP device handle
114 * @param region The PMP region to lock
115 * @return 0 if the region is successfully locked
117 int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region);
120 * @brief Set the address for a PMP region
121 * @param pmp The PMP device handle
122 * @param region The PMP region to set
123 * @param address The desired address of the PMP region
124 * @return 0 if the address is successfully set
126 int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address);
129 * @brief Get the address of a PMP region
130 * @param pmp The PMP device handle
131 * @param region The PMP region to read
132 * @return The address of the PMP region, or 0 if the region could not be read
134 size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region);
137 * @brief Set the addressing mode of a PMP region
138 * @param pmp The PMP device handle
139 * @param region The PMP region to set
140 * @param mode The PMP addressing mode to set
141 * @return 0 if the addressing mode is successfully set
143 int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode);
146 * @brief Get the addressing mode of a PMP region
147 * @param pmp The PMP device handle
148 * @param region The PMP region to read
149 * @return The address mode of the PMP region
151 enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region);
154 * @brief Set the executable bit for a PMP region
155 * @param pmp The PMP device handle
156 * @param region The PMP region to set
157 * @param X The desired value of the executable bit
158 * @return 0 if the executable bit is successfully set
160 int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X);
163 * @brief Get the executable bit for a PMP region
164 * @param pmp The PMP device handle
165 * @param region The PMP region to read
166 * @return the value of the executable bit
168 int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region);
171 * @brief Set the writable bit for a PMP region
172 * @param pmp The PMP device handle
173 * @param region The PMP region to set
174 * @param W The desired value of the writable bit
175 * @return 0 if the writable bit is successfully set
177 int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W);
180 * @brief Get the writable bit for a PMP region
181 * @param pmp The PMP device handle
182 * @param region The PMP region to read
183 * @return the value of the writable bit
185 int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region);
188 * @brief Set the readable bit for a PMP region
189 * @param pmp The PMP device handle
190 * @param region The PMP region to set
191 * @param R The desired value of the readable bit
192 * @return 0 if the readable bit is successfully set
194 int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R);
197 * @brief Set the readable bit for a PMP region
198 * @param pmp The PMP device handle
199 * @param region The PMP region to read
200 * @return the value of the readable bit
202 int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region);