mem: mmap the backing store with MAP_NORESERVE
This patch ensures we can run simulations with very large simulated memories (at least 64 TB based on some quick runs on a Linux workstation). In essence this allows us to efficiently deal with sparse address maps without having to implement a redirection layer in the backing store. This opens up for run-time errors if we eventually exhausts the hosts memory and swap space, but this should hopefully never happen.
This commit is contained in:
parent
57758ca685
commit
e17328a227
4 changed files with 39 additions and 4 deletions
|
@ -56,12 +56,29 @@
|
||||||
#include "mem/abstract_mem.hh"
|
#include "mem/abstract_mem.hh"
|
||||||
#include "mem/physical.hh"
|
#include "mem/physical.hh"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Linux, MAP_NORESERVE allow us to simulate a very large memory
|
||||||
|
* without committing to actually providing the swap space on the
|
||||||
|
* host. On OSX the MAP_NORESERVE flag does not exist, so simply make
|
||||||
|
* it 0.
|
||||||
|
*/
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#ifndef MAP_NORESERVE
|
||||||
|
#define MAP_NORESERVE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
PhysicalMemory::PhysicalMemory(const string& _name,
|
PhysicalMemory::PhysicalMemory(const string& _name,
|
||||||
const vector<AbstractMemory*>& _memories) :
|
const vector<AbstractMemory*>& _memories,
|
||||||
_name(_name), rangeCache(addrMap.end()), size(0)
|
bool mmap_using_noreserve) :
|
||||||
|
_name(_name), rangeCache(addrMap.end()), size(0),
|
||||||
|
mmapUsingNoReserve(mmap_using_noreserve)
|
||||||
{
|
{
|
||||||
|
if (mmap_using_noreserve)
|
||||||
|
warn("Not reserving swap space. May cause SIGSEGV on actual usage\n");
|
||||||
|
|
||||||
// add the memories from the system to the address map as
|
// add the memories from the system to the address map as
|
||||||
// appropriate
|
// appropriate
|
||||||
for (const auto& m : _memories) {
|
for (const auto& m : _memories) {
|
||||||
|
@ -148,6 +165,13 @@ PhysicalMemory::createBackingStore(AddrRange range,
|
||||||
DPRINTF(AddrRanges, "Creating backing store for range %s with size %d\n",
|
DPRINTF(AddrRanges, "Creating backing store for range %s with size %d\n",
|
||||||
range.to_string(), range.size());
|
range.to_string(), range.size());
|
||||||
int map_flags = MAP_ANON | MAP_PRIVATE;
|
int map_flags = MAP_ANON | MAP_PRIVATE;
|
||||||
|
|
||||||
|
// to be able to simulate very large memories, the user can opt to
|
||||||
|
// pass noreserve to mmap
|
||||||
|
if (mmapUsingNoReserve) {
|
||||||
|
map_flags |= MAP_NORESERVE;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(),
|
uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(),
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
map_flags, -1, 0);
|
map_flags, -1, 0);
|
||||||
|
|
|
@ -85,6 +85,9 @@ class PhysicalMemory : public Serializable
|
||||||
// The total memory size
|
// The total memory size
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
|
||||||
|
// Let the user choose if we reserve swap space when calling mmap
|
||||||
|
const bool mmapUsingNoReserve;
|
||||||
|
|
||||||
// The physical memory used to provide the memory in the simulated
|
// The physical memory used to provide the memory in the simulated
|
||||||
// system
|
// system
|
||||||
std::vector<std::pair<AddrRange, uint8_t*>> backingStore;
|
std::vector<std::pair<AddrRange, uint8_t*>> backingStore;
|
||||||
|
@ -112,7 +115,8 @@ class PhysicalMemory : public Serializable
|
||||||
* Create a physical memory object, wrapping a number of memories.
|
* Create a physical memory object, wrapping a number of memories.
|
||||||
*/
|
*/
|
||||||
PhysicalMemory(const std::string& _name,
|
PhysicalMemory(const std::string& _name,
|
||||||
const std::vector<AbstractMemory*>& _memories);
|
const std::vector<AbstractMemory*>& _memories,
|
||||||
|
bool mmap_using_noreserve);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmap all the backing store we have used.
|
* Unmap all the backing store we have used.
|
||||||
|
|
|
@ -59,6 +59,13 @@ class System(MemObject):
|
||||||
"All memories in the system")
|
"All memories in the system")
|
||||||
mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
|
mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
|
||||||
|
|
||||||
|
# When reserving memory on the host, we have the option of
|
||||||
|
# reserving swap space or not (by passing MAP_NORESERVE to
|
||||||
|
# mmap). By enabling this flag, we accomodate cases where a large
|
||||||
|
# (but sparse) memory is simulated.
|
||||||
|
mmap_using_noreserve = Param.Bool(False, "mmap the backing store " \
|
||||||
|
"without reserving swap")
|
||||||
|
|
||||||
# The memory ranges are to be populated when creating the system
|
# The memory ranges are to be populated when creating the system
|
||||||
# such that these can be passed from the I/O subsystem through an
|
# such that these can be passed from the I/O subsystem through an
|
||||||
# I/O bridge or cache
|
# I/O bridge or cache
|
||||||
|
|
|
@ -88,7 +88,7 @@ System::System(Params *p)
|
||||||
loadAddrMask(p->load_addr_mask),
|
loadAddrMask(p->load_addr_mask),
|
||||||
loadAddrOffset(p->load_offset),
|
loadAddrOffset(p->load_offset),
|
||||||
nextPID(0),
|
nextPID(0),
|
||||||
physmem(name() + ".physmem", p->memories),
|
physmem(name() + ".physmem", p->memories, p->mmap_using_noreserve),
|
||||||
memoryMode(p->mem_mode),
|
memoryMode(p->mem_mode),
|
||||||
_cacheLineSize(p->cache_line_size),
|
_cacheLineSize(p->cache_line_size),
|
||||||
workItemsBegin(0),
|
workItemsBegin(0),
|
||||||
|
|
Loading…
Reference in a new issue