This patch fixes a problem that occurs when restoring from a checkpoint where Mapped File Buffers are not restored. This causes errors and unexpected behavior during further execution. Since the checkpoint already has the size of the area (address range) and the file name, only the offset is missing to restore the Mapped File Buffer. Having the offset value, it's possible to open those files for which an offset is specified and create a VMA with a Mapped File Buffer. Change-Id: Ib9dfa174cda6348b966b892184c36daeaba80e81 Signed-off-by: Emin Gadzhiev <e.gadzhiev.mhk@gmail.com> Issue-On: https://gem5.atlassian.net/browse/GEM5-1302 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/66311 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com>
160 lines
4.8 KiB
C++
160 lines
4.8 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#include "sim/vma.hh"
|
|
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "base/types.hh"
|
|
|
|
namespace gem5
|
|
{
|
|
|
|
void
|
|
VMA::fillMemPages(Addr start, Addr size, PortProxy &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, _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 %#x end %#x\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 = (void *)((uint8_t *)_hostBuf + overlap_len);
|
|
}
|
|
|
|
_addrRange = AddrRange(slice_addr, _addrRange.end());
|
|
|
|
DPRINTF(Vma, "slice left vma start %#x end %#x\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() % _pageBytes) == 0);
|
|
assert((_addrRange.end() % _pageBytes) == 0);
|
|
}
|
|
|
|
VMA::MappedFileBuffer::MappedFileBuffer(int fd, size_t length,
|
|
off_t offset)
|
|
: _buffer(nullptr), _length(length), _offset(offset)
|
|
{
|
|
panic_if(_length == 0, "Tried to mmap file of length zero");
|
|
|
|
struct stat file_stat;
|
|
if (fstat(fd, &file_stat) > 0) {
|
|
panic("Cannot stat file: %s\n", strerror(errno));
|
|
}
|
|
|
|
// Don't bother mapping more than the actual file size
|
|
panic_if(offset > file_stat.st_size,
|
|
"Tried to mmap with offset greater than file size");
|
|
_length = std::min((size_t)(file_stat.st_size - offset), _length);
|
|
|
|
// cannot call mmap with _length == 0
|
|
if (_length) {
|
|
_buffer = mmap(NULL, _length, PROT_READ,
|
|
MAP_PRIVATE, fd, offset);
|
|
if (_buffer == MAP_FAILED) {
|
|
panic("Failed to map file into host address space: %s",
|
|
strerror(errno));
|
|
}
|
|
} else {
|
|
panic("Tried to mmap 0 bytes");
|
|
}
|
|
}
|
|
|
|
VMA::MappedFileBuffer::~MappedFileBuffer()
|
|
{
|
|
if (_buffer) {
|
|
panic_if(munmap(_buffer, _length) == -1,
|
|
"mmap: failed to unmap file-backed host memory: %s",
|
|
strerror(errno));
|
|
}
|
|
}
|
|
|
|
} // namespace gem5
|