aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2024-09-02 18:33:59 -0500
committerGitHub <noreply@github.com>2024-09-02 18:33:59 -0500
commit2538c1fb203056fcdb96ea0f06dc1fbde5da73a5 (patch)
tree004e8d6e8e83f240feb4d4505a218e66adda8d5f
parent3c5b1bb09ef6daf4146e311d1303cb8dd67c5ff3 (diff)
parent52f045d9ba21fe0552c1475e4171fddc3c13c5e3 (diff)
downloadriscv-isa-sim-2538c1fb203056fcdb96ea0f06dc1fbde5da73a5.zip
riscv-isa-sim-2538c1fb203056fcdb96ea0f06dc1fbde5da73a5.tar.gz
riscv-isa-sim-2538c1fb203056fcdb96ea0f06dc1fbde5da73a5.tar.bz2
Merge pull request #1788 from riscv-software-src/support-larger-addresses
Lift restriction on physical-address size
-rw-r--r--riscv/cfg.cc6
-rw-r--r--riscv/mmu.h2
-rw-r--r--riscv/sim.cc3
-rw-r--r--spike_main/spike.cc68
4 files changed, 36 insertions, 43 deletions
diff --git a/riscv/cfg.cc b/riscv/cfg.cc
index 8763240..2f9a229 100644
--- a/riscv/cfg.cc
+++ b/riscv/cfg.cc
@@ -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));
}
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 0aa1f96..1047a71 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -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
{
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 115fc0c..d47ceae 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -336,7 +336,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)
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index 1a298f2..d656d64 100644
--- a/spike_main/spike.cc
+++ b/spike_main/spike.cc
@@ -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;
@@ -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;
}
@@ -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;