| /* |
| * Copyright (c) 2017-2020 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. |
| */ |
| |
| #ifndef __SRC_MEM_VMA_HH__ |
| #define __SRC_MEM_VMA_HH__ |
| |
| #include <string> |
| |
| #include "arch/isa_traits.hh" |
| #include "base/addr_range.hh" |
| #include "base/types.hh" |
| #include "debug/Vma.hh" |
| #include "mem/se_translating_port_proxy.hh" |
| |
| class VMA |
| { |
| class MappedFileBuffer; |
| |
| public: |
| VMA(AddrRange r, Addr page_bytes, const std::string& vma_name="anon", |
| int fd=-1, off_t off=0) |
| : _addrRange(r), _pageBytes(page_bytes), _vmaName(vma_name) |
| { |
| DPRINTF(Vma, "Creating vma start %#x len %llu end %#x\n", |
| r.start(), r.size(), r.end()); |
| |
| if (fd != -1) { |
| _origHostBuf = |
| std::make_shared<MappedFileBuffer>(fd, r.size(), off); |
| _hostBuf = _origHostBuf->getBuffer(); |
| _hostBufLen = _origHostBuf->getLength(); |
| } |
| |
| 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 %#x end %#x\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, PortProxy &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); |
| |
| const 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(); |
| |
| /** |
| * Address range for this virtual memory area. |
| */ |
| AddrRange _addrRange; |
| |
| /** |
| * Number of bytes in an OS page. |
| */ |
| Addr _pageBytes; |
| |
| /** |
| * 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. |
| */ |
| void *_hostBuf; |
| |
| /** |
| * Length of host buffer for this virtual memory area. |
| */ |
| uint64_t _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; |
| |
| /** |
| * 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. |
| */ |
| class MappedFileBuffer |
| { |
| public: |
| MappedFileBuffer(int fd, size_t length, off_t offset); |
| ~MappedFileBuffer(); |
| |
| void *getBuffer() const { return _buffer; } |
| uint64_t getLength() const { return _length; } |
| |
| private: |
| void *_buffer; // Host buffer ptr |
| size_t _length; // Length of host ptr |
| }; |
| }; |
| |
| #endif // __SRC_MEM_VMA_HH__ |