gem5  v20.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/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 
69 RiscvProcess64::RiscvProcess64(ProcessParams *params,
70  ::Loader::ObjectFile *objFile) :
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 
82 RiscvProcess32::RiscvProcess32(ProcessParams *params,
83  ::Loader::ObjectFile *objFile) :
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)
102  system->threads[ctx]->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
103 }
104 
105 void
107 {
109 
110  argsInit<uint32_t>(PageBytes);
111  for (ContextID ctx: contextIds) {
112  auto *tc = system->threads[ctx];
113  tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U);
114  PCState pc = tc->pcState();
115  pc.rv32(true);
116  tc->pcState(pc);
117  }
118 }
119 
120 template<class IntType> void
122 {
123  const int RandomBytes = 16;
124  const int addrSize = sizeof(IntType);
125 
126  auto *elfObject = dynamic_cast<::Loader::ElfObject*>(objFile);
127  memState->setStackMin(memState->getStackBase());
128 
129  // Determine stack size and populate auxv
130  Addr stack_top = memState->getStackMin();
131  stack_top -= RandomBytes;
132  for (const string& arg: argv)
133  stack_top -= arg.size() + 1;
134  for (const string& env: envp)
135  stack_top -= env.size() + 1;
136  stack_top &= -addrSize;
137 
139  if (elfObject != nullptr) {
140  auxv.emplace_back(M5_AT_ENTRY, objFile->entryPoint());
141  auxv.emplace_back(M5_AT_PHNUM, elfObject->programHeaderCount());
142  auxv.emplace_back(M5_AT_PHENT, elfObject->programHeaderSize());
143  auxv.emplace_back(M5_AT_PHDR, elfObject->programHeaderTable());
144  auxv.emplace_back(M5_AT_PAGESZ, PageBytes);
145  auxv.emplace_back(M5_AT_SECURE, 0);
146  auxv.emplace_back(M5_AT_RANDOM, stack_top);
147  auxv.emplace_back(M5_AT_NULL, 0);
148  }
149  stack_top -= (1 + argv.size()) * addrSize +
150  (1 + envp.size()) * addrSize +
151  addrSize + 2 * sizeof(IntType) * auxv.size();
152  stack_top &= -2*addrSize;
153  memState->setStackSize(memState->getStackBase() - stack_top);
154  memState->mapRegion(roundDown(stack_top, pageSize),
155  roundUp(memState->getStackSize(), pageSize), "stack");
156 
157  // Copy random bytes (for AT_RANDOM) to stack
158  memState->setStackMin(memState->getStackMin() - RandomBytes);
159  uint8_t at_random[RandomBytes];
160  generate(begin(at_random), end(at_random),
161  [&]{ return random_mt.random(0, 0xFF); });
162  initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes);
163 
164  // Copy argv to stack
165  vector<Addr> argPointers;
166  for (const string& arg: argv) {
167  memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
168  initVirtMem->writeString(memState->getStackMin(), arg.c_str());
169  argPointers.push_back(memState->getStackMin());
170  if (DTRACE(Stack)) {
171  string wrote;
172  initVirtMem->readString(wrote, argPointers.back());
173  DPRINTFN("Wrote arg \"%s\" to address %p\n",
174  wrote, (void*)memState->getStackMin());
175  }
176  }
177  argPointers.push_back(0);
178 
179  // Copy envp to stack
180  vector<Addr> envPointers;
181  for (const string& env: envp) {
182  memState->setStackMin(memState->getStackMin() - (env.size() + 1));
183  initVirtMem->writeString(memState->getStackMin(), env.c_str());
184  envPointers.push_back(memState->getStackMin());
185  DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
186  env, (void*)memState->getStackMin());
187  }
188  envPointers.push_back(0);
189 
190  // Align stack
191  memState->setStackMin(memState->getStackMin() & -addrSize);
192 
193  // Calculate bottom of stack
194  memState->setStackMin(memState->getStackMin() -
195  ((1 + argv.size()) * addrSize +
196  (1 + envp.size()) * addrSize +
197  addrSize + 2 * sizeof(IntType) * auxv.size()));
198  memState->setStackMin(memState->getStackMin() & (-2 * addrSize));
199  Addr sp = memState->getStackMin();
200  const auto pushOntoStack =
201  [this, &sp](IntType data) {
202  initVirtMem->write(sp, data, GuestByteOrder);
203  sp += sizeof(data);
204  };
205 
206  // Push argc and argv pointers onto stack
207  IntType argc = argv.size();
208  DPRINTF(Stack, "Wrote argc %d to address %#x\n", argc, sp);
209  pushOntoStack(argc);
210 
211  for (const Addr& argPointer: argPointers) {
212  DPRINTF(Stack, "Wrote argv pointer %#x to address %#x\n",
213  argPointer, sp);
214  pushOntoStack(argPointer);
215  }
216 
217  // Push env pointers onto stack
218  for (const Addr& envPointer: envPointers) {
219  DPRINTF(Stack, "Wrote envp pointer %#x to address %#x\n",
220  envPointer, sp);
221  pushOntoStack(envPointer);
222  }
223 
224  // Push aux vector onto stack
225  std::map<IntType, string> aux_keys = {
226  {M5_AT_ENTRY, "M5_AT_ENTRY"},
227  {M5_AT_PHNUM, "M5_AT_PHNUM"},
228  {M5_AT_PHENT, "M5_AT_PHENT"},
229  {M5_AT_PHDR, "M5_AT_PHDR"},
230  {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
231  {M5_AT_SECURE, "M5_AT_SECURE"},
232  {M5_AT_RANDOM, "M5_AT_RANDOM"},
233  {M5_AT_NULL, "M5_AT_NULL"}
234  };
235  for (const auto &aux: auxv) {
236  DPRINTF(Stack, "Wrote aux key %s to address %#x\n",
237  aux_keys[aux.type], sp);
238  pushOntoStack(aux.type);
239  DPRINTF(Stack, "Wrote aux value %x to address %#x\n", aux.val, sp);
240  pushOntoStack(aux.val);
241  }
242 
244  tc->setIntReg(StackPointerReg, memState->getStackMin());
245  tc->pcState(getStartPC());
246 
247  memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
248 }
249 
251  10, 11, 12, 13, 14, 15, 16
252 };
RiscvISA::MISCREG_PRV
@ MISCREG_PRV
Definition: registers.hh:129
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:217
data
const char data[]
Definition: circlebuf.test.cc:42
M5_AT_NULL
@ M5_AT_NULL
Definition: aux_vector.hh:58
Process
Definition: process.hh:65
ContextID
int ContextID
Globally unique thread context ID.
Definition: types.hh:231
Process::argv
std::vector< std::string > argv
Definition: process.hh:216
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:49
process_impl.hh
DTRACE
#define DTRACE(x)
Definition: debug.hh:146
std::vector
STL vector class.
Definition: stl.hh:37
Process::initVirtMem
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:177
isa.hh
Loader::ElfObject
Definition: elf_object.hh:59
Loader::MemoryImage::maxAddr
Addr maxAddr() const
Definition: memory_image.hh:131
RiscvISA
Definition: fs_workload.cc:36
M5_AT_ENTRY
@ M5_AT_ENTRY
Definition: aux_vector.hh:67
random_mt
Random random_mt
Definition: random.cc:96
RiscvProcess::RiscvProcess
RiscvProcess(ProcessParams *params, ::Loader::ObjectFile *objFile)
Definition: process.cc:60
Loader::ObjectFile
Definition: object_file.hh:70
M5_AT_PHNUM
@ M5_AT_PHNUM
Definition: aux_vector.hh:63
elf_object.hh
Loader::ObjectFile::entryPoint
Addr entryPoint() const
Definition: object_file.hh:108
syscall_return.hh
RiscvProcess::argsInit
void argsInit(int pageSize)
Definition: process.cc:121
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:48
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:240
process.hh
RiscvISA::PRV_U
@ PRV_U
Definition: isa.hh:58
RiscvProcess64::RiscvProcess64
RiscvProcess64(ProcessParams *params, ::Loader::ObjectFile *objFile)
Definition: process.cc:69
process.hh
Process::image
::Loader::MemoryImage image
Definition: process.hh:214
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:142
Process::objFile
::Loader::ObjectFile * objFile
Definition: process.hh:213
SimObject::params
const Params * params() const
Definition: sim_object.hh:119
name
const std::string & name()
Definition: trace.cc:50
Process::contextIds
std::vector< ContextID > contextIds
Definition: process.hh:160
RiscvProcess::SyscallABI::ArgumentRegs
static const std::vector< int > ArgumentRegs
Definition: process.hh:60
registers.hh
RiscvProcess
Definition: process.hh:47
ThreadContext::pcState
virtual TheISA::PCState pcState() const =0
System::threads
Threads threads
Definition: system.hh:309
ArmISA::PageBytes
const Addr PageBytes
Definition: isa_traits.hh:52
aux_vector.hh
ArmISA::StackPointerReg
const int StackPointerReg
Definition: registers.hh:114
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
Process::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:290
roundUp
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
RiscvProcess64::initState
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:96
logging.hh
Random::random
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:86
Process::getStartPC
Addr getStartPC()
Definition: process.cc:476
DPRINTFN
#define DPRINTFN(...)
Definition: trace.hh:238
Process::system
System * system
Definition: process.hh:163
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
RiscvProcess32::RiscvProcess32
RiscvProcess32(ProcessParams *params, ::Loader::ObjectFile *objFile)
Definition: process.cc:82
thread_context.hh
Process::memState
std::shared_ptr< MemState > memState
Definition: process.hh:279
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:106

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