Matthew Poremba has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/25365 )

Change subject: sim-se: Implement Virtual Memory Area API
......................................................................

sim-se: Implement Virtual Memory Area API

Virtual memory areas change how mmap'd address ranges are tracked and is a
high-level mimicry of Linux' memory management. Instead of binding virtual
pages to physical pages during mmap/remap, a VMA is created that covers the
region of memory. Physical pages are only allocated when an accesses occurs
on an address which has a valid VMA region already assigned. New physical
pages result in a fault which is resolved by the MemState class and new
page table assignments are created. This allows mmap in SE mode to support
sparse usages of mmap'd memory.

This changeset only adds APIs for virtual memory areas. These are used in
a subsequent changeset.

Change-Id: Ibbdce5be79a95e3231d2e1c9ee8f397b4503f0fb
---
A src/base/mapped_file_buffer.hh
M src/sim/SConscript
A src/sim/vma.cc
A src/sim/vma.hh
4 files changed, 356 insertions(+), 0 deletions(-)



diff --git a/src/base/mapped_file_buffer.hh b/src/base/mapped_file_buffer.hh
new file mode 100644
index 0000000..9d9ba48
--- /dev/null
+++ b/src/base/mapped_file_buffer.hh
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Michael LeBeane
+ */
+
+#ifndef __BASE_MAPPED_FILE_BUFFER_HH__
+#define __BASE_MAPPED_FILE_BUFFER_HH__
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "base/logging.hh"
+#include "base/types.hh"
+
+/**
+ * MappedFileBuffer is a wrapper around a region of host memory backed by a
+ * file. The constructor attempts to map a file from host memory, and the
+ * destructor attempts to unmap it.  If there is a problem with the host
+ * mapping/unmapping, then we panic.
+ */
+struct MappedFileBuffer
+{
+    char *buf;          // Host buffer ptr
+    uint64_t len;       // Length of host ptr
+
+    MappedFileBuffer(int fd, uint64_t length, uint64_t offset)
+        : buf(nullptr), len(0)
+    {
+        struct stat file_stat;
+        if (fstat(fd, &file_stat) > 0)
+            panic("mmap: cannot stat file");
+        // Don't bother mapping more than the actual file size
+        len = std::min((uint64_t)file_stat.st_size - offset, length);
+        // cannot call mmap with len == 0
+        if (len) {
+ buf = (char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, offset);
+            if (buf == MAP_FAILED)
+                panic("mmap: failed to map file into host address space");
+        }
+    }
+
+    ~MappedFileBuffer()
+    {
+        if (buf)
+            if (munmap(buf, len) == -1)
+                panic("mmap: failed to unmap file-backed host memory");
+    }
+};
+
+#endif // __BASE_MAPPED_FILE_BUFFER_HH__
diff --git a/src/sim/SConscript b/src/sim/SConscript
index b27dc51..ee670cf 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -90,6 +90,7 @@
     Source('pseudo_inst.cc')
     Source('syscall_emul.cc')
     Source('syscall_desc.cc')
+    Source('vma.cc')

 if env['TARGET_ISA'] != 'x86':
     Source('microcode_rom.cc')
@@ -117,5 +118,6 @@
 DebugFlag('ClockDomain')
 DebugFlag('VoltageDomain')
 DebugFlag('DVFS')
+DebugFlag('Vma')

 CompoundFlag('SyscallAll', [ 'SyscallBase', 'SyscallVerbose'])
diff --git a/src/sim/vma.cc b/src/sim/vma.cc
new file mode 100644
index 0000000..840d266
--- /dev/null
+++ b/src/sim/vma.cc
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Michael LeBeane
+ *         Brandon Potter
+ */
+
+#include "sim/vma.hh"
+
+#include "config/the_isa.hh"
+
+void
+VMA::fillMemPages(Addr start, Addr size, SETranslatingPortProxy &port) const
+{
+    auto offset = start - _addrRange.start();
+
+    /**
+     * Try to copy a full page, but don't overrun the size of the file.
+     */
+    if (offset < _hostBufLen) {
+        auto size = std::min(_hostBufLen - offset, TheISA::PageBytes);
+        port.writeBlob(start, (uint8_t*) _hostBuf + offset, size);
+    }
+}
+
+bool
+VMA::isStrictSuperset(const AddrRange &r) const
+{
+    return (r.start() > _addrRange.start() && r.end() < _addrRange.end());
+}
+
+void
+VMA::sliceRegionRight(Addr slice_addr)
+{
+    if (hasHostBuf()) {
+        auto nonoverlap_len = slice_addr - _addrRange.start();
+        _hostBufLen = std::min(_hostBufLen, nonoverlap_len);
+    }
+
+    _addrRange = AddrRange(_addrRange.start(), slice_addr);
+
+    DPRINTF(Vma, "slice right vma start %p end %p\n", _addrRange.start(),
+            _addrRange.end());
+
+    sanityCheck();
+}
+
+void
+VMA::sliceRegionLeft(Addr slice_addr)
+{
+    if (hasHostBuf()) {
+        auto overlap_len = slice_addr - _addrRange.start();
+
+        if (overlap_len >= _hostBufLen) {
+            _hostBufLen = 0;
+            _hostBuf = nullptr;
+            _origHostBuf = nullptr;
+        } else {
+            _hostBufLen -= overlap_len;
+        }
+
+        _hostBuf += overlap_len;
+    }
+
+    _addrRange = AddrRange(slice_addr, _addrRange.end());
+
+    DPRINTF(Vma, "slice left vma start %p end %p\n", _addrRange.start(),
+            _addrRange.end());
+
+    sanityCheck();
+}
+
+void
+VMA::sanityCheck()
+{
+    /**
+     * Avoid regions without a length.
+     */
+    assert(_addrRange.start() != _addrRange.end());
+
+    /**
+     * Avoid regions with an end point before the start point
+     */
+    assert(_addrRange.start() < _addrRange.end());
+
+    /**
+     *  Avoid non-aligned regions; we assume in the code that the
+     *  regions are page aligned so consider this to be a bug.
+     */
+    assert(!(_addrRange.start() % TheISA::PageBytes));
+    assert(!((_addrRange.end()) % TheISA::PageBytes));
+}
diff --git a/src/sim/vma.hh b/src/sim/vma.hh
new file mode 100644
index 0000000..c514835
--- /dev/null
+++ b/src/sim/vma.hh
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Michael LeBeane
+ */
+
+#ifndef SRC_MEM_VMA_HH
+#define SRC_MEM_VMA_HH
+
+#include <string>
+
+#include "arch/isa_traits.hh"
+#include "base/addr_range.hh"
+#include "base/mapped_file_buffer.hh"
+#include "base/types.hh"
+#include "debug/Vma.hh"
+#include "mem/se_translating_port_proxy.hh"
+
+class VMA
+{
+  public:
+    VMA(Addr sa, Addr len, int fd, Addr off, std::string vma_name)
+        : _addrRange(sa, sa + len), _origHostBuf(nullptr),
+          _hostBuf(nullptr), _hostBufLen(0), _vmaName(vma_name)
+    {
+        DPRINTF(Vma, "Creating vma start %p len %p end %p\n",
+                sa, len, sa + len);
+
+        if (fd != -1) {
+ _origHostBuf = std::make_shared<MappedFileBuffer>(fd, len, off);
+            _hostBuf = _origHostBuf->buf;
+            _hostBufLen = _origHostBuf->len;
+        }
+
+        sanityCheck();
+    }
+
+    /**
+     * Remap the virtual memory area starting at new_start.
+     */
+    void remap(Addr new_start)
+    {
+        _addrRange = AddrRange(new_start, new_start + _addrRange.size());
+
+        DPRINTF(Vma, "Remapping vma start %p end %p\n", _addrRange.start(),
+                _addrRange.end());
+
+        sanityCheck();
+    }
+
+    /**
+     * Check if the virtual memory area has an equivalent buffer on the
+     * host machine.
+     */
+    bool hasHostBuf() const { return _origHostBuf != nullptr; }
+
+    /**
+     * Copy memory from a buffer which resides on the host machine into a
+     * section of memory on the target.
+     */
+    void fillMemPages(Addr start, Addr size,
+                      SETranslatingPortProxy &port) const;
+
+    /**
+     * Returns true if desired range exists within this virtual memory area
+     * and does not include the start and end addresses.
+     */
+    bool isStrictSuperset(const AddrRange &range) const;
+
+    /**
+     * Remove the address range to the right of slice_addr.
+     */
+    void sliceRegionRight(Addr slice_addr);
+
+    /**
+     * Remove the address range to the left of slice_addr.
+     */
+    void sliceRegionLeft(Addr slice_addr);
+
+    std::string getName() { return _vmaName; }
+
+    /**
+     * Defer AddrRange related calls to the AddrRange.
+     */
+    Addr size() { return _addrRange.size(); }
+    Addr start() { return _addrRange.start(); }
+    Addr end() { return _addrRange.end(); }
+
+    bool mergesWith(const AddrRange& r) const
+    { return _addrRange.mergesWith(r); }
+
+    bool intersects(const AddrRange& r) const
+    { return _addrRange.intersects(r); }
+
+    bool isSubset(const AddrRange& r) const
+    { return _addrRange.isSubset(r); }
+
+    bool contains(const Addr& a) const
+    { return _addrRange.contains(a); }
+
+  private:
+    void sanityCheck();
+
+    AddrRange _addrRange;
+
+    /**
+     * The host file backing will be chopped up and reassigned as pages are
+     * mapped, remapped, and unmapped. In addition to the current host
+     * pointer and length, each virtual memory area will also keep a
+ * reference-counted handle to the original host memory. The last virtual
+     * memory area to die cleans up the host memory it handles.
+     */
+    std::shared_ptr<MappedFileBuffer> _origHostBuf;
+
+    /**
+     * Host buffer ptr for this virtual memory area.
+     */
+    char *_hostBuf;
+
+    /**
+     * Length of host buffer for this virtual memory area.
+     */
+    Addr _hostBufLen;
+
+    /**
+     * Human-readable name associated with the virtual memory area.
+     * The name is useful for debugging and also exposing vma state through
+     * the psuedo file system (i.e. Linux's /proc/self/maps) to the
+     * application.
+     */
+    std::string _vmaName;
+};
+
+#endif

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/25365
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ibbdce5be79a95e3231d2e1c9ee8f397b4503f0fb
Gerrit-Change-Number: 25365
Gerrit-PatchSet: 1
Gerrit-Owner: Matthew Poremba <matthew.pore...@amd.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to