# Node ID d7b3eddc8bfea43a2261c3e52b4ddadd505de614 # Parent d4aeed880fa4a2234231271109bd7d8f1a1af34f diff --git a/src/cpu/kvm/vm.cc b/src/cpu/kvm/vm.cc --- a/src/cpu/kvm/vm.cc +++ b/src/cpu/kvm/vm.cc @@ -341,13 +341,18 @@ KvmVM::cpuStartup() void KvmVM::delayedStartup() { - const std::vector >&memories( + const std::vector &memories( system->getPhysMem().getBackingStore()); DPRINTF(Kvm, "Mapping %i memory region(s)\n", memories.size()); for (int slot(0); slot < memories.size(); ++slot) { - const AddrRange &range(memories[slot].first); - void *pmem(memories[slot].second); + if (!memories[slot].kvmMap) { + DPRINTF(Kvm, "Skipping region marked as not usable by KVM\n"); + continue; + } + + const AddrRange &range(memories[slot].range); + void *pmem(memories[slot].pmem); if (pmem) { DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n", diff --git a/src/mem/AbstractMemory.py b/src/mem/AbstractMemory.py --- a/src/mem/AbstractMemory.py +++ b/src/mem/AbstractMemory.py @@ -57,6 +57,12 @@ class AbstractMemory(MemObject): # e.g. by the testers that use shadow memories as a reference in_addr_map = Param.Bool(True, "Memory part of the global address map") + # When KVM acceleration is used, memory is mapped into the guest process + # address space and accessed directly. Some memories may need to be + # excluded from this mapping if they overlap with other memory ranges or + # are not accessible by the CPU. + kvm_map = Param.Bool(True, "Should KVM map this memory for the guest") + # Should the bootloader include this memory when passing # configuration information about the physical memory layout to # the kernel, e.g. using ATAG or ACPI diff --git a/src/mem/abstract_mem.hh b/src/mem/abstract_mem.hh --- a/src/mem/abstract_mem.hh +++ b/src/mem/abstract_mem.hh @@ -116,6 +116,9 @@ class AbstractMemory : public MemObject // Should the memory appear in the global address map bool inAddrMap; + // Should KVM map this memory for the guest + bool kvmMap; + std::list lockedAddrList; // helper function for checkLockedAddrs(): we really want to @@ -283,6 +286,14 @@ class AbstractMemory : public MemObject bool isInAddrMap() const { return inAddrMap; } /** + * When shadow memories are in use, KVM may want to make one or the other, + * but cannot map both into the guest address space. + * + * @return if this memory should be mapped into the KVM guest address space + */ + bool isKvmMap() const { return kvmMap; } + + /** * Perform an untimed memory access and update all the state * (e.g. locked addresses) and statistics accordingly. The packet * is turned into a response if required. diff --git a/src/mem/abstract_mem.cc b/src/mem/abstract_mem.cc --- a/src/mem/abstract_mem.cc +++ b/src/mem/abstract_mem.cc @@ -57,7 +57,7 @@ using namespace std; AbstractMemory::AbstractMemory(const Params *p) : MemObject(p), range(params()->range), pmemAddr(NULL), confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map), - _system(NULL) + kvmMap(p->kvm_map), _system(NULL) { } diff --git a/src/mem/physical.hh b/src/mem/physical.hh --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -49,6 +49,38 @@ class AbstractMemory; /** + * A single entry for the backing store. + */ +class BackingStoreEntry +{ + public: + + /** + * Create a backing store entry. Don't worry about managing the memory + * pointers, because PhysicalMemory is responsible for that. + */ + BackingStoreEntry(AddrRange range, uint8_t* pmem, bool kvm_map) + : range(range), pmem(pmem), kvmMap(kvm_map) + {} + + /** + * The address range covered. + */ + AddrRange range; + + /** + * The memories this range maps to. + */ + uint8_t* pmem; + + /** + * Used by Kvm to avoid mapping overlapping regions. + */ + + bool kvmMap; +}; + +/** * The physical memory encapsulates all memories in the system and * provides basic functionality for accessing those memories without * going through the memory system and interconnect. @@ -90,7 +122,7 @@ class PhysicalMemory : public Serializab // The physical memory used to provide the memory in the simulated // system - std::vector> backingStore; + std::vector backingStore; // Prevent copying PhysicalMemory(const PhysicalMemory&); @@ -105,9 +137,11 @@ class PhysicalMemory : public Serializab * * @param range The address range covered * @param memories The memories this range maps to + * @param kvm_map Should KVM map this memory for the guest */ void createBackingStore(AddrRange range, - const std::vector& _memories); + const std::vector& _memories, + bool kvm_map); public: @@ -167,7 +201,7 @@ class PhysicalMemory : public Serializab * * @return Pointers to the memory backing store */ - std::vector> getBackingStore() const + std::vector getBackingStore() const { return backingStore; } /** diff --git a/src/mem/physical.cc b/src/mem/physical.cc --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -79,13 +79,18 @@ PhysicalMemory::PhysicalMemory(const str 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 // appropriate + bool kvm_addr_map = true; for (const auto& m : _memories) { // only add the memory if it is part of the global address map if (m->isInAddrMap()) { memories.push_back(m); + if (!m->isKvmMap()) + kvm_addr_map = false; + // calculate the total size once and for all size += m->size(); @@ -111,7 +116,8 @@ PhysicalMemory::PhysicalMemory(const str // memories are allowed to overlap in the logic address // map vector unmapped_mems{m}; - createBackingStore(m->getAddrRange(), unmapped_mems); + createBackingStore(m->getAddrRange(), unmapped_mems, + m->isKvmMap()); } } @@ -132,7 +138,8 @@ PhysicalMemory::PhysicalMemory(const str if (!intlv_ranges.empty() && !intlv_ranges.back().mergesWith(r.first)) { AddrRange merged_range(intlv_ranges); - createBackingStore(merged_range, curr_memories); + createBackingStore(merged_range, curr_memories, + curr_memories.front()->isKvmMap()); intlv_ranges.clear(); curr_memories.clear(); } @@ -140,7 +147,7 @@ PhysicalMemory::PhysicalMemory(const str curr_memories.push_back(r.second); } else { vector single_memory{r.second}; - createBackingStore(r.first, single_memory); + createBackingStore(r.first, single_memory, kvm_addr_map); } } } @@ -149,13 +156,15 @@ PhysicalMemory::PhysicalMemory(const str // ahead and do it if (!intlv_ranges.empty()) { AddrRange merged_range(intlv_ranges); - createBackingStore(merged_range, curr_memories); + createBackingStore(merged_range, curr_memories, + curr_memories.front()->isKvmMap()); } } void PhysicalMemory::createBackingStore(AddrRange range, - const vector& _memories) + const vector& _memories, + bool kvm_map) { panic_if(range.interleaved(), "Cannot create backing store for interleaved range %s\n", @@ -184,7 +193,7 @@ PhysicalMemory::createBackingStore(AddrR // remember this backing store so we can checkpoint it and unmap // it appropriately - backingStore.push_back(make_pair(range, pmem)); + backingStore.push_back(BackingStoreEntry(range, pmem, kvm_map)); // point the memories to their backing store for (const auto& m : _memories) { @@ -198,7 +207,7 @@ PhysicalMemory::~PhysicalMemory() { // unmap the backing store for (auto& s : backingStore) - munmap((char*)s.second, s.first.size()); + munmap((char*)s.pmem, s.range.size()); } bool @@ -314,7 +323,7 @@ PhysicalMemory::serialize(CheckpointOut // store each backing store memory segment in a file for (auto& s : backingStore) { ScopedCheckpointSection sec(cp, csprintf("store%d", store_id)); - serializeStore(cp, store_id++, s.first, s.second); + serializeStore(cp, store_id++, s.range, s.pmem); } } @@ -407,8 +416,8 @@ PhysicalMemory::unserializeStore(Checkpo fatal("Can't open physical memory checkpoint file '%s'", filename); // we've already got the actual backing store mapped - uint8_t* pmem = backingStore[store_id].second; - AddrRange range = backingStore[store_id].first; + uint8_t* pmem = backingStore[store_id].pmem; + AddrRange range = backingStore[store_id].range; long range_size; UNSERIALIZE_SCALAR(range_size); diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -250,6 +250,10 @@ Sequencer::markRemoved() m_outstanding_count--; assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); + + if (drainState() == DrainState::Draining) { + testDrainComplete(); + } } void