gem5  v19.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  * Authors: Gabe Black
30  * Ali Saidi
31  * Korey Sewell
32  * Alec Roelke
33  */
34 #include "arch/riscv/process.hh"
35 
36 #include <algorithm>
37 #include <cstddef>
38 #include <iostream>
39 #include <iterator>
40 #include <map>
41 #include <string>
42 #include <vector>
43 
44 #include "arch/riscv/isa.hh"
45 #include "arch/riscv/isa_traits.hh"
46 #include "arch/riscv/registers.hh"
49 #include "base/logging.hh"
50 #include "base/random.hh"
51 #include "cpu/thread_context.hh"
52 #include "debug/Stack.hh"
53 #include "mem/page_table.hh"
54 #include "params/Process.hh"
55 #include "sim/aux_vector.hh"
56 #include "sim/process.hh"
57 #include "sim/process_impl.hh"
58 #include "sim/syscall_return.hh"
59 #include "sim/system.hh"
60 
61 using namespace std;
62 using namespace RiscvISA;
63 
64 RiscvProcess::RiscvProcess(ProcessParams *params, 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 
73  RiscvProcess(params, objFile)
74 {
75  const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
76  const Addr max_stack_size = 8 * 1024 * 1024;
77  const Addr next_thread_stack_base = stack_base - max_stack_size;
78  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
79  const Addr mmap_end = 0x4000000000000000L;
80  memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
81  next_thread_stack_base, mmap_end);
82 }
83 
85  RiscvProcess(params, objFile)
86 {
87  const Addr stack_base = 0x7FFFFFFF;
88  const Addr max_stack_size = 8 * 1024 * 1024;
89  const Addr next_thread_stack_base = stack_base - max_stack_size;
90  const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
91  const Addr mmap_end = 0x40000000L;
92  memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
93  next_thread_stack_base, mmap_end);
94 }
95 
96 void
98 {
100 
101  argsInit<uint64_t>(PageBytes);
102  for (ContextID ctx: contextIds)
104 }
105 
106 void
108 {
110 
111  argsInit<uint32_t>(PageBytes);
112  for (ContextID ctx: contextIds) {
115  pc.rv32(true);
116  system->getThreadContext(ctx)->pcState(pc);
117  }
118 }
119 
120 template<class IntType> void
122 {
123  const int RandomBytes = 16;
124  const int addrSize = sizeof(IntType);
125 
126  ElfObject* elfObject = dynamic_cast<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  allocateMem(roundDown(stack_top, pageSize),
155  roundUp(memState->getStackSize(), pageSize));
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) {
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 
250 RegVal
252 {
253  // If a larger index is requested than there are syscall argument
254  // registers, return 0
255  RegVal retval = 0;
256  if (i < SyscallArgumentRegs.size())
257  retval = tc->readIntReg(SyscallArgumentRegs[i]);
258  i++;
259  return retval;
260 }
261 
262 void
264 {
265  if (sysret.successful()) {
266  // no error
268  } else {
269  // got an error, return details
271  }
272 }
#define DPRINTF(x,...)
Definition: trace.hh:229
ObjectFile * objFile
Definition: process.hh:217
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:97
Addr programHeaderTable()
Definition: elf_object.hh:128
Bitfield< 7, 0 > L
Definition: int.hh:59
void rv32(bool val)
Definition: types.hh:70
const std::string & name()
Definition: trace.cc:54
Bitfield< 7 > i
virtual TheISA::PCState pcState() const =0
virtual RegVal readIntReg(RegIndex reg_idx) const =0
bool successful() const
Was the system call successful?
std::vector< ContextID > contextIds
Definition: process.hh:167
void writeString(Addr addr, const char *str) const
Same as tryWriteString, but insists on success.
Definition: port_proxy.hh:241
virtual void setMiscRegNoEffect(RegIndex misc_reg, RegVal val)=0
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition: process.cc:333
const std::vector< int > SyscallArgumentRegs
Definition: registers.hh:112
SETranslatingPortProxy initVirtMem
Definition: process.hh:183
RiscvProcess(ProcessParams *params, ObjectFile *objFile)
Definition: process.cc:64
Bitfield< 0 > sp
uint64_t RegVal
Definition: types.hh:168
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:307
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:168
std::shared_ptr< MemState > memState
Definition: process.hh:283
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define DPRINTFN(...)
Definition: trace.hh:233
int64_t encodedValue() const
The encoded value (as described above)
const ByteOrder GuestByteOrder
Definition: isa_traits.hh:42
STL vector class.
Definition: stl.hh:40
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:83
ThreadContext * getThreadContext(ContextID tid) const
Definition: system.hh:194
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) override
Definition: process.cc:263
Bitfield< 4 > pc
#define DTRACE(x)
Definition: trace.hh:227
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:189
const Params * params() const
Definition: sim_object.hh:114
Addr maxAddr() const
Addr getStartPC()
Definition: process.cc:532
System * system
Definition: process.hh:170
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:203
const RegIndex StackPointerReg
Definition: registers.hh:77
T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:185
const RegIndex SyscallPseudoReturnReg
Definition: registers.hh:86
RiscvProcess32(ProcessParams *params, ObjectFile *objFile)
Definition: process.cc:84
std::vector< std::string > envp
Definition: process.hh:221
void argsInit(int pageSize)
Definition: process.cc:121
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
int64_t returnValue() const
The return value.
const Addr PageBytes
Definition: isa_traits.hh:47
uint16_t programHeaderSize()
Definition: elf_object.hh:129
RiscvProcess64(ProcessParams *params, ObjectFile *objFile)
Definition: process.cc:72
void readString(std::string &str, Addr addr) const
Same as tryReadString, but insists on success.
Definition: port_proxy.hh:257
Declarations of a non-full system Page Table.
uint16_t programHeaderCount()
Definition: elf_object.hh:130
Random random_mt
Definition: random.cc:100
Addr entryPoint() const
Definition: object_file.hh:131
void write(Addr address, const T &data) const
Write object T to address.
Definition: port_proxy.hh:293
std::vector< std::string > argv
Definition: process.hh:220
This class represents the return value from an emulated system call, including any errno setting...
RegVal getSyscallArg(ThreadContext *tc, int &i) override
Definition: process.cc:251
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:107
const char data[]
int ContextID
Globally unique thread context ID.
Definition: types.hh:231
MemoryImage image
Definition: process.hh:218

Generated on Fri Feb 28 2020 16:26:56 for gem5 by doxygen 1.8.13