aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2021-02-03 17:57:47 -0800
committerAndrew Waterman <andrew@sifive.com>2021-02-04 03:26:19 -0800
commit716245f5147995575b927a094c664a32f9335c4c (patch)
tree3693392d39a2415847a0954844a18c15a30d5997
parentf8fc5d8c04c1c85e4bf968ed774128bae177d813 (diff)
downloadspike-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.cc53
-rw-r--r--riscv/devices.h25
-rw-r--r--riscv/sim.cc2
-rw-r--r--spike_main/spike.cc11
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;
}
}