gem5  v20.0.0.2
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 std;
58 using namespace RiscvISA;
59 
60 RiscvProcess::RiscvProcess(ProcessParams *params,
61  ::Loader::ObjectFile *objFile) :
62  Process(params,
63  new EmulationPageTable(params->name, params->pid, PageBytes),
64  objFile)
65 {
66  fatal_if(params->useArchPT, "Arch page tables not implemented.");
67 }
68 
71  RiscvProcess(params, objFile)
72 {
73  const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
74  const Addr max_stack_size = 8 * 1024 * 1024;
75  const Addr next_thread_stack_base = stack_base - max_stack_size;
76  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
77  const Addr mmap_end = 0x4000000000000000L;
78  memState = make_shared<MemState>(this, brk_point, stack_base,
79  max_stack_size, next_thread_stack_base, mmap_end);
80 }
81 
84  RiscvProcess(params, objFile)
85 {
86  const Addr stack_base = 0x7FFFFFFF;
87  const Addr max_stack_size = 8 * 1024 * 1024;
88  const Addr next_thread_stack_base = stack_base - max_stack_size;
89  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
90  const Addr mmap_end = 0x40000000L;
91  memState = make_shared<MemState>(this, brk_point, stack_base,
92  max_stack_size, next_thread_stack_base, mmap_end);
93 }
94 
95 void
97 {
99 
100  argsInit<uint64_t>(PageBytes);
101  for (ContextID ctx: contextIds)
103 }
104 
105 void
107 {
109 
110  argsInit<uint32_t>(PageBytes);
111  for (ContextID ctx: contextIds) {
114  pc.rv32(true);
115  system->getThreadContext(ctx)->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 string& arg: argv)
132  stack_top -= arg.size() + 1;
133  for (const 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  generate(begin(at_random), 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  vector<Addr> argPointers;
165  for (const 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  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  vector<Addr> envPointers;
180  for (const 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, 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 }
248 
250  10, 11, 12, 13, 14, 15, 16
251 };
#define DPRINTF(x,...)
Definition: trace.hh:222
static const std::vector< int > ArgumentRegs
Definition: process.hh:60
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:96
Bitfield< 7, 0 > L
Definition: int.hh:57
void rv32(bool val)
Definition: types.hh:66
const std::string & name()
Definition: trace.cc:50
virtual TheISA::PCState pcState() const =0
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:177
std::vector< ContextID > contextIds
Definition: process.hh:160
virtual void setMiscRegNoEffect(RegIndex misc_reg, RegVal val)=0
Bitfield< 0 > sp
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:295
#define DTRACE(x)
Definition: debug.hh:143
Addr maxAddr() const
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:114
std::shared_ptr< MemState > memState
Definition: process.hh:279
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define DPRINTFN(...)
Definition: trace.hh:226
STL vector class.
Definition: stl.hh:37
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:79
ThreadContext * getThreadContext(ContextID tid) const
Definition: system.hh:186
Bitfield< 4 > pc
const int StackPointerReg
Definition: registers.hh:114
RiscvProcess(ProcessParams *params, ::Loader::ObjectFile *objFile)
Definition: process.cc:60
Addr getStartPC()
Definition: process.cc:481
System * system
Definition: process.hh:163
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:199
T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
std::vector< std::string > envp
Definition: process.hh:217
void argsInit(int pageSize)
Definition: process.cc:120
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
const Params * params() const
Definition: sim_object.hh:118
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
Declarations of a non-full system Page Table.
::Loader::MemoryImage image
Definition: process.hh:214
RiscvProcess32(ProcessParams *params, ::Loader::ObjectFile *objFile)
Definition: process.cc:82
Random random_mt
Definition: random.cc:96
Addr entryPoint() const
Definition: object_file.hh:128
const Addr PageBytes
Definition: isa_traits.hh:56
const ByteOrder GuestByteOrder
Definition: isa_traits.hh:51
std::vector< std::string > argv
Definition: process.hh:216
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:106
const char data[]
::Loader::ObjectFile * objFile
Definition: process.hh:213
int ContextID
Globally unique thread context ID.
Definition: types.hh:229
RiscvProcess64(ProcessParams *params, ::Loader::ObjectFile *objFile)
Definition: process.cc:69

Generated on Mon Jun 8 2020 15:34:39 for gem5 by doxygen 1.8.13