diff options
author | Andrew Waterman <andrew@sifive.com> | 2021-02-03 17:57:47 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2021-02-04 03:26:19 -0800 |
commit | 716245f5147995575b927a094c664a32f9335c4c (patch) | |
tree | 3693392d39a2415847a0954844a18c15a30d5997 | |
parent | f8fc5d8c04c1c85e4bf968ed774128bae177d813 (diff) | |
download | spike-716245f5147995575b927a094c664a32f9335c4c.zip spike-716245f5147995575b927a094c664a32f9335c4c.tar.gz spike-716245f5147995575b927a094c664a32f9335c4c.tar.bz2 |
Fix --kernel and --initrd options w.r.t. sparse mem_t implementation
For some reason, the old accessors for the non-sparse version were left
dangling. These methods are used by the --kernel and --initrd options,
and so those options were just broken.
This also fixes a memory leak and refactors the implementation a bit.
-rw-r--r-- | riscv/devices.cc | 53 | ||||
-rw-r--r-- | riscv/devices.h | 25 | ||||
-rw-r--r-- | riscv/sim.cc | 2 | ||||
-rw-r--r-- | spike_main/spike.cc | 11 |
4 files changed, 60 insertions, 31 deletions
diff --git a/riscv/devices.cc b/riscv/devices.cc index 6c78456..fb476ec 100644 --- a/riscv/devices.cc +++ b/riscv/devices.cc @@ -1,5 +1,6 @@ #include "devices.h" #include "mmu.h" +#include <stdexcept> void bus_t::add_device(reg_t addr, abstract_device_t* dev) { @@ -90,17 +91,49 @@ bool mmio_plugin_device_t::store(reg_t addr, size_t len, const uint8_t* bytes) return (*plugin.store)(user_data, addr, len, bytes); } -char* mem_t::contents() { - return data; +mem_t::mem_t(reg_t size) + : sz(size) +{ + if (size == 0 || size % PGSIZE != 0) + throw std::runtime_error("memory size must be a positive multiple of 4 KiB"); +} + +mem_t::~mem_t() +{ + for (auto& entry : sparse_memory_map) + free(entry.second); +} + +bool mem_t::load_store(reg_t addr, size_t len, uint8_t* bytes, bool store) +{ + if (addr + len < addr || addr + len > sz) + return false; + + while (len > 0) { + auto n = std::min(PGSIZE - (addr % PGSIZE), len); + + if (store) + memcpy(this->contents(addr), bytes, n); + else + memcpy(bytes, this->contents(addr), n); + + addr += n; + bytes += n; + len -= n; + } + + return true; } char* mem_t::contents(reg_t addr) { - reg_t pg_idx = addr & ~reg_t(PGSIZE - 1); - auto search = acc_tbl.find(pg_idx); - if (search == acc_tbl.end() || !search->second.second) { - char* mem_ptr = (char*)calloc(PGSIZE, sizeof(char)); - acc_tbl[pg_idx] = std::make_pair(mem_ptr, true); - } - auto offset = addr & (PGSIZE - 1); - return acc_tbl[pg_idx].first + offset; + reg_t ppn = addr >> PGSHIFT, pgoff = addr % PGSIZE; + auto search = sparse_memory_map.find(ppn); + if (search == sparse_memory_map.end()) { + auto res = (char*)calloc(PGSIZE, 1); + if (res == nullptr) + throw std::bad_alloc(); + sparse_memory_map[ppn] = res; + return res + pgoff; + } + return search->second + pgoff; } diff --git a/riscv/devices.h b/riscv/devices.h index 82aab89..2003d17 100644 --- a/riscv/devices.h +++ b/riscv/devices.h @@ -7,7 +7,6 @@ #include <string> #include <map> #include <vector> -#include <stdexcept> #include <utility> class processor_t; @@ -43,26 +42,20 @@ class rom_device_t : public abstract_device_t { class mem_t : public abstract_device_t { public: - mem_t(size_t size) : len(size) { - if (!size) - throw std::runtime_error("zero bytes of target memory requested"); - data = nullptr; - } + mem_t(reg_t size); mem_t(const mem_t& that) = delete; - ~mem_t() { - free(data); - } + ~mem_t(); - bool load(reg_t addr, size_t len, uint8_t* bytes) { return false; } - bool store(reg_t addr, size_t len, const uint8_t* bytes) { return false; } - char* contents(); + bool load(reg_t addr, size_t len, uint8_t* bytes) { return load_store(addr, len, bytes, false); } + bool store(reg_t addr, size_t len, const uint8_t* bytes) { return load_store(addr, len, const_cast<uint8_t*>(bytes), true); } char* contents(reg_t addr); - size_t size() { return len; } + reg_t size() { return sz; } private: - std::map<reg_t, std::pair<char*, bool>> acc_tbl; - char* data; - size_t len; + bool load_store(reg_t addr, size_t len, uint8_t* bytes, bool store); + + std::map<reg_t, char*> sparse_memory_map; + reg_t sz; }; class clint_t : public abstract_device_t { diff --git a/riscv/sim.cc b/riscv/sim.cc index 73d2b45..e9e61c5 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -353,7 +353,7 @@ char* sim_t::addr_to_mem(reg_t addr) { auto desc = bus.find_device(addr); if (auto mem = dynamic_cast<mem_t*>(desc.second)) if (addr - desc.first < mem->size()) - return mem->contents(addr); + return mem->contents(addr - desc.first); return NULL; } diff --git a/spike_main/spike.cc b/spike_main/spike.cc index b86f829..94b35c5 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -89,11 +89,14 @@ static std::ifstream::pos_type get_file_size(const char *filename) } static void read_file_bytes(const char *filename,size_t fileoff, - char *read_buf, size_t read_sz) + mem_t* mem, size_t memoff, size_t read_sz) { std::ifstream in(filename, std::ios::in | std::ios::binary); in.seekg(fileoff, std::ios::beg); - in.read(read_buf, read_sz); + + std::vector<char> read_buf(read_sz, 0); + in.read(&read_buf[0], read_sz); + mem->store(memoff, read_sz, (uint8_t*)&read_buf[0]); } bool sort_mem_region(const std::pair<reg_t, mem_t*> &a, @@ -374,7 +377,7 @@ int main(int argc, char** argv) kernel_offset = 0x400000; for (auto& m : mems) { if (kernel_size && (kernel_offset + kernel_size) < m.second->size()) { - read_file_bytes(kernel, 0, m.second->contents() + kernel_offset, kernel_size); + read_file_bytes(kernel, 0, m.second, kernel_offset, kernel_size); break; } } @@ -386,7 +389,7 @@ int main(int argc, char** argv) if (initrd_size && (initrd_size + 0x1000) < m.second->size()) { initrd_end = m.first + m.second->size() - 0x1000; initrd_start = initrd_end - initrd_size; - read_file_bytes(initrd, 0, m.second->contents() + (initrd_start - m.first), initrd_size); + read_file_bytes(initrd, 0, m.second, initrd_start - m.first, initrd_size); break; } } |