gem5  v21.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
process.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2005 The Regents of The University of Michigan
3  * Copyright (c) 2016 The University of Virginia
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met: redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer;
10  * redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution;
13  * neither the name of the copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "arch/riscv/process.hh"
31 
32 #include <algorithm>
33 #include <cstddef>
34 #include <iostream>
35 #include <iterator>
36 #include <map>
37 #include <string>
38 #include <vector>
39 
40 #include "arch/riscv/isa.hh"
41 #include "arch/riscv/isa_traits.hh"
42 #include "arch/riscv/registers.hh"
45 #include "base/logging.hh"
46 #include "base/random.hh"
47 #include "cpu/thread_context.hh"
48 #include "debug/Stack.hh"
49 #include "mem/page_table.hh"
50 #include "params/Process.hh"
51 #include "sim/aux_vector.hh"
52 #include "sim/process.hh"
53 #include "sim/process_impl.hh"
54 #include "sim/syscall_return.hh"
55 #include "sim/system.hh"
56 
57 using namespace RiscvISA;
58 
59 RiscvProcess::RiscvProcess(const ProcessParams &params,
60  ::Loader::ObjectFile *objFile) :
61  Process(params,
62  new EmulationPageTable(params.name, params.pid, PageBytes),
63  objFile)
64 {
65  fatal_if(params.useArchPT, "Arch page tables not implemented.");
66 }
67 
68 RiscvProcess64::RiscvProcess64(const ProcessParams &params,
69  ::Loader::ObjectFile *objFile) :
70  RiscvProcess(params, objFile)
71 {
72  const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
73  const Addr max_stack_size = 8 * 1024 * 1024;
74  const Addr next_thread_stack_base = stack_base - max_stack_size;
75  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
76  const Addr mmap_end = 0x4000000000000000L;
77  memState = std::make_shared<MemState>(this, brk_point, stack_base,
78  max_stack_size, next_thread_stack_base, mmap_end);
79 }
80 
81 RiscvProcess32::RiscvProcess32(const ProcessParams &params,
82  ::Loader::ObjectFile *objFile) :
83  RiscvProcess(params, objFile)
84 {
85  const Addr stack_base = 0x7FFFFFFF;
86  const Addr max_stack_size = 8 * 1024 * 1024;
87  const Addr next_thread_stack_base = stack_base - max_stack_size;
88  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
89  const Addr mmap_end = 0x40000000L;
90  memState = std::make_shared<MemState>(this, brk_point, stack_base,
91  max_stack_size, next_thread_stack_base, mmap_end);
92 }
93 
94 void
96 {
98 
99  argsInit<uint64_t>(PageBytes);
100  for (ContextID ctx: contextIds)
101  system->threads[ctx]->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
102 }
103 
104 void
106 {
108 
109  argsInit<uint32_t>(PageBytes);
110  for (ContextID ctx: contextIds) {
111  auto *tc = system->threads[ctx];
112  tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
113  PCState pc = tc->pcState();
114  pc.rv32(true);
115  tc->pcState(pc);
116  }
117 }
118 
119 template<class IntType> void
121 {
122  const int RandomBytes = 16;
123  const int addrSize = sizeof(IntType);
124 
125  auto *elfObject = dynamic_cast<::Loader::ElfObject*>(objFile);
126  memState->setStackMin(memState->getStackBase());
127 
128  // Determine stack size and populate auxv
129  Addr stack_top = memState->getStackMin();
130  stack_top -= RandomBytes;
131  for (const std::string& arg: argv)
132  stack_top -= arg.size() + 1;
133  for (const std::string& env: envp)
134  stack_top -= env.size() + 1;
135  stack_top &= -addrSize;
136 
138  if (elfObject != nullptr) {
139  auxv.emplace_back(M5_AT_ENTRY, objFile->entryPoint());
140  auxv.emplace_back(M5_AT_PHNUM, elfObject->programHeaderCount());
141  auxv.emplace_back(M5_AT_PHENT, elfObject->programHeaderSize());
142  auxv.emplace_back(M5_AT_PHDR, elfObject->programHeaderTable());
143  auxv.emplace_back(M5_AT_PAGESZ, PageBytes);
144  auxv.emplace_back(M5_AT_SECURE, 0);
145  auxv.emplace_back(M5_AT_RANDOM, stack_top);
146  auxv.emplace_back(M5_AT_NULL, 0);
147  }
148  stack_top -= (1 + argv.size()) * addrSize +
149  (1 + envp.size()) * addrSize +
150  addrSize + 2 * sizeof(IntType) * auxv.size();
151  stack_top &= -2*addrSize;
152  memState->setStackSize(memState->getStackBase() - stack_top);
153  memState->mapRegion(roundDown(stack_top, pageSize),
154  roundUp(memState->getStackSize(), pageSize), "stack");
155 
156  // Copy random bytes (for AT_RANDOM) to stack
157  memState->setStackMin(memState->getStackMin() - RandomBytes);
158  uint8_t at_random[RandomBytes];
159  std::generate(std::begin(at_random), std::end(at_random),
160  [&]{ return random_mt.random(0, 0xFF); });
161  initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes);
162 
163  // Copy argv to stack
164  std::vector<Addr> argPointers;
165  for (const std::string& arg: argv) {
166  memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
167  initVirtMem->writeString(memState->getStackMin(), arg.c_str());
168  argPointers.push_back(memState->getStackMin());
169  if (DTRACE(Stack)) {
170  std::string wrote;
171  initVirtMem->readString(wrote, argPointers.back());
172  DPRINTFN("Wrote arg \"%s\" to address %p\n",
173  wrote, (void*)memState->getStackMin());
174  }
175  }
176  argPointers.push_back(0);
177 
178  // Copy envp to stack
179  std::vector<Addr> envPointers;
180  for (const std::string& env: envp) {
181  memState->setStackMin(memState->getStackMin() - (env.size() + 1));
182  initVirtMem->writeString(memState->getStackMin(), env.c_str());
183  envPointers.push_back(memState->getStackMin());
184  DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
185  env, (void*)memState->getStackMin());
186  }
187  envPointers.push_back(0);
188 
189  // Align stack
190  memState->setStackMin(memState->getStackMin() & -addrSize);
191 
192  // Calculate bottom of stack
193  memState->setStackMin(memState->getStackMin() -
194  ((1 + argv.size()) * addrSize +
195  (1 + envp.size()) * addrSize +
196  addrSize + 2 * sizeof(IntType) * auxv.size()));
197  memState->setStackMin(memState->getStackMin() & (-2 * addrSize));
198  Addr sp = memState->getStackMin();
199  const auto pushOntoStack =
200  [this, &sp](IntType data) {
201  initVirtMem->write(sp, data, GuestByteOrder);
202  sp += sizeof(data);
203  };
204 
205  // Push argc and argv pointers onto stack
206  IntType argc = argv.size();
207  DPRINTF(Stack, "Wrote argc %d to address %#x\n", argc, sp);
208  pushOntoStack(argc);
209 
210  for (const Addr& argPointer: argPointers) {
211  DPRINTF(Stack, "Wrote argv pointer %#x to address %#x\n",
212  argPointer, sp);
213  pushOntoStack(argPointer);
214  }
215 
216  // Push env pointers onto stack
217  for (const Addr& envPointer: envPointers) {
218  DPRINTF(Stack, "Wrote envp pointer %#x to address %#x\n",
219  envPointer, sp);
220  pushOntoStack(envPointer);
221  }
222 
223  // Push aux vector onto stack
224  std::map<IntType, std::string> aux_keys = {
225  {M5_AT_ENTRY, "M5_AT_ENTRY"},
226  {M5_AT_PHNUM, "M5_AT_PHNUM"},
227  {M5_AT_PHENT, "M5_AT_PHENT"},
228  {M5_AT_PHDR, "M5_AT_PHDR"},
229  {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
230  {M5_AT_SECURE, "M5_AT_SECURE"},
231  {M5_AT_RANDOM, "M5_AT_RANDOM"},
232  {M5_AT_NULL, "M5_AT_NULL"}
233  };
234  for (const auto &aux: auxv) {
235  DPRINTF(Stack, "Wrote aux key %s to address %#x\n",
236  aux_keys[aux.type], sp);
237  pushOntoStack(aux.type);
238  DPRINTF(Stack, "Wrote aux value %x to address %#x\n", aux.val, sp);
239  pushOntoStack(aux.val);
240  }
241 
243  tc->setIntReg(StackPointerReg, memState->getStackMin());
244  tc->pcState(getStartPC());
245 
246  memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
247 }
RiscvISA::MISCREG_PRV
@ MISCREG_PRV
Definition: registers.hh:154
roundDown
T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:150
X86ISA::L
Bitfield< 7, 0 > L
Definition: int.hh:57
RiscvISA::PCState
Definition: types.hh:53
system.hh
Process::envp
std::vector< std::string > envp
Definition: process.hh:212
data
const char data[]
Definition: circlebuf.test.cc:47
M5_AT_NULL
@ M5_AT_NULL
Definition: aux_vector.hh:58
RiscvISA::PageBytes
const Addr PageBytes
Definition: isa_traits.hh:54
Process
Definition: process.hh:65
ContextID
int ContextID
Globally unique thread context ID.
Definition: types.hh:237
Process::argv
std::vector< std::string > argv
Definition: process.hh:211
random.hh
ThreadContext::setIntReg
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
M5_AT_PAGESZ
@ M5_AT_PAGESZ
Definition: aux_vector.hh:64
M5_AT_SECURE
@ M5_AT_SECURE
Definition: aux_vector.hh:76
M5_AT_PHENT
@ M5_AT_PHENT
Definition: aux_vector.hh:62
ArmISA::GuestByteOrder
const ByteOrder GuestByteOrder
Definition: isa_traits.hh:50
process_impl.hh
DTRACE
#define DTRACE(x)
Definition: debug.hh:156
std::vector
STL vector class.
Definition: stl.hh:37
Process::initVirtMem
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:172
isa.hh
RiscvProcess64::RiscvProcess64
RiscvProcess64(const ProcessParams &params, ::Loader::ObjectFile *objFile)
Definition: process.cc:68
Loader::ElfObject
Definition: elf_object.hh:59
Loader::MemoryImage::maxAddr
Addr maxAddr() const
Definition: memory_image.hh:131
RiscvISA
Definition: fs_workload.cc:36
Random::random
std::enable_if_t< std::is_integral< T >::value, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:86
M5_AT_ENTRY
@ M5_AT_ENTRY
Definition: aux_vector.hh:67
random_mt
Random random_mt
Definition: random.cc:96
Loader::ObjectFile
Definition: object_file.hh:74
M5_AT_PHNUM
@ M5_AT_PHNUM
Definition: aux_vector.hh:63
elf_object.hh
Loader::ObjectFile::entryPoint
Addr entryPoint() const
Definition: object_file.hh:112
syscall_return.hh
RiscvProcess::argsInit
void argsInit(int pageSize)
Definition: process.cc:120
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
EmulationPageTable
Definition: page_table.hh:49
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:240
process.hh
RiscvProcess32::RiscvProcess32
RiscvProcess32(const ProcessParams &params, ::Loader::ObjectFile *objFile)
Definition: process.cc:81
RiscvISA::PRV_U
@ PRV_U
Definition: isa.hh:58
process.hh
Process::image
::Loader::MemoryImage image
Definition: process.hh:209
M5_AT_RANDOM
@ M5_AT_RANDOM
Definition: aux_vector.hh:78
ArmISA::sp
Bitfield< 0 > sp
Definition: miscregs_types.hh:71
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:148
Process::objFile
::Loader::ObjectFile * objFile
Definition: process.hh:208
name
const std::string & name()
Definition: trace.cc:48
Process::contextIds
std::vector< ContextID > contextIds
Definition: process.hh:157
registers.hh
RiscvProcess
Definition: process.hh:47
ThreadContext::pcState
virtual TheISA::PCState pcState() const =0
System::threads
Threads threads
Definition: system.hh:304
ArmISA::PageBytes
const Addr PageBytes
Definition: isa_traits.hh:53
aux_vector.hh
ArmISA::StackPointerReg
const int StackPointerReg
Definition: registers.hh:106
Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:277
roundUp
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
RiscvProcess::RiscvProcess
RiscvProcess(const ProcessParams &params, ::Loader::ObjectFile *objFile)
Definition: process.cc:59
RiscvProcess64::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:95
logging.hh
Process::getStartPC
Addr getStartPC()
Definition: process.cc:477
DPRINTFN
#define DPRINTFN(...)
Definition: trace.hh:241
SimObject::params
const Params & params() const
Definition: sim_object.hh:168
Process::system
System * system
Definition: process.hh:160
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:219
page_table.hh
object_file.hh
thread_context.hh
Process::memState
std::shared_ptr< MemState > memState
Definition: process.hh:274
isa_traits.hh
M5_AT_PHDR
@ M5_AT_PHDR
Definition: aux_vector.hh:61
RiscvProcess32::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:105

Generated on Tue Mar 23 2021 19:41:20 for gem5 by doxygen 1.8.17