summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/bsp/install/include/metal/pmp.h
blob: 9121b10a14774ad8053b4a19938264317b4f510f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */

#ifndef METAL__PMP_H
#define METAL__PMP_H

/*!
 * @file metal/pmp.h
 *
 * @brief API for Configuring Physical Memory Protection on RISC-V Cores
 *
 * The Physical Memory Protection (PMP) interface on RISC-V cores
 * is a form of memory protection unit which allows for a finite number
 * of physical memory regions to be configured with certain access
 * permissions. 
 *
 * Additional information about the use and configuration rules for PMPs
 * can be found by reading the RISC-V Privileged Architecture Specification.
 */

#include <stddef.h>
#include <metal/machine.h>

struct metal_pmp;

/*!
 * @brief Set of available PMP addressing modes
 */
enum metal_pmp_address_mode {
    /*! @brief Disable the PMP region */
    METAL_PMP_OFF   = 0,
    /*! @brief Use Top-of-Range mode */
    METAL_PMP_TOR   = 1,
    /*! @brief Use naturally-aligned 4-byte region mode */
    METAL_PMP_NA4   = 2,
    /*! @brief Use naturally-aligned power-of-two mode */
    METAL_PMP_NAPOT = 3
};

/*!
 * @brief Configuration for a PMP region
 */
struct metal_pmp_config {
    /*! @brief Sets whether reads to the PMP region succeed */
    int R : 1;
    /*! @brief Sets whether writes to the PMP region succeed */
    int W : 1;
    /*! @brief Sets whether the PMP region is executable */
    int X : 1;

    /*! @brief Sets the addressing mode of the PMP region */
    enum metal_pmp_address_mode A : 2;

    int _pad : 2;

    /*! @brief Sets whether the PMP region is locked */
    enum metal_pmp_locked {
        METAL_PMP_UNLOCKED = 0,
        METAL_PMP_LOCKED   = 1
    } L : 1;
};

/*!
 * @brief A handle for the PMP device
 */
struct metal_pmp {
    /* The minimum granularity of the PMP region. Set by metal_pmp_init */
    uintptr_t _granularity[METAL_MAX_CORES];
};

/*!
 * @brief Get the PMP device handle
 */
struct metal_pmp *metal_pmp_get_device(void);

/*!
 * @brief Initialize the PMP
 * @param pmp The PMP device handle to be initialized
 *
 * The PMP initialization routine is optional and may be called as many times
 * as is desired. The effect of the initialization routine is to attempt to set
 * all regions to unlocked and disabled, as well as to clear the X, W, and R
 * bits. Only the pmp configuration of the hart which executes the routine will
 * be affected.
 *
 * If any regions are fused to preset values by the implementation or locked,
 * those PMP regions will silently remain uninitialized.
 */
void metal_pmp_init(struct metal_pmp *pmp);

/*!
 * @brief Configure a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to configure
 * @param config The desired configuration of the PMP region
 * @param address The desired address of the PMP region
 * @return 0 upon success
 */
int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address);

/*! 
 * @brief Get the configuration for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to read
 * @param config Variable to store the PMP region configuration
 * @param address Variable to store the PMP region address
 * @return 0 if the region is read successfully
 */
int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address);

/*!
 * @brief Lock a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to lock
 * @return 0 if the region is successfully locked
 */
int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region);

/*!
 * @brief Set the address for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to set
 * @param address The desired address of the PMP region
 * @return 0 if the address is successfully set
 */
int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address);

/*!
 * @brief Get the address of a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to read
 * @return The address of the PMP region, or 0 if the region could not be read
 */
size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region);

/*!
 * @brief Set the addressing mode of a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to set
 * @param mode The PMP addressing mode to set
 * @return 0 if the addressing mode is successfully set
 */
int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode);

/*!
 * @brief Get the addressing mode of a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to read
 * @return The address mode of the PMP region
 */
enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region);

/*!
 * @brief Set the executable bit for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to set
 * @param X The desired value of the executable bit
 * @return 0 if the executable bit is successfully set
 */
int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X);

/*!
 * @brief Get the executable bit for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to read
 * @return the value of the executable bit
 */
int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region);

/*!
 * @brief Set the writable bit for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to set
 * @param W The desired value of the writable bit
 * @return 0 if the writable bit is successfully set
 */
int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W);

/*!
 * @brief Get the writable bit for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to read
 * @return the value of the writable bit
 */
int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region);

/*!
 * @brief Set the readable bit for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to set
 * @param R The desired value of the readable bit
 * @return 0 if the readable bit is successfully set
 */
int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R);

/*!
 * @brief Set the readable bit for a PMP region
 * @param pmp The PMP device handle
 * @param region The PMP region to read
 * @return the value of the readable bit
 */
int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region);

#endif