gem5  v20.1.0.0
mem_state.cc
Go to the documentation of this file.
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/mem_state.hh"
30 
31 #include <cassert>
32 
33 #include "arch/generic/tlb.hh"
34 #include "debug/Vma.hh"
36 #include "sim/process.hh"
38 #include "sim/system.hh"
39 #include "sim/vma.hh"
40 
41 MemState::MemState(Process *owner, Addr brk_point, Addr stack_base,
42  Addr max_stack_size, Addr next_thread_stack_base,
43  Addr mmap_end)
44  : _ownerProcess(owner),
45  _pageBytes(owner->system->getPageBytes()), _brkPoint(brk_point),
46  _stackBase(stack_base), _stackSize(max_stack_size),
47  _maxStackSize(max_stack_size), _stackMin(stack_base - max_stack_size),
48  _nextThreadStackBase(next_thread_stack_base),
49  _mmapEnd(mmap_end), _endBrkPoint(brk_point)
50 {
51 }
52 
53 MemState&
55 {
56  if (this == &in)
57  return *this;
58 
60  _brkPoint = in._brkPoint;
64  _stackMin = in._stackMin;
66  _mmapEnd = in._mmapEnd;
68  _vmaList = in._vmaList; /* This assignment does a deep copy. */
69 
70  return *this;
71 }
72 
73 void
75 {
76  _ownerProcess = owner;
77 }
78 
79 bool
81 {
82  Addr end_addr = start_addr + length;
83  const AddrRange range(start_addr, end_addr);
84  for (const auto &vma : _vmaList) {
85  if (vma.intersects(range))
86  return false;
87  }
88 
93  for (auto start = start_addr; start < end_addr;
94  start += _pageBytes) {
95  if (_ownerProcess->pTable->lookup(start) != nullptr) {
96  panic("Someone allocated physical memory at VA %p without "
97  "creating a VMA!\n", start);
98  return false;
99  }
100  }
101  return true;
102 }
103 
104 void
106 {
115  if (new_brk < old_brk) {
116  _brkPoint = new_brk;
117  return;
118  }
119 
126  auto page_aligned_brk = roundUp(new_brk, _pageBytes);
127 
138  if (page_aligned_brk > _endBrkPoint) {
139  auto length = page_aligned_brk - _endBrkPoint;
145  if (!isUnmapped(_endBrkPoint, length)) {
146  return;
147  }
148 
156  mapRegion(_endBrkPoint, length, "heap");
157  _endBrkPoint = page_aligned_brk;
158  }
159 
160  _brkPoint = new_brk;
161 }
162 
163 void
165  const std::string& region_name, int sim_fd, Addr offset)
166 {
167  DPRINTF(Vma, "memstate: creating vma (%s) [0x%x - 0x%x]\n",
168  region_name.c_str(), start_addr, start_addr + length);
169 
174  assert(isUnmapped(start_addr, length));
175 
179  _vmaList.emplace_back(AddrRange(start_addr, start_addr + length),
180  _pageBytes, region_name, sim_fd, offset);
181 }
182 
183 void
185 {
186  Addr end_addr = start_addr + length;
187  const AddrRange range(start_addr, end_addr);
188 
189  auto vma = std::begin(_vmaList);
190  while (vma != std::end(_vmaList)) {
191  if (vma->isStrictSuperset(range)) {
192  DPRINTF(Vma, "memstate: split vma [0x%x - 0x%x] into "
193  "[0x%x - 0x%x] and [0x%x - 0x%x]\n",
194  vma->start(), vma->end(),
195  vma->start(), start_addr,
196  end_addr, vma->end());
201  _vmaList.push_back(*vma);
202  _vmaList.back().sliceRegionRight(start_addr);
203 
207  vma->sliceRegionLeft(end_addr);
208 
213  break;
214  } else if (vma->isSubset(range)) {
215  DPRINTF(Vma, "memstate: destroying vma [0x%x - 0x%x]\n",
216  vma->start(), vma->end());
220  vma = _vmaList.erase(vma);
221 
222  continue;
223 
224  } else if (vma->intersects(range)) {
228  if (vma->start() < start_addr) {
229  DPRINTF(Vma, "memstate: resizing vma [0x%x - 0x%x] "
230  "into [0x%x - 0x%x]\n",
231  vma->start(), vma->end(),
232  vma->start(), start_addr);
236  vma->sliceRegionRight(start_addr);
237  } else {
238  DPRINTF(Vma, "memstate: resizing vma [0x%x - 0x%x] "
239  "into [0x%x - 0x%x]\n",
240  vma->start(), vma->end(),
241  end_addr, vma->end());
245  vma->sliceRegionLeft(end_addr);
246  }
247  }
248 
249  vma++;
250  }
251 
260  for (auto *tc: _ownerProcess->system->threads) {
261  tc->getDTBPtr()->flushAll();
262  tc->getITBPtr()->flushAll();
263  }
264 
265  do {
266  if (!_ownerProcess->pTable->isUnmapped(start_addr, _pageBytes))
267  _ownerProcess->pTable->unmap(start_addr, _pageBytes);
268 
269  start_addr += _pageBytes;
270 
277  length -= _pageBytes;
278  } while (length > 0);
279 }
280 
281 void
282 MemState::remapRegion(Addr start_addr, Addr new_start_addr, Addr length)
283 {
284  Addr end_addr = start_addr + length;
285  const AddrRange range(start_addr, end_addr);
286 
287  auto vma = std::begin(_vmaList);
288  while (vma != std::end(_vmaList)) {
289  if (vma->isStrictSuperset(range)) {
293  _vmaList.push_back(*vma);
294  _vmaList.back().sliceRegionRight(start_addr);
295 
299  _vmaList.push_back(*vma);
300  _vmaList.back().sliceRegionLeft(end_addr);
301 
306  vma->sliceRegionLeft(start_addr);
307  vma->sliceRegionRight(end_addr);
308  vma->remap(new_start_addr);
309 
314  break;
315  } else if (vma->isSubset(range)) {
319  vma->remap(vma->start() - start_addr + new_start_addr);
320  } else if (vma->intersects(range)) {
324  _vmaList.push_back(*vma);
325 
326  if (vma->start() < start_addr) {
330  _vmaList.back().sliceRegionRight(start_addr);
331 
335  vma->sliceRegionLeft(start_addr);
336  vma->remap(new_start_addr);
337  } else {
341  _vmaList.back().sliceRegionLeft(end_addr);
342 
346  vma->sliceRegionRight(end_addr);
347  vma->remap(new_start_addr + vma->start() - start_addr);
348  }
349  }
350 
351  vma++;
352  }
353 
362  for (auto *tc: _ownerProcess->system->threads) {
363  tc->getDTBPtr()->flushAll();
364  tc->getITBPtr()->flushAll();
365  }
366 
367  do {
368  if (!_ownerProcess->pTable->isUnmapped(start_addr, _pageBytes))
369  _ownerProcess->pTable->remap(start_addr, _pageBytes,
370  new_start_addr);
371 
372  start_addr += _pageBytes;
373  new_start_addr += _pageBytes;
374 
381  length -= _pageBytes;
382  } while (length > 0);
383 }
384 
385 bool
387 {
392  for (const auto &vma : _vmaList) {
393  if (vma.contains(vaddr)) {
394  Addr vpage_start = roundDown(vaddr, _pageBytes);
395  _ownerProcess->allocateMem(vpage_start, _pageBytes);
396 
403  if (vma.hasHostBuf()) {
408  for (auto &cid : _ownerProcess->contextIds) {
409  auto *tc = _ownerProcess->system->threads[cid];
411  virt_mem(tc, SETranslatingPortProxy::Always);
412  vma.fillMemPages(vpage_start, _pageBytes, virt_mem);
413  }
414  }
415  return true;
416  }
417  }
418 
426  if (vaddr >= _stackMin && vaddr < _stackBase) {
428  return true;
429  }
430 
435  if (vaddr < _stackMin && vaddr >= _stackBase - _maxStackSize) {
436  while (vaddr < _stackMin) {
439  fatal("Maximum stack size exceeded\n");
440  }
442  inform("Increasing stack size by one page.");
443  }
444  return true;
445  }
446 
447  return false;
448 }
449 
450 Addr
452 {
453  Addr start = _mmapEnd;
454 
456  start = _mmapEnd - length;
457 
458  // Look for a contiguous region of free virtual memory. We can't assume
459  // that the region beyond mmap_end is free because of fixed mappings from
460  // the user.
461  while (!isUnmapped(start, length)) {
462  DPRINTF(Vma, "memstate: cannot extend vma for mmap region at %p. "
463  "Virtual address range is already reserved! Skipping a page "
464  "and trying again!\n", start);
465  start = (_ownerProcess->mmapGrowsDown()) ? start - _pageBytes :
466  start + _pageBytes;
467  }
468 
469  DPRINTF(Vma, "memstate: extending mmap region (old %p) (new %p)\n",
470  _mmapEnd,
471  _ownerProcess->mmapGrowsDown() ? start : start + length);
472 
473  _mmapEnd = _ownerProcess->mmapGrowsDown() ? start : start + length;
474 
475  return start;
476 }
477 
478 std::string
480 {
481  std::stringstream file_content;
482 
483  for (auto vma : _vmaList) {
484  std::stringstream line;
485  line << std::hex << vma.start() << "-";
486  line << std::hex << vma.end() << " ";
487  line << "r-xp 00000000 00:00 0 ";
488  line << "[" << vma.getName() << "]" << std::endl;
489  file_content << line.str();
490  }
491 
492  return file_content.str();
493 }
syscall_debug_macros.hh
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
MemState::_ownerProcess
Process * _ownerProcess
Owner process of MemState.
Definition: mem_state.hh:240
MemState::printVmaList
std::string printVmaList()
Print the list of VMAs in a format similar to /proc/self/maps.
Definition: mem_state.cc:479
roundDown
T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:150
MemState::MemState
MemState(Process *owner, Addr brk_point, Addr stack_base, Addr max_stack_size, Addr next_thread_stack_base, Addr mmap_end)
Definition: mem_state.cc:41
length
uint8_t length
Definition: inet.hh:422
SETranslatingPortProxy
Definition: se_translating_port_proxy.hh:46
system.hh
MemState
This class holds the memory state for the Process class and all of its derived, architecture-specific...
Definition: mem_state.hh:62
MemState::isUnmapped
bool isUnmapped(Addr start_addr, Addr length)
Check if any page in the virtual address range from start_addr to start_addr + length is already mapp...
Definition: mem_state.cc:80
MemState::resetOwner
void resetOwner(Process *owner)
Change the Process owner in case this MemState is copied.
Definition: mem_state.cc:74
MemState::remapRegion
void remapRegion(Addr start_addr, Addr new_start_addr, Addr length)
Remap a pre-existing region.
Definition: mem_state.cc:282
Process
Definition: process.hh:65
MemState::operator=
MemState & operator=(const MemState &in)
Definition: mem_state.cc:54
tlb.hh
Process::pTable
EmulationPageTable * pTable
Definition: process.hh:174
EmulationPageTable::unmap
virtual void unmap(Addr vaddr, int64_t size)
Definition: page_table.cc:101
MemState::_pageBytes
Addr _pageBytes
Definition: mem_state.hh:242
EmulationPageTable::isUnmapped
virtual bool isUnmapped(Addr vaddr, int64_t size)
Check if any pages in a region are already allocated.
Definition: page_table.cc:117
mem_state.hh
EmulationPageTable::lookup
const Entry * lookup(Addr vaddr)
Lookup function.
Definition: page_table.cc:130
X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:997
AddrRange
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:68
MemState::extendMmap
Addr extendMmap(Addr length)
Definition: mem_state.cc:451
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
SETranslatingPortProxy::Always
@ Always
Definition: se_translating_port_proxy.hh:51
EmulationPageTable::remap
virtual void remap(Addr vaddr, int64_t size, Addr new_vaddr)
Definition: page_table.cc:72
MipsISA::vaddr
vaddr
Definition: pra_constants.hh:275
Process::allocateMem
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition: process.cc:319
MemState::_stackSize
Addr _stackSize
Definition: mem_state.hh:245
MemState::_vmaList
std::list< VMA > _vmaList
The _vmaList member is a list of virtual memory areas in the target application space that have been ...
Definition: mem_state.hh:268
MemState::mapRegion
void mapRegion(Addr start_addr, Addr length, const std::string &name="anon", int sim_fd=-1, Addr offset=0)
Add a new memory region.
Definition: mem_state.cc:164
process.hh
MemState::_endBrkPoint
Addr _endBrkPoint
Keeps record of the furthest mapped heap location.
Definition: mem_state.hh:254
MemState::fixupFault
bool fixupFault(Addr vaddr)
Attempt to fix up a fault at vaddr by allocating a page.
Definition: mem_state.cc:386
MemState::_mmapEnd
Addr _mmapEnd
Definition: mem_state.hh:249
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Process::contextIds
std::vector< ContextID > contextIds
Definition: process.hh:160
MemState::_stackBase
Addr _stackBase
Definition: mem_state.hh:244
MemState::_brkPoint
Addr _brkPoint
Definition: mem_state.hh:243
System::threads
Threads threads
Definition: system.hh:309
Process::mmapGrowsDown
virtual bool mmapGrowsDown() const
Does mmap region grow upward or downward from mmapEnd? Most platforms grow downward,...
Definition: process.hh:136
inform
#define inform(...)
Definition: logging.hh:240
roundUp
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
MemState::_nextThreadStackBase
Addr _nextThreadStackBase
Definition: mem_state.hh:248
MemState::_maxStackSize
Addr _maxStackSize
Definition: mem_state.hh:246
se_translating_port_proxy.hh
Process::system
System * system
Definition: process.hh:163
MemState::unmapRegion
void unmapRegion(Addr start_addr, Addr length)
Unmap a pre-existing region.
Definition: mem_state.cc:184
vma.hh
MemState::_stackMin
Addr _stackMin
Definition: mem_state.hh:247
MemState::updateBrkRegion
void updateBrkRegion(Addr old_brk, Addr new_brk)
Change the end of a process' program break.
Definition: mem_state.cc:105
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153

Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17