Skip to content

Commit f4edc81

Browse files
committed
adapts pmp to changed arch::priv_if
1 parent 1afc6fe commit f4edc81

1 file changed

Lines changed: 59 additions & 86 deletions

File tree

src/iss/mem/pmp.h

Lines changed: 59 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -40,68 +40,29 @@
4040

4141
namespace iss {
4242
namespace mem {
43-
struct clic_config {
44-
uint64_t clic_base{0xc0000000};
45-
unsigned clic_int_ctl_bits{4};
46-
unsigned clic_num_irq{16};
47-
unsigned clic_num_trigger{0};
48-
bool nmode{false};
49-
};
50-
51-
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
52-
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
53-
switch(offs) {
54-
default:
55-
for(auto i = 0U; i < length; ++i)
56-
*(data + i) = *(reg_ptr + i);
57-
break;
58-
case 1:
59-
for(auto i = 0U; i < length; ++i)
60-
*(data + i) = *(reg_ptr + 1 + i);
61-
break;
62-
case 2:
63-
for(auto i = 0U; i < length; ++i)
64-
*(data + i) = *(reg_ptr + 2 + i);
65-
break;
66-
case 3:
67-
*data = *(reg_ptr + 3);
68-
break;
69-
}
70-
}
71-
72-
inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) {
73-
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
74-
switch(offs) {
75-
default:
76-
for(auto i = 0U; i < length; ++i)
77-
*(reg_ptr + i) = *(data + i);
78-
break;
79-
case 1:
80-
for(auto i = 0U; i < length; ++i)
81-
*(reg_ptr + 1 + i) = *(data + i);
82-
break;
83-
case 2:
84-
for(auto i = 0U; i < length; ++i)
85-
*(reg_ptr + 2 + i) = *(data + i);
86-
break;
87-
case 3:
88-
*(reg_ptr + 3) = *data;
89-
break;
90-
}
91-
}
9243

9344
template <typename PLAT> struct pmp : public memory_elem {
9445
using this_class = pmp<PLAT>;
9546
using reg_t = typename PLAT::reg_t;
47+
static constexpr auto cfg_reg_size = sizeof(reg_t);
48+
static constexpr auto PMP_SHIFT = 2U;
49+
static constexpr auto PMP_R = 0x1U;
50+
static constexpr auto PMP_W = 0x2U;
51+
static constexpr auto PMP_X = 0x4U;
52+
static constexpr auto PMP_A = 0x18U;
53+
static constexpr auto PMP_L = 0x80U;
54+
static constexpr auto PMP_TOR = 0x1U;
55+
static constexpr auto PMP_NA4 = 0x2U;
56+
static constexpr auto PMP_NAPOT = 0x3U;
9657

9758
pmp(arch::priv_if<reg_t> hart_if)
9859
: hart_if(hart_if) {
9960
for(size_t i = arch::pmpaddr0; i <= arch::pmpaddr15; ++i) {
100-
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain);
101-
hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_plain);
61+
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_pmpaddr);
62+
hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_pmpaddr);
10263
}
10364
for(size_t i = arch::pmpcfg0; i < arch::pmpcfg0 + 16 / sizeof(reg_t); ++i) {
104-
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain);
65+
hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_pmpcfg);
10566
hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_pmpcfg);
10667
}
10768
}
@@ -116,13 +77,16 @@ template <typename PLAT> struct pmp : public memory_elem {
11677
void set_next(memory_if mem) override { down_stream_mem = mem; }
11778

11879
private:
80+
std::array<reg_t, 16> pmpaddr;
81+
std::array<reg_t, 16 / sizeof(reg_t)> pmpcfg;
82+
11983
iss::status read_mem(const addr_t& addr, unsigned length, uint8_t* data) {
12084
assert((addr.type == iss::address_type::PHYSICAL || is_debug(addr.access)) && "Only physical addresses are expected in pmp");
121-
if(likely(addr.space == arch::traits<PLAT>::MEM) && !pmp_check(addr.access, addr.val, length) && !is_debug(addr.access)) {
122-
hart_if.fault_data = addr;
85+
if(likely(addr.space == arch::traits<PLAT>::MEM || std::numeric_limits<decltype(phys_addr_t::space)>::max()) &&
86+
!pmp_check(addr.access, addr.val, length) && !is_debug(addr.access)) {
12387
if(is_debug(addr.access))
12488
throw trap_access(0, addr.val);
125-
hart_if.reg.trap_state = (1UL << 31) | ((addr.access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1
89+
hart_if.raise_trap(/*trap_id*/ 0, /*cause*/ (addr.access == access_type::FETCH) ? 1 : 5, /*fault_data*/ addr.val);
12690
return iss::Err;
12791
}
12892
return down_stream_mem.rd_mem(addr, length, data);
@@ -131,62 +95,71 @@ template <typename PLAT> struct pmp : public memory_elem {
13195
iss::status write_mem(const addr_t& addr, unsigned length, uint8_t const* data) {
13296
assert((addr.type == iss::address_type::PHYSICAL || is_debug(addr.access)) && "Only physical addresses are expected in pmp");
13397
if(likely(addr.space == arch::traits<PLAT>::MEM) && !pmp_check(addr.access, addr.val, length) && !is_debug(addr.access)) {
134-
hart_if.fault_data = addr;
13598
if(is_debug(addr.access))
13699
throw trap_access(0, addr.val);
137-
hart_if.reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1
100+
hart_if.raise_trap(/*trap_id*/ 0, /*cause*/ 7, /*fault_data*/ addr.val);
138101
return iss::Err;
139102
}
140103
return down_stream_mem.wr_mem(addr, length, data);
141104
}
142105

143-
iss::status read_plain(unsigned addr, reg_t& val) {
144-
val = hart_if.csr[addr];
145-
return iss::Ok;
106+
iss::status read_pmpaddr(unsigned addr, reg_t& val) {
107+
if(addr >= arch::pmpaddr0 && addr <= arch::pmpaddr15) {
108+
val = pmpaddr[addr - arch::pmpaddr0];
109+
return iss::Ok;
110+
}
111+
return iss::Err;
146112
}
147113

148-
iss::status write_plain(unsigned addr, reg_t const& val) {
149-
hart_if.csr[addr] = val;
150-
return iss::Ok;
114+
iss::status write_pmpaddr(unsigned addr, reg_t const& val) {
115+
if(addr >= arch::pmpaddr0 && addr <= arch::pmpaddr15) {
116+
pmpaddr[addr - arch::pmpaddr0] = val;
117+
return iss::Ok;
118+
}
119+
return iss::Err;
151120
}
152121

122+
iss::status read_pmpcfg(unsigned addr, reg_t& val) {
123+
if(addr >= arch::pmpcfg0 && addr < (arch::pmpcfg0 + 16 / sizeof(reg_t))) {
124+
val = pmpaddr[addr - arch::pmpcfg0];
125+
return iss::Ok;
126+
}
127+
return iss::Err;
128+
}
153129
iss::status write_pmpcfg(unsigned addr, reg_t val) {
154-
hart_if.csr[addr] = val & 0x9f9f9f9f;
155-
return iss::Ok;
130+
if(addr >= arch::pmpcfg0 && addr < (arch::pmpcfg0 + 16 / sizeof(reg_t))) {
131+
pmpaddr[addr - arch::pmpcfg0] = val & 0x9f9f9f9f;
132+
any_active = false;
133+
for(size_t i = 0; i < 16; i++) {
134+
auto cfg = pmpcfg[i / cfg_reg_size] >> (i % cfg_reg_size);
135+
any_active |= cfg & PMP_A;
136+
}
137+
return iss::Ok;
138+
}
139+
return iss::Err;
156140
}
157141

158-
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
142+
bool pmp_check(access_type type, uint64_t addr, unsigned len);
159143

160144
protected:
145+
bool any_active = false;
161146
arch::priv_if<reg_t> hart_if;
162147
memory_if down_stream_mem;
163148
};
164149

165-
template <typename PLAT> bool pmp<PLAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
166-
constexpr auto PMP_SHIFT = 2U;
167-
constexpr auto PMP_R = 0x1U;
168-
constexpr auto PMP_W = 0x2U;
169-
constexpr auto PMP_X = 0x4U;
170-
constexpr auto PMP_A = 0x18U;
171-
constexpr auto PMP_L = 0x80U;
172-
constexpr auto PMP_TOR = 0x1U;
173-
constexpr auto PMP_NA4 = 0x2U;
174-
constexpr auto PMP_NAPOT = 0x3U;
150+
template <typename PLAT> bool pmp<PLAT>::pmp_check(access_type type, uint64_t addr, unsigned len) {
151+
if(!any_active)
152+
return true;
175153
reg_t base = 0;
176-
auto any_active = false;
177-
auto const cfg_reg_size = sizeof(reg_t);
178154
for(size_t i = 0; i < 16; i++) {
179-
reg_t tor = hart_if.csr[arch::pmpaddr0 + i] << PMP_SHIFT;
180-
uint8_t cfg = hart_if.csr[arch::pmpcfg0 + (i / cfg_reg_size)] >> (i % cfg_reg_size);
155+
reg_t tor = pmpaddr[i] << PMP_SHIFT;
156+
reg_t cfg = pmpcfg[i / cfg_reg_size] >> (i % cfg_reg_size);
181157
if(cfg & PMP_A) {
182-
any_active = true;
183158
auto pmp_a = (cfg & PMP_A) >> 3;
184159
auto is_tor = pmp_a == PMP_TOR;
185160
auto is_na4 = pmp_a == PMP_NA4;
186-
187-
reg_t mask = (hart_if.csr[arch::pmpaddr0 + i] << 1) | (!is_na4);
161+
reg_t mask = (pmpaddr[i] << 1) | (!is_na4);
188162
mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
189-
190163
// Check each 4-byte sector of the access
191164
auto any_match = false;
192165
auto all_match = true;
@@ -202,7 +175,7 @@ template <typename PLAT> bool pmp<PLAT>::pmp_check(const access_type type, const
202175
// If the PMP matches only a strict subset of the access, fail it
203176
if(!all_match)
204177
return false;
205-
return (hart_if.reg.PRIV == arch::PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) ||
178+
return (hart_if.PRIV == arch::PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) ||
206179
(type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X));
207180
}
208181
}
@@ -239,7 +212,7 @@ template <typename PLAT> bool pmp<PLAT>::pmp_check(const access_type type, const
239212
// }
240213
// tor_base = pmpaddr;
241214
// }
242-
return !any_active || hart_if.reg.PRIV == arch::PRIV_M;
215+
return hart_if.PRIV == arch::PRIV_M;
243216
}
244217

245218
} // namespace mem

0 commit comments

Comments
 (0)