arch-arm,cpu: Introduce a getEMI virtual method on StaticInst.
[gem5.git] / src / sim / vma.cc
1 /*
2 * Copyright (c) 2017-2020 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "sim/vma.hh"
30
31 #include <sys/mman.h>
32 #include <sys/stat.h>
33
34 #include "base/types.hh"
35 #include "config/the_isa.hh"
36
37 void
38 VMA::fillMemPages(Addr start, Addr size, PortProxy &port) const
39 {
40 auto offset = start - _addrRange.start();
41
42 /**
43 * Try to copy a full page, but don't overrun the size of the file.
44 */
45 if (offset < _hostBufLen) {
46 auto size = std::min(_hostBufLen - offset, _pageBytes);
47 port.writeBlob(start, (uint8_t*)_hostBuf + offset, size);
48 }
49 }
50
51 bool
52 VMA::isStrictSuperset(const AddrRange &r) const
53 {
54 return (r.start() > _addrRange.start() && r.end() < _addrRange.end());
55 }
56
57 void
58 VMA::sliceRegionRight(Addr slice_addr)
59 {
60 if (hasHostBuf()) {
61 auto nonoverlap_len = slice_addr - _addrRange.start();
62 _hostBufLen = std::min(_hostBufLen, nonoverlap_len);
63 }
64
65 _addrRange = AddrRange(_addrRange.start(), slice_addr);
66
67 DPRINTF(Vma, "slice right vma start %#x end %#x\n", _addrRange.start(),
68 _addrRange.end());
69
70 sanityCheck();
71 }
72
73 void
74 VMA::sliceRegionLeft(Addr slice_addr)
75 {
76 if (hasHostBuf()) {
77 auto overlap_len = slice_addr - _addrRange.start();
78
79 if (overlap_len >= _hostBufLen) {
80 _hostBufLen = 0;
81 _hostBuf = nullptr;
82 _origHostBuf = nullptr;
83 } else {
84 _hostBufLen -= overlap_len;
85 }
86
87 _hostBuf = (void *)((uint8_t *)_hostBuf + overlap_len);
88 }
89
90 _addrRange = AddrRange(slice_addr, _addrRange.end());
91
92 DPRINTF(Vma, "slice left vma start %#x end %#x\n", _addrRange.start(),
93 _addrRange.end());
94
95 sanityCheck();
96 }
97
98 void
99 VMA::sanityCheck()
100 {
101 /**
102 * Avoid regions without a length.
103 */
104 assert(_addrRange.start() != _addrRange.end());
105
106 /**
107 * Avoid regions with an end point before the start point
108 */
109 assert(_addrRange.start() < _addrRange.end());
110
111 /**
112 * Avoid non-aligned regions; we assume in the code that the
113 * regions are page aligned so consider this to be a bug.
114 */
115 assert((_addrRange.start() % _pageBytes) == 0);
116 assert((_addrRange.end() % _pageBytes) == 0);
117 }
118
119 VMA::MappedFileBuffer::MappedFileBuffer(int fd, size_t length,
120 off_t offset)
121 : _buffer(nullptr), _length(length)
122 {
123 panic_if(_length == 0, "Tried to mmap file of length zero");
124
125 struct stat file_stat;
126 if (fstat(fd, &file_stat) > 0) {
127 panic("Cannot stat file: %s\n", strerror(errno));
128 }
129
130 // Don't bother mapping more than the actual file size
131 panic_if(offset > file_stat.st_size,
132 "Tried to mmap with offset greater than file size");
133 _length = std::min((size_t)(file_stat.st_size - offset), _length);
134
135 // cannot call mmap with _length == 0
136 if (_length) {
137 _buffer = mmap(NULL, _length, PROT_READ,
138 MAP_PRIVATE, fd, offset);
139 if (_buffer == MAP_FAILED) {
140 panic("Failed to map file into host address space: %s",
141 strerror(errno));
142 }
143 } else {
144 panic("Tried to mmap 0 bytes");
145 }
146 }
147
148 VMA::MappedFileBuffer::~MappedFileBuffer()
149 {
150 if (_buffer) {
151 panic_if(munmap(_buffer, _length) == -1,
152 "mmap: failed to unmap file-backed host memory: %s",
153 strerror(errno));
154 }
155 }