17
17
#ifndef PMA_H
18
18
#define PMA_H
19
19
20
+ #include < array>
20
21
#include < cstdint>
21
22
23
+ #include " compiler-defines.h"
22
24
#include " pma-constants.h"
23
25
24
26
namespace cartesi {
@@ -32,8 +34,6 @@ static constexpr const char *pma_get_DID_name(PMA_ISTART_DID did) {
32
34
return " DID.memory" ;
33
35
case PMA_ISTART_DID::shadow_state:
34
36
return " DID.shadow_state" ;
35
- case PMA_ISTART_DID::shadow_pmas:
36
- return " DID.shadow_pmas" ;
37
37
case PMA_ISTART_DID::shadow_TLB:
38
38
return " DID.shadow_TLB" ;
39
39
case PMA_ISTART_DID::flash_drive:
@@ -73,7 +73,7 @@ struct pma_flags {
73
73
bool operator ==(const pma_flags &) const = default ;
74
74
};
75
75
76
- static constexpr pma_flags unpack_pma_istart (uint64_t istart, uint64_t &start) {
76
+ static constexpr pma_flags pma_unpack_istart (uint64_t istart, uint64_t &start) {
77
77
start = istart & PMA_ISTART_START_MASK;
78
78
return pma_flags{.M = ((istart & PMA_ISTART_M_MASK) >> PMA_ISTART_M_SHIFT) != 0 ,
79
79
.IO = ((istart & PMA_ISTART_IO_MASK) >> PMA_ISTART_IO_SHIFT) != 0 ,
@@ -86,7 +86,7 @@ static constexpr pma_flags unpack_pma_istart(uint64_t istart, uint64_t &start) {
86
86
.DID = static_cast <PMA_ISTART_DID>((istart & PMA_ISTART_DID_MASK) >> PMA_ISTART_DID_SHIFT)};
87
87
}
88
88
89
- static constexpr uint64_t pack_pma_istart (const pma_flags &flags, uint64_t start) {
89
+ static constexpr uint64_t pma_pack_istart (const pma_flags &flags, uint64_t start) {
90
90
uint64_t istart = start;
91
91
istart |= (static_cast <uint64_t >(flags.M ) << PMA_ISTART_M_SHIFT);
92
92
istart |= (static_cast <uint64_t >(flags.IO ) << PMA_ISTART_IO_SHIFT);
@@ -100,6 +100,67 @@ static constexpr uint64_t pack_pma_istart(const pma_flags &flags, uint64_t start
100
100
return istart;
101
101
}
102
102
103
+ // / \brief Shadow memory layout
104
+ struct PACKED pma_entry {
105
+ uint64_t istart;
106
+ uint64_t ilength;
107
+ };
108
+
109
+ using pmas_state = std::array<pma_entry, PMA_MAX>;
110
+
111
+ // / \brief List of field types
112
+ enum class pma_what : uint64_t {
113
+ istart = offsetof(pma_entry, istart),
114
+ ilength = offsetof(pma_entry, ilength),
115
+ unknown_ = UINT64_C(1 ) << 63 , // Outside of RISC-V address space
116
+ };
117
+
118
+ // / \brief Obtains the absolute address of a PMA entry.
119
+ // / \param p Index of desired PMA entry
120
+ // / \returns The address.
121
+ static constexpr uint64_t pma_get_abs_addr (uint64_t p) {
122
+ return PMA_PMAS_START + (p * sizeof (pma_entry));
123
+ }
124
+
125
+ // / \brief Obtains the absolute address of a PMA entry.
126
+ // / \param p Index of desired PMA entry
127
+ // / \param what Desired field
128
+ // / \returns The address.
129
+ static constexpr uint64_t pma_get_abs_addr (uint64_t p, pma_what what) {
130
+ return pma_get_abs_addr (p) + static_cast <uint64_t >(what);
131
+ }
132
+
133
+ static constexpr pma_what pma_get_what (uint64_t paddr) {
134
+ if (paddr < PMA_PMAS_START || paddr - PMA_PMAS_START >= sizeof (pmas_state) ||
135
+ (paddr & (sizeof (uint64_t ) - 1 )) != 0 ) {
136
+ return pma_what::unknown_;
137
+ }
138
+ // ??D First condition ensures offset = (paddr-PMA_PMAS_START) >= 0
139
+ // ??D Second ensures offset < sizeof(pmas_state)
140
+ // ??D Third ensures offset is aligned to sizeof(uint64_t)
141
+ // ??D pma_entry only contains uint64_t fields
142
+ // ??D pmas_state_what contains one entry with the offset of each field in pma_entry
143
+ // ??D I don't see how the cast can produce something outside the enum...
144
+ // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
145
+ return pma_what{(paddr - PMA_PMAS_START) % sizeof (pma_entry)};
146
+ }
147
+
148
+ static constexpr const char *pma_get_what_name (pma_what what) {
149
+ const auto paddr = static_cast <uint64_t >(what);
150
+ if (paddr >= sizeof (pma_entry) || (paddr & (sizeof (uint64_t ) - 1 )) != 0 ) {
151
+ return " pma.unknown_" ;
152
+ }
153
+ switch (what) {
154
+ case pma_what::istart:
155
+ return " pma.istart" ;
156
+ case pma_what::ilength:
157
+ return " pma.ilength" ;
158
+ case pma_what::unknown_:
159
+ return " pma.unknown_" ;
160
+ }
161
+ return " pmas.unknown_" ;
162
+ }
163
+
103
164
} // namespace cartesi
104
165
105
166
#endif
0 commit comments