Skip to content

Commit 2538c1f

Browse files
authored
Merge pull request riscv-software-src#1788 from riscv-software-src/support-larger-addresses
Lift restriction on physical-address size
2 parents 3c5b1bb + 52f045d commit 2538c1f

File tree

4 files changed

+36
-43
lines changed

4 files changed

+36
-43
lines changed

riscv/cfg.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ bool mem_cfg_t::check_if_supported(reg_t base, reg_t size)
1818
// the regions in the first place, but we have them here to make sure that
1919
// we can't end up describing memory regions that don't make sense. They
2020
// ask that the page size is a multiple of the minimum page size, that the
21-
// page is aligned to the minimum page size, that the page is non-empty and
22-
// that the top address is still representable in a reg_t.
21+
// page is aligned to the minimum page size, that the page is non-empty,
22+
// that the size doesn't overflow size_t, and that the top address is still
23+
// representable in a reg_t.
2324
//
2425
// Note: (base + size == 0) part of the assertion is to handle cases like
2526
// { base = 0xffff_ffff_ffff_f000, size: 0x1000 }
2627
return (size % PGSIZE == 0) &&
2728
(base % PGSIZE == 0) &&
29+
(size_t(size) == size) &&
2830
(size > 0) &&
2931
((base + size > base) || (base + size == 0));
3032
}

riscv/mmu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#define PGSHIFT 12
2020
const reg_t PGSIZE = 1 << PGSHIFT;
2121
const reg_t PGMASK = ~(PGSIZE-1);
22-
#define MAX_PADDR_BITS 56 // imposed by Sv39 / Sv48
22+
#define MAX_PADDR_BITS 64
2323

2424
struct insn_fetch_t
2525
{

riscv/sim.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,8 @@ void sim_t::set_procs_debug(bool value)
336336

337337
static bool paddr_ok(reg_t addr)
338338
{
339-
return (addr >> MAX_PADDR_BITS) == 0;
339+
static_assert(MAX_PADDR_BITS == 8 * sizeof(addr));
340+
return true;
340341
}
341342

342343
bool sim_t::mmio_load(reg_t paddr, size_t len, uint8_t* bytes)

spike_main/spike.cc

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,31 @@ merge_overlapping_memory_regions(std::vector<mem_cfg_t> mems)
191191
return merged_mem;
192192
}
193193

194+
static mem_cfg_t create_mem_region(unsigned long long base, unsigned long long size)
195+
{
196+
// page-align base and size
197+
auto base0 = base, size0 = size;
198+
size += base0 % PGSIZE;
199+
base -= base0 % PGSIZE;
200+
if (size % PGSIZE != 0)
201+
size += PGSIZE - size % PGSIZE;
202+
203+
if (size != size0) {
204+
fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n"
205+
"to the %ld KiB page size: [0x%llX, 0x%llX]\n",
206+
base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1);
207+
}
208+
209+
if (!mem_cfg_t::check_if_supported(base, size)) {
210+
fprintf(stderr, "Unsupported memory region "
211+
"{base = 0x%llX, size = 0x%llX} specified\n",
212+
base, size);
213+
exit(EXIT_FAILURE);
214+
}
215+
216+
return mem_cfg_t(base, size);
217+
}
218+
194219
static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
195220
{
196221
std::vector<mem_cfg_t> res;
@@ -200,9 +225,9 @@ static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
200225
auto mb = strtoull(arg, &p, 0);
201226
if (*p == 0) {
202227
reg_t size = reg_t(mb) << 20;
203-
if (size != (size_t)size)
204-
throw std::runtime_error("Size would overflow size_t");
205-
res.push_back(mem_cfg_t(reg_t(DRAM_BASE), size));
228+
if ((size >> 20) != mb)
229+
throw std::runtime_error("Memory size too large");
230+
res.push_back(create_mem_region(DRAM_BASE, size));
206231
return res;
207232
}
208233

@@ -213,42 +238,7 @@ static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
213238
help();
214239
auto size = strtoull(p + 1, &p, 0);
215240

216-
// page-align base and size
217-
auto base0 = base, size0 = size;
218-
size += base0 % PGSIZE;
219-
base -= base0 % PGSIZE;
220-
if (size % PGSIZE != 0)
221-
size += PGSIZE - size % PGSIZE;
222-
223-
if (size != size0) {
224-
fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n"
225-
"to the %ld KiB page size: [0x%llX, 0x%llX]\n",
226-
base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1);
227-
}
228-
229-
if (!mem_cfg_t::check_if_supported(base, size)) {
230-
fprintf(stderr, "Unsupported memory region "
231-
"{base = 0x%llX, size = 0x%llX} specified\n",
232-
base, size);
233-
exit(EXIT_FAILURE);
234-
}
235-
236-
const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull;
237-
assert(max_allowed_pa <= std::numeric_limits<reg_t>::max());
238-
mem_cfg_t mem_region(base, size);
239-
if (mem_region.get_inclusive_end() > max_allowed_pa) {
240-
int bits_required = 64 - clz(mem_region.get_inclusive_end());
241-
fprintf(stderr, "Unsupported memory region "
242-
"{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified,"
243-
" which requires %d bits of physical address\n"
244-
" The largest accessible physical address "
245-
"is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n",
246-
mem_region.get_base(), mem_region.get_size(), bits_required,
247-
max_allowed_pa, MAX_PADDR_BITS);
248-
exit(EXIT_FAILURE);
249-
}
250-
251-
res.push_back(mem_region);
241+
res.push_back(create_mem_region(base, size));
252242

253243
if (!*p)
254244
break;

0 commit comments

Comments
 (0)