Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lift restriction on physical-address size #1788

Merged
merged 4 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions riscv/cfg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ bool mem_cfg_t::check_if_supported(reg_t base, reg_t size)
// the regions in the first place, but we have them here to make sure that
// we can't end up describing memory regions that don't make sense. They
// ask that the page size is a multiple of the minimum page size, that the
// page is aligned to the minimum page size, that the page is non-empty and
// that the top address is still representable in a reg_t.
// page is aligned to the minimum page size, that the page is non-empty,
// that the size doesn't overflow size_t, and that the top address is still
// representable in a reg_t.
//
// Note: (base + size == 0) part of the assertion is to handle cases like
// { base = 0xffff_ffff_ffff_f000, size: 0x1000 }
return (size % PGSIZE == 0) &&
(base % PGSIZE == 0) &&
(size_t(size) == size) &&
(size > 0) &&
((base + size > base) || (base + size == 0));
}
Expand Down
2 changes: 1 addition & 1 deletion riscv/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#define PGSHIFT 12
const reg_t PGSIZE = 1 << PGSHIFT;
const reg_t PGMASK = ~(PGSIZE-1);
#define MAX_PADDR_BITS 56 // imposed by Sv39 / Sv48
#define MAX_PADDR_BITS 64

struct insn_fetch_t
{
Expand Down
3 changes: 2 additions & 1 deletion riscv/sim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ void sim_t::set_procs_debug(bool value)

static bool paddr_ok(reg_t addr)
{
return (addr >> MAX_PADDR_BITS) == 0;
static_assert(MAX_PADDR_BITS == 8 * sizeof(addr));
return true;
}

bool sim_t::mmio_load(reg_t paddr, size_t len, uint8_t* bytes)
Expand Down
68 changes: 29 additions & 39 deletions spike_main/spike.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,31 @@ merge_overlapping_memory_regions(std::vector<mem_cfg_t> mems)
return merged_mem;
}

static mem_cfg_t create_mem_region(unsigned long long base, unsigned long long size)
{
// page-align base and size
auto base0 = base, size0 = size;
size += base0 % PGSIZE;
base -= base0 % PGSIZE;
if (size % PGSIZE != 0)
size += PGSIZE - size % PGSIZE;

if (size != size0) {
fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n"
"to the %ld KiB page size: [0x%llX, 0x%llX]\n",
base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1);
}

if (!mem_cfg_t::check_if_supported(base, size)) {
fprintf(stderr, "Unsupported memory region "
"{base = 0x%llX, size = 0x%llX} specified\n",
base, size);
exit(EXIT_FAILURE);
}

return mem_cfg_t(base, size);
}

static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
{
std::vector<mem_cfg_t> res;
Expand All @@ -200,9 +225,9 @@ static std::vector<mem_cfg_t> parse_mem_layout(const char* arg)
auto mb = strtoull(arg, &p, 0);
if (*p == 0) {
reg_t size = reg_t(mb) << 20;
if (size != (size_t)size)
throw std::runtime_error("Size would overflow size_t");
res.push_back(mem_cfg_t(reg_t(DRAM_BASE), size));
if ((size >> 20) != mb)
throw std::runtime_error("Memory size too large");
res.push_back(create_mem_region(DRAM_BASE, size));
return res;
}

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

// page-align base and size
auto base0 = base, size0 = size;
size += base0 % PGSIZE;
base -= base0 % PGSIZE;
if (size % PGSIZE != 0)
size += PGSIZE - size % PGSIZE;

if (size != size0) {
fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n"
"to the %ld KiB page size: [0x%llX, 0x%llX]\n",
base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1);
}

if (!mem_cfg_t::check_if_supported(base, size)) {
fprintf(stderr, "Unsupported memory region "
"{base = 0x%llX, size = 0x%llX} specified\n",
base, size);
exit(EXIT_FAILURE);
}

const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull;
assert(max_allowed_pa <= std::numeric_limits<reg_t>::max());
mem_cfg_t mem_region(base, size);
if (mem_region.get_inclusive_end() > max_allowed_pa) {
int bits_required = 64 - clz(mem_region.get_inclusive_end());
fprintf(stderr, "Unsupported memory region "
"{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified,"
" which requires %d bits of physical address\n"
" The largest accessible physical address "
"is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n",
mem_region.get_base(), mem_region.get_size(), bits_required,
max_allowed_pa, MAX_PADDR_BITS);
exit(EXIT_FAILURE);
}

res.push_back(mem_region);
res.push_back(create_mem_region(base, size));

if (!*p)
break;
Expand Down
Loading