# Node ID 04bf0f731f998075fb1573842ddc6a8253f4fda2 # Parent 704b0198f747b766b839c577614eb2924fd1dfee 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,32 @@ 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); + + AddrRange this_range = memories[slot].range; + bool duplicated = false; + for (int other_slot(0); other_slot < memories.size(); ++other_slot) { + AddrRange other_range = memories[other_slot].range; + if (this_range == other_range && + (memories[slot].inAddrMap && + !memories[other_slot].inAddrMap)) { + warn("KVM: detected two memory regions with the same range," + " one not visible in the global address map. Assume that" + " the not visible range is the Ruby access backing" + " store and don't map the other."); + duplicated = true; + break; + } + } + if (duplicated) + 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", @@ -358,8 +377,25 @@ KvmVM::delayedStartup() "a KVM VM.\n"); } - const MemSlot slot = allocMemSlot(range.size()); - setupMemSlot(slot, pmem, range.start(), 0/* flags */); + AddrRangeList ranges; + if (range.intersects(AddrRange(0xFFF00000, 0xFFFFFFFF))) { + DPRINTF(Kvm, "Splitting address range that contains reserved " + "values."); + // We can ignore the other AddrRange fields because we've + // established above that the range isn't interleaved. + ranges.push_back(AddrRange(range.start(), 0xFF0FFFFF)); + ranges.push_back(AddrRange(0x100000000, range.end())); + } else { + ranges.push_back(range); + } + + for (auto r : ranges) { + // At exactly 4GB, the higher split range will have 0 size. + if (r.size() != 0) { + const MemSlot slot = allocMemSlot(r.size()); + setupMemSlot(slot, pmem, r.start(), 0/* flags */); + } + } } else { DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start()); hack("KVM: Zero memory handled as IO\n"); 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,39 @@ 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 is_in_addr_map) + : range(range), pmem(pmem), inAddrMap(is_in_addr_map) + {} + + /** + * The address range covered. + */ + AddrRange range; + + /** + * The memories this range maps to. + */ + uint8_t* pmem; + + /** + * Is this range in the global address map. Used by Kvm to avoid + * mapping overlapping regions when the Ruby access backing store + * is in use. + */ + bool inAddrMap; +}; + +/** * 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 +123,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 +138,11 @@ class PhysicalMemory : public Serializab * * @param range The address range covered * @param memories The memories this range maps to + * @param is_in_addr_map Is this range in the global address map */ void createBackingStore(AddrRange range, - const std::vector& _memories); + const std::vector& _memories, + bool is_in_addr_map); public: @@ -167,7 +202,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 @@ -111,7 +111,7 @@ 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, false); } } @@ -132,7 +132,7 @@ 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, true); intlv_ranges.clear(); curr_memories.clear(); } @@ -140,7 +140,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, true); } } } @@ -149,13 +149,14 @@ 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, true); } } void PhysicalMemory::createBackingStore(AddrRange range, - const vector& _memories) + const vector& _memories, + bool is_in_addr_map) { panic_if(range.interleaved(), "Cannot create backing store for interleaved range %s\n", @@ -184,7 +185,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, is_in_addr_map)); // point the memories to their backing store for (const auto& m : _memories) { @@ -198,7 +199,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 +315,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 +408,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 diff --git a/src/sim/system.cc b/src/sim/system.cc --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -327,9 +327,11 @@ System::allocPhysPages(int npages) Addr next_return_addr = pagePtr << PageShift; + AddrRange reservedRange(0xfff00000, 0xfff0ffff); AddrRange m5opRange(0xffff0000, 0xffffffff); - if (m5opRange.contains(next_return_addr)) { - warn("Reached m5ops MMIO region\n"); + if (reservedRange.contains(next_return_addr) || + m5opRange.contains(next_return_addr)) { + warn("Reached m5ops MMIO or another reserved region\n"); return_addr = 0xffffffff; pagePtr = 0xffffffff >> PageShift; }