gem5  v22.1.0.0
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/page_size.hh"
42 #include "arch/riscv/regs/int.hh"
43 #include "arch/riscv/regs/misc.hh"
46 #include "base/logging.hh"
47 #include "base/random.hh"
48 #include "cpu/thread_context.hh"
49 #include "debug/Stack.hh"
50 #include "mem/page_table.hh"
51 #include "params/Process.hh"
52 #include "sim/aux_vector.hh"
53 #include "sim/process.hh"
54 #include "sim/process_impl.hh"
55 #include "sim/syscall_return.hh"
56 #include "sim/system.hh"
57 
58 namespace gem5
59 {
60 
61 using namespace RiscvISA;
62 
63 RiscvProcess::RiscvProcess(const ProcessParams &params,
64  loader::ObjectFile *objFile) :
65  Process(params,
66  new EmulationPageTable(params.name, params.pid, PageBytes),
67  objFile)
68 {
69  fatal_if(params.useArchPT, "Arch page tables not implemented.");
70 }
71 
72 RiscvProcess64::RiscvProcess64(const ProcessParams &params,
73  loader::ObjectFile *objFile) :
74  RiscvProcess(params, objFile)
75 {
76  const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
77  const Addr max_stack_size = 8 * 1024 * 1024;
78  const Addr next_thread_stack_base = stack_base - max_stack_size;
79  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
80  const Addr mmap_end = 0x4000000000000000L;
81  memState = std::make_shared<MemState>(this, brk_point, stack_base,
82  max_stack_size, next_thread_stack_base, mmap_end);
83 }
84 
85 RiscvProcess32::RiscvProcess32(const ProcessParams &params,
86  loader::ObjectFile *objFile) :
87  RiscvProcess(params, objFile)
88 {
89  const Addr stack_base = 0x7FFFFFFF;
90  const Addr max_stack_size = 8 * 1024 * 1024;
91  const Addr next_thread_stack_base = stack_base - max_stack_size;
92  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
93  const Addr mmap_end = 0x40000000L;
94  memState = std::make_shared<MemState>(this, brk_point, stack_base,
95  max_stack_size, next_thread_stack_base, mmap_end);
96 }
97 
98 void
100 {
102 
103  argsInit<uint64_t>(PageBytes);
104  for (ContextID ctx: contextIds)
105  system->threads[ctx]->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
106 }
107 
108 void
110 {
112 
113  argsInit<uint32_t>(PageBytes);
114  for (ContextID ctx: contextIds) {
115  auto *tc = system->threads[ctx];
116  tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
117  PCState pc = tc->pcState().as<PCState>();
118  pc.rv32(true);
119  tc->pcState(pc);
120  }
121 }
122 
123 template<class IntType> void
125 {
126  const int RandomBytes = 16;
127  const int addrSize = sizeof(IntType);
128 
129  auto *elfObject = dynamic_cast<loader::ElfObject*>(objFile);
130  memState->setStackMin(memState->getStackBase());
131 
132  // Determine stack size and populate auxv
133  Addr stack_top = memState->getStackMin();
134  stack_top -= RandomBytes;
135  for (const std::string& arg: argv)
136  stack_top -= arg.size() + 1;
137  for (const std::string& env: envp)
138  stack_top -= env.size() + 1;
139  stack_top &= -addrSize;
140 
142  if (elfObject != nullptr) {
143  auxv.emplace_back(gem5::auxv::Entry, objFile->entryPoint());
144  auxv.emplace_back(gem5::auxv::Phnum, elfObject->programHeaderCount());
145  auxv.emplace_back(gem5::auxv::Phent, elfObject->programHeaderSize());
146  auxv.emplace_back(gem5::auxv::Phdr, elfObject->programHeaderTable());
147  auxv.emplace_back(gem5::auxv::Pagesz, PageBytes);
148  auxv.emplace_back(gem5::auxv::Secure, 0);
149  auxv.emplace_back(gem5::auxv::Random, stack_top);
150  auxv.emplace_back(gem5::auxv::Null, 0);
151  }
152  stack_top -= (1 + argv.size()) * addrSize +
153  (1 + envp.size()) * addrSize +
154  addrSize + 2 * sizeof(IntType) * auxv.size();
155  stack_top &= -2*addrSize;
156  memState->setStackSize(memState->getStackBase() - stack_top);
157  memState->mapRegion(roundDown(stack_top, pageSize),
158  roundUp(memState->getStackSize(), pageSize), "stack");
159 
160  // Copy random bytes (for AT_RANDOM) to stack
161  memState->setStackMin(memState->getStackMin() - RandomBytes);
162  uint8_t at_random[RandomBytes];
163  std::generate(std::begin(at_random), std::end(at_random),
164  [&]{ return random_mt.random(0, 0xFF); });
165  initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes);
166 
167  // Copy argv to stack
168  std::vector<Addr> argPointers;
169  for (const std::string& arg: argv) {
170  memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
171  initVirtMem->writeString(memState->getStackMin(), arg.c_str());
172  argPointers.push_back(memState->getStackMin());
173  if (debug::Stack) {
174  std::string wrote;
175  initVirtMem->readString(wrote, argPointers.back());
176  DPRINTFN("Wrote arg \"%s\" to address %p\n",
177  wrote, (void*)memState->getStackMin());
178  }
179  }
180  argPointers.push_back(0);
181 
182  // Copy envp to stack
183  std::vector<Addr> envPointers;
184  for (const std::string& env: envp) {
185  memState->setStackMin(memState->getStackMin() - (env.size() + 1));
186  initVirtMem->writeString(memState->getStackMin(), env.c_str());
187  envPointers.push_back(memState->getStackMin());
188  DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
189  env, (void*)memState->getStackMin());
190  }
191  envPointers.push_back(0);
192 
193  // Align stack
194  memState->setStackMin(memState->getStackMin() & -addrSize);
195 
196  // Calculate bottom of stack
197  memState->setStackMin(memState->getStackMin() -
198  ((1 + argv.size()) * addrSize +
199  (1 + envp.size()) * addrSize +
200  addrSize + 2 * sizeof(IntType) * auxv.size()));
201  memState->setStackMin(memState->getStackMin() & (-2 * addrSize));
202  Addr sp = memState->getStackMin();
203  const auto pushOntoStack =
204  [this, &sp](IntType data) {
205  initVirtMem->write(sp, data, ByteOrder::little);
206  sp += sizeof(data);
207  };
208 
209  // Push argc and argv pointers onto stack
210  IntType argc = argv.size();
211  DPRINTF(Stack, "Wrote argc %d to address %#x\n", argc, sp);
212  pushOntoStack(argc);
213 
214  for (const Addr& argPointer: argPointers) {
215  DPRINTF(Stack, "Wrote argv pointer %#x to address %#x\n",
216  argPointer, sp);
217  pushOntoStack(argPointer);
218  }
219 
220  // Push env pointers onto stack
221  for (const Addr& envPointer: envPointers) {
222  DPRINTF(Stack, "Wrote envp pointer %#x to address %#x\n",
223  envPointer, sp);
224  pushOntoStack(envPointer);
225  }
226 
227  // Push aux vector onto stack
228  std::map<IntType, std::string> aux_keys = {
229  {gem5::auxv::Entry, "gem5::auxv::Entry"},
230  {gem5::auxv::Phnum, "gem5::auxv::Phnum"},
231  {gem5::auxv::Phent, "gem5::auxv::Phent"},
232  {gem5::auxv::Phdr, "gem5::auxv::Phdr"},
233  {gem5::auxv::Pagesz, "gem5::auxv::Pagesz"},
234  {gem5::auxv::Secure, "gem5::auxv::Secure"},
235  {gem5::auxv::Random, "gem5::auxv::Random"},
236  {gem5::auxv::Null, "gem5::auxv::Null"}
237  };
238  for (const auto &aux: auxv) {
239  DPRINTF(Stack, "Wrote aux key %s to address %#x\n",
240  aux_keys[aux.type], sp);
241  pushOntoStack(aux.type);
242  DPRINTF(Stack, "Wrote aux value %x to address %#x\n", aux.val, sp);
243  pushOntoStack(aux.val);
244  }
245 
247  tc->setReg(StackPointerReg, memState->getStackMin());
248  tc->pcState(getStartPC());
249 
250  memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
251 }
252 
253 } // namespace gem5
#define DPRINTFN(...)
Definition: trace.hh:214
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
loader::MemoryImage image
Definition: process.hh:225
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:188
std::shared_ptr< MemState > memState
Definition: process.hh:290
std::vector< std::string > argv
Definition: process.hh:227
std::vector< ContextID > contextIds
Definition: process.hh:171
System * system
Definition: process.hh:174
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:288
std::vector< std::string > envp
Definition: process.hh:228
Addr getStartPC()
Definition: process.cc:497
loader::ObjectFile * objFile
Definition: process.hh:224
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:109
RiscvProcess32(const ProcessParams &params, loader::ObjectFile *objFile)
Definition: process.cc:85
RiscvProcess64(const ProcessParams &params, loader::ObjectFile *objFile)
Definition: process.cc:72
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:99
RiscvProcess(const ProcessParams &params, loader::ObjectFile *objFile)
Definition: process.cc:63
void argsInit(int pageSize)
Definition: process.cc:124
Threads threads
Definition: system.hh:313
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual const PCStateBase & pcState() const =0
virtual void setReg(const RegId &reg, RegVal val)
STL vector class.
Definition: stl.hh:37
Random random_mt
Definition: random.cc:99
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:90
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:279
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:260
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
const Params & params() const
Definition: sim_object.hh:176
constexpr auto & StackPointerReg
Definition: int.hh:654
Bitfield< 0 > sp
Definition: misc_types.hh:75
Bitfield< 4 > pc
const Addr PageBytes
Definition: page_size.hh:54
@ MISCREG_PRV
Definition: misc.hh:67
const Addr PageBytes
Definition: page_size.hh:42
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
int ContextID
Globally unique thread context ID.
Definition: types.hh:239
Declarations of a non-full system Page Table.
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:26 for gem5 by doxygen 1.9.1