aboutsummaryrefslogtreecommitdiff
path: root/riscv/mmu.cc
diff options
context:
space:
mode:
authorScott Johnson <scott.johnson@arilinc.com>2023-03-03 05:22:52 -0800
committerAndrew Waterman <andrew@sifive.com>2023-03-04 17:30:31 -0800
commit1951f80361e7cb82a8baa975183d036e8a944bd2 (patch)
tree6f2e6ca06d58f833204989cb01cc8d59c9fffab8 /riscv/mmu.cc
parent360e55535da0d3a0f8123bbe9ca4b2947950e8ea (diff)
downloadriscv-isa-sim-1951f80361e7cb82a8baa975183d036e8a944bd2.zip
riscv-isa-sim-1951f80361e7cb82a8baa975183d036e8a944bd2.tar.gz
riscv-isa-sim-1951f80361e7cb82a8baa975183d036e8a944bd2.tar.bz2
Don't issue misaligned or non-power-of-2 MMIO accesses
@aswaterman explains: Rather than requiring each MMIO device to support arbitrary sizes and alignments, decompose MMIO misaligned loads and stores in such a way as to guarantee their constituent parts are always aligned. (Specifically, they now always decompose to a sequence of one-byte accesses.) This is not a semantic change for main-memory accesses, but it is a semantic change for I/O devices. It makes them more realistic, in that most bus standards don't support non-power-of-2-sized accesses.
Diffstat (limited to 'riscv/mmu.cc')
-rw-r--r--riscv/mmu.cc31
1 files changed, 24 insertions, 7 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index fc80dfa..8ce7a3a 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -147,18 +147,35 @@ bool mmu_t::mmio_fetch(reg_t paddr, size_t len, uint8_t* bytes)
bool mmu_t::mmio_load(reg_t paddr, size_t len, uint8_t* bytes)
{
- if (!mmio_ok(paddr, LOAD))
- return false;
-
- return sim->mmio_load(paddr, len, bytes);
+ return mmio(paddr, len, bytes, LOAD);
}
bool mmu_t::mmio_store(reg_t paddr, size_t len, const uint8_t* bytes)
{
- if (!mmio_ok(paddr, STORE))
- return false;
+ return mmio(paddr, len, const_cast<uint8_t*>(bytes), STORE);
+}
+
+bool mmu_t::mmio(reg_t paddr, size_t len, uint8_t* bytes, access_type type)
+{
+ bool power_of_2 = (len & (len - 1)) == 0;
+ bool naturally_aligned = (paddr & (len - 1)) == 0;
+
+ if (power_of_2 && naturally_aligned) {
+ if (!mmio_ok(paddr, type))
+ return false;
+
+ if (type == STORE)
+ return sim->mmio_store(paddr, len, bytes);
+ else
+ return sim->mmio_load(paddr, len, bytes);
+ }
- return sim->mmio_store(paddr, len, bytes);
+ for (size_t i = 0; i < len; i++) {
+ if (!mmio(paddr + i, 1, bytes + i, type))
+ return false;
+ }
+
+ return true;
}
void mmu_t::check_triggers(triggers::operation_t operation, reg_t address, std::optional<reg_t> data)