changeset 8fc6e7a835d1 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=8fc6e7a835d1
description:
        Let other objects set up memory like regions in a KVM VM.

diffstat:

 src/cpu/kvm/vm.cc |  80 ++++++++++++++++++++++++++++++++++++++++++++++++------
 src/cpu/kvm/vm.hh |  60 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 127 insertions(+), 13 deletions(-)

diffs (221 lines):

diff -r 4e09ae443c96 -r 8fc6e7a835d1 src/cpu/kvm/vm.cc
--- a/src/cpu/kvm/vm.cc Mon Dec 08 04:49:53 2014 -0500
+++ b/src/cpu/kvm/vm.cc Tue Dec 09 21:53:44 2014 -0800
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2014 Google, Inc.
  * Copyright (c) 2012 ARM Limited
  * All rights reserved
  *
@@ -124,6 +125,16 @@
     return checkExtension(KVM_CAP_COALESCED_MMIO);
 }
 
+int
+Kvm::capNumMemSlots() const
+{
+#ifdef KVM_CAP_NR_MEMSLOTS
+    return checkExtension(KVM_CAP_NR_MEMSLOTS);
+#else
+    return 0;
+#endif
+}
+
 bool
 Kvm::capOneReg() const
 {
@@ -288,6 +299,10 @@
       started(false),
       nextVCPUID(0)
 {
+    maxMemorySlot = kvm.capNumMemSlots();
+    /* If we couldn't determine how memory slots there are, guess 32. */
+    if (!maxMemorySlot)
+        maxMemorySlot = 32;
     /* Setup the coalesced MMIO regions */
     for (int i = 0; i < params->coalescedMMIO.size(); ++i)
         coalesceMMIO(params->coalescedMMIO[i]);
@@ -323,7 +338,13 @@
             DPRINTF(Kvm, "Mapping region: 0x%p -> 0x%llx [size: 0x%llx]\n",
                     pmem, range.start(), range.size());
 
-            setUserMemoryRegion(slot, pmem, range, 0 /* flags */);
+            if (range.interleaved()) {
+                panic("Tried to map an interleaved memory range into "
+                      "a KVM VM.\n");
+            }
+
+            const MemSlot slot = allocMemSlot(range.size());
+            setupMemSlot(slot, pmem, range.start(), 0/* flags */);
         } else {
             DPRINTF(Kvm, "Zero-region not mapped: [0x%llx]\n", range.start());
             hack("KVM: Zero memory handled as IO\n");
@@ -331,17 +352,58 @@
     }
 }
 
+const KvmVM::MemSlot
+KvmVM::allocMemSlot(uint64_t size)
+{
+    if (!size)
+        panic("Memory slots must have non-zero size.\n");
+
+    std::vector<MemorySlot>::iterator pos;
+    for (pos = memorySlots.begin(); pos != memorySlots.end(); pos++) {
+        if (!pos->size) {
+            pos->size = size;
+            pos->active = false;
+            return pos->slot;
+        }
+    }
+
+    uint32_t nextSlot = memorySlots.size();
+    if (nextSlot > maxMemorySlot)
+        panic("Out of memory slots.\n");
+
+    MemorySlot slot;
+    slot.size = size;
+    slot.slot = nextSlot;
+    slot.active = false;
+
+    memorySlots.push_back(slot);
+    return MemSlot(slot.slot);
+}
+
 void
-KvmVM::setUserMemoryRegion(uint32_t slot,
-                           void *host_addr, AddrRange guest_range,
-                           uint32_t flags)
+KvmVM::setupMemSlot(const KvmVM::MemSlot num, void *host_addr, Addr guest,
+                    uint32_t flags)
 {
-    if (guest_range.interleaved())
-        panic("Tried to map an interleaved memory range into a KVM VM.\n");
+    MemorySlot &slot = memorySlots.at(num.num);
+    slot.active = true;
+    setUserMemoryRegion(num.num, host_addr, guest, slot.size, flags);
+}
 
-    setUserMemoryRegion(slot, host_addr,
-                        guest_range.start(), guest_range.size(),
-                        flags);
+void
+KvmVM::disableMemSlot(const KvmVM::MemSlot num)
+{
+    MemorySlot &slot = memorySlots.at(num.num);
+    if (slot.active)
+        setUserMemoryRegion(num.num, NULL, 0, 0, 0);
+    slot.active = false;
+}
+
+void
+KvmVM::freeMemSlot(const KvmVM::MemSlot num)
+{
+    disableMemSlot(num.num);
+    MemorySlot &slot = memorySlots.at(num.num);
+    slot.size = 0;
 }
 
 void
diff -r 4e09ae443c96 -r 8fc6e7a835d1 src/cpu/kvm/vm.hh
--- a/src/cpu/kvm/vm.hh Mon Dec 08 04:49:53 2014 -0500
+++ b/src/cpu/kvm/vm.hh Tue Dec 09 21:53:44 2014 -0800
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2014 Google, Inc.
  * Copyright (c) 2012 ARM Limited
  * All rights reserved
  *
@@ -110,6 +111,12 @@
     int capCoalescedMMIO() const;
 
     /**
+     * Attempt to determine how many memory slots are available. If it can't
+     * be determined, this function returns 0.
+     */
+    int capNumMemSlots() const;
+
+    /**
      * Support for reading and writing single registers.
      *
      * @see BaseKvmCPU::getOneReg(), and BaseKvmCPU::setOneReg()
@@ -331,6 +338,42 @@
     bool hasKernelIRQChip() const { return _hasKernelIRQChip; }
     /** @} */
 
+    struct MemSlot
+    {
+        MemSlot(uint32_t _num) : num(_num)
+        {}
+        MemSlot() : num(-1)
+        {}
+
+        int32_t num;
+    };
+
+    /**
+     *  Allocate a memory slot within the VM.
+     */
+    const MemSlot allocMemSlot(uint64_t size);
+
+    /**
+     * Setup a region of physical memory in the guest
+     *
+     * @param slot KVM memory slot ID returned by allocMemSlot
+     * @param host_addr Memory allocation backing the memory
+     * @param guest_addr Address in the guest
+     * @param flags Flags (see the KVM API documentation)
+     */
+    void setupMemSlot(const MemSlot slot, void *host_addr, Addr guest_addr,
+                      uint32_t flags);
+
+    /**
+     * Disable a memory slot.
+     */
+    void disableMemSlot(const MemSlot slot);
+
+    /**
+     *  Free a previously allocated memory slot.
+     */
+    void freeMemSlot(const MemSlot slot);
+
     /** Global KVM interface */
     Kvm kvm;
 
@@ -366,16 +409,12 @@
      * @param slot KVM memory slot ID (must be unique)
      * @param host_addr Memory allocation backing the memory
      * @param guest_addr Address in the guest
-     * @param guest_range Address range used by guest.
      * @param len Size of the allocation in bytes
      * @param flags Flags (see the KVM API documentation)
      */
     void setUserMemoryRegion(uint32_t slot,
                              void *host_addr, Addr guest_addr,
                              uint64_t len, uint32_t flags);
-    void setUserMemoryRegion(uint32_t slot,
-                             void *host_addr, AddrRange guest_range,
-                             uint32_t flags);
     /** @} */
 
     /**
@@ -437,6 +476,19 @@
 
     /** Next unallocated vCPU ID */
     long nextVCPUID;
+
+    /**
+     *  Structures tracking memory slots.
+     */
+    class MemorySlot
+    {
+      public:
+        uint64_t size;
+        uint32_t slot;
+        bool active;
+    };
+    std::vector<MemorySlot> memorySlots;
+    uint32_t maxMemorySlot;
 };
 
 #endif
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to