Browse Source

Merge pull request #1268 from riscv-software-src/more-plic-fixes

Don't issue misaligned or non-power-of-2 MMIO accesses
pull/1272/head
Andrew Waterman 3 years ago
committed by GitHub
parent
commit
6d6858ce7e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      riscv/clint.cc
  2. 17
      riscv/devices.h
  3. 31
      riscv/mmu.cc
  4. 1
      riscv/mmu.h

12
riscv/clint.cc

@ -71,12 +71,14 @@ bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
return store(addr, 4, bytes) && store(addr + 4, 4, bytes + 4);
}
msip_t msip = 0;
write_little_endian_reg(&msip, addr, len, bytes);
if (addr % sizeof(msip_t) == 0) { // ignore in-between bytes
msip_t msip = 0;
write_little_endian_reg(&msip, addr, len, bytes);
const auto hart_id = (addr - MSIP_BASE) / sizeof(msip_t);
if (sim->get_harts().count(hart_id))
sim->get_harts().at(hart_id)->state.mip->backdoor_write_with_mask(MIP_MSIP, msip & 1 ? MIP_MSIP : 0);
const auto hart_id = (addr - MSIP_BASE) / sizeof(msip_t);
if (sim->get_harts().count(hart_id))
sim->get_harts().at(hart_id)->state.mip->backdoor_write_with_mask(MIP_MSIP, msip & 1 ? MIP_MSIP : 0);
}
} else if (addr >= MTIMECMP_BASE && addr < MTIME_BASE) {
const auto hart_id = (addr - MTIMECMP_BASE) / sizeof(mtimecmp_t);
if (sim->get_harts().count(hart_id))

17
riscv/devices.h

@ -82,18 +82,17 @@ class clint_t : public abstract_device_t {
struct plic_context_t {
plic_context_t(processor_t* proc, bool mmode)
: proc(proc), mmode(mmode), priority_threshold(0), enable{}, pending{},
pending_priority{}, claimed{}
: proc(proc), mmode(mmode)
{}
processor_t *proc;
bool mmode;
processor_t *proc;
bool mmode;
uint8_t priority_threshold;
uint32_t enable[PLIC_MAX_DEVICES/32];
uint32_t pending[PLIC_MAX_DEVICES/32];
uint8_t pending_priority[PLIC_MAX_DEVICES];
uint32_t claimed[PLIC_MAX_DEVICES/32];
uint8_t priority_threshold {};
uint32_t enable[PLIC_MAX_DEVICES/32] {};
uint32_t pending[PLIC_MAX_DEVICES/32] {};
uint8_t pending_priority[PLIC_MAX_DEVICES] {};
uint32_t claimed[PLIC_MAX_DEVICES/32] {};
};
class plic_t : public abstract_device_t, public abstract_interrupt_controller_t {

31
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)

1
riscv/mmu.h

@ -339,6 +339,7 @@ private:
bool mmio_fetch(reg_t paddr, size_t len, uint8_t* bytes);
bool mmio_load(reg_t paddr, size_t len, uint8_t* bytes);
bool mmio_store(reg_t paddr, size_t len, const uint8_t* bytes);
bool mmio(reg_t paddr, size_t len, uint8_t* bytes, access_type type);
bool mmio_ok(reg_t paddr, access_type type);
void check_triggers(triggers::operation_t operation, reg_t address, std::optional<reg_t> data = std::nullopt);
reg_t translate(reg_t addr, reg_t len, access_type type, uint32_t xlate_flags);

Loading…
Cancel
Save