gem5  v22.1.0.0
process.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2008 The Florida State University
3  * Copyright (c) 2009 The University of Edinburgh
4  * Copyright (c) 2021 IBM Corporation
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met: redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer;
11  * redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution;
14  * neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "arch/power/process.hh"
32 
33 #include "arch/power/page_size.hh"
34 #include "arch/power/regs/int.hh"
35 #include "arch/power/regs/misc.hh"
36 #include "arch/power/types.hh"
39 #include "base/logging.hh"
40 #include "cpu/thread_context.hh"
41 #include "debug/Stack.hh"
42 #include "mem/page_table.hh"
43 #include "params/Process.hh"
44 #include "sim/aux_vector.hh"
45 #include "sim/byteswap.hh"
46 #include "sim/process_impl.hh"
47 #include "sim/syscall_return.hh"
48 #include "sim/system.hh"
49 
50 namespace gem5
51 {
52 
53 using namespace PowerISA;
54 
56  const ProcessParams &params, loader::ObjectFile *objFile)
57  : Process(params,
58  new EmulationPageTable(params.name, params.pid, PageBytes),
59  objFile)
60 {
61  fatal_if(params.useArchPT, "Arch page tables not implemented.");
62  // Set up break point (Top of Heap)
63  Addr brk_point = image.maxAddr();
64  brk_point = roundUp(brk_point, PageBytes);
65 
66  Addr stack_base = 0xbf000000L;
67 
68  Addr max_stack_size = 8 * 1024 * 1024;
69 
70  // Set pointer for next thread stack. Reserve 8M for main stack.
71  Addr next_thread_stack_base = stack_base - max_stack_size;
72 
73  // Set up region for mmaps. For now, start at bottom of kuseg space.
74  Addr mmap_end = 0x70000000L;
75 
76  memState = std::make_shared<MemState>(
77  this, brk_point, stack_base, max_stack_size,
78  next_thread_stack_base, mmap_end);
79 }
80 
81 void
83 {
85 
86  if (objFile->getArch() == loader::Power)
87  argsInit<uint32_t>(PageBytes);
88  else
89  argsInit<uint64_t>(PageBytes);
90 
91  // Fix up entry point and symbol table for 64-bit ELF ABI v1
93  return;
94 
95  // Fix entry point address and the base TOC pointer by looking the
96  // the function descriptor in the .opd section
97  Addr entryPoint, tocBase;
98  ByteOrder byteOrder = objFile->getByteOrder();
100 
101  // The first doubleword of the descriptor contains the address of the
102  // entry point of the function
103  initVirtMem->readBlob(getStartPC(), &entryPoint, sizeof(Addr));
104 
105  // Update the PC state
106  auto pc = tc->pcState().as<PowerISA::PCState>();
107  pc.byteOrder(byteOrder);
108  pc.set(gtoh(entryPoint, byteOrder));
109  tc->pcState(pc);
110 
111  // The second doubleword of the descriptor contains the TOC base
112  // address for the function
113  initVirtMem->readBlob(getStartPC() + 8, &tocBase, sizeof(Addr));
114  tc->setReg(TOCPointerReg, gtoh(tocBase, byteOrder));
115 
116  // Fix symbol table entries as they would otherwise point to the
117  // function descriptor rather than the actual entry point address
118  auto *symbolTable = new loader::SymbolTable;
119 
120  for (auto sym : loader::debugSymbolTable) {
121  Addr entry;
122  loader::Symbol symbol = sym;
123 
124  // Try to read entry point from function descriptor
125  if (initVirtMem->tryReadBlob(sym.address, &entry, sizeof(Addr)))
126  symbol.address = gtoh(entry, byteOrder);
127 
128  symbolTable->insert(symbol);
129  }
130 
131  // Replace the current debug symbol table
133  loader::debugSymbolTable.insert(*symbolTable);
134  delete symbolTable;
135 }
136 
137 template <typename IntType>
138 void
140 {
141  int intSize = sizeof(IntType);
142  ByteOrder byteOrder = objFile->getByteOrder();
143  bool is64bit = (objFile->getArch() == loader::Power64);
144  bool isLittleEndian = (byteOrder == ByteOrder::little);
146 
147  std::string filename;
148  if (argv.size() < 1)
149  filename = "";
150  else
151  filename = argv[0];
152 
153  //We want 16 byte alignment
154  uint64_t align = 16;
155 
156  // load object file into target memory
159 
160  //Setup the auxilliary vectors. These will already have endian conversion.
161  //Auxilliary vectors are loaded only for elf formatted executables.
162  auto *elfObject = dynamic_cast<loader::ElfObject *>(objFile);
163  if (elfObject) {
164  IntType features = HWCAP_FEATURE_32;
165 
166  // Check if running in 64-bit mode
167  if (is64bit)
168  features |= HWCAP_FEATURE_64;
169 
170  // Check if running in little endian mode
171  if (isLittleEndian)
173 
174  //Bits which describe the system hardware capabilities
175  //XXX Figure out what these should be
176  auxv.emplace_back(gem5::auxv::Hwcap, features);
177  //The system page size
178  auxv.emplace_back(gem5::auxv::Pagesz, pageSize);
179  //Frequency at which times() increments
180  auxv.emplace_back(gem5::auxv::Clktck, 0x64);
181  // For statically linked executables, this is the virtual address of
182  // the program header tables if they appear in the executable image
183  auxv.emplace_back(gem5::auxv::Phdr, elfObject->programHeaderTable());
184  // This is the size of a program header entry from the elf file.
185  auxv.emplace_back(gem5::auxv::Phent, elfObject->programHeaderSize());
186  // This is the number of program headers from the original elf file.
187  auxv.emplace_back(gem5::auxv::Phnum, elfObject->programHeaderCount());
188  // This is the base address of the ELF interpreter; it should be
189  // zero for static executables or contain the base address for
190  // dynamic executables.
191  auxv.emplace_back(gem5::auxv::Base, getBias());
192  //XXX Figure out what this should be.
193  auxv.emplace_back(gem5::auxv::Flags, 0);
194  //The entry point to the program
195  auxv.emplace_back(gem5::auxv::Entry, objFile->entryPoint());
196  //Different user and group IDs
197  auxv.emplace_back(gem5::auxv::Uid, uid());
198  auxv.emplace_back(gem5::auxv::Euid, euid());
199  auxv.emplace_back(gem5::auxv::Gid, gid());
200  auxv.emplace_back(gem5::auxv::Egid, egid());
201  //Whether to enable "secure mode" in the executable
202  auxv.emplace_back(gem5::auxv::Secure, 0);
203  //The address of 16 "random" bytes
204  auxv.emplace_back(gem5::auxv::Random, 0);
205  //The filename of the program
206  auxv.emplace_back(gem5::auxv::Execfn, 0);
207  //The string "v51" with unknown meaning
208  auxv.emplace_back(gem5::auxv::Platform, 0);
209  }
210 
211  //Figure out how big the initial stack nedes to be
212 
213  // A sentry NULL void pointer at the top of the stack.
214  int sentry_size = intSize;
215 
216  std::string platform = "v51";
217  int platform_size = platform.size() + 1;
218 
219  // The aux vectors are put on the stack in two groups. The first group are
220  // the vectors that are generated as the elf is loaded. The second group
221  // are the ones that were computed ahead of time and include the platform
222  // string.
223  int aux_data_size = filename.size() + 1;
224 
225  const int numRandomBytes = 16;
226  aux_data_size += numRandomBytes;
227 
228  int env_data_size = 0;
229  for (int i = 0; i < envp.size(); ++i) {
230  env_data_size += envp[i].size() + 1;
231  }
232  int arg_data_size = 0;
233  for (int i = 0; i < argv.size(); ++i) {
234  arg_data_size += argv[i].size() + 1;
235  }
236 
237  int info_block_size =
238  sentry_size + env_data_size + arg_data_size +
239  aux_data_size + platform_size;
240 
241  //Each auxilliary vector is two 4 byte words
242  int aux_array_size = intSize * 2 * (auxv.size() + 1);
243 
244  int envp_array_size = intSize * (envp.size() + 1);
245  int argv_array_size = intSize * (argv.size() + 1);
246 
247  int argc_size = intSize;
248 
249  //Figure out the size of the contents of the actual initial frame
250  int frame_size =
251  info_block_size +
252  aux_array_size +
253  envp_array_size +
254  argv_array_size +
255  argc_size;
256 
257  //There needs to be padding after the auxiliary vector data so that the
258  //very bottom of the stack is aligned properly.
259  int partial_size = frame_size;
260  int aligned_partial_size = roundUp(partial_size, align);
261  int aux_padding = aligned_partial_size - partial_size;
262 
263  int space_needed = frame_size + aux_padding;
264 
265  Addr stack_min = memState->getStackBase() - space_needed;
266  stack_min = roundDown(stack_min, align);
267 
268  memState->setStackSize(memState->getStackBase() - stack_min);
269 
270  // map memory
271  memState->mapRegion(roundDown(stack_min, pageSize),
272  roundUp(memState->getStackSize(), pageSize), "stack");
273 
274  // map out initial stack contents
275  IntType sentry_base = memState->getStackBase() - sentry_size;
276  IntType aux_data_base = sentry_base - aux_data_size;
277  IntType env_data_base = aux_data_base - env_data_size;
278  IntType arg_data_base = env_data_base - arg_data_size;
279  IntType platform_base = arg_data_base - platform_size;
280  IntType auxv_array_base = platform_base - aux_array_size - aux_padding;
281  IntType envp_array_base = auxv_array_base - envp_array_size;
282  IntType argv_array_base = envp_array_base - argv_array_size;
283  IntType argc_base = argv_array_base - argc_size;
284 
285  DPRINTF(Stack, "The addresses of items on the initial stack:\n");
286  DPRINTF(Stack, "0x%x - aux data\n", aux_data_base);
287  DPRINTF(Stack, "0x%x - env data\n", env_data_base);
288  DPRINTF(Stack, "0x%x - arg data\n", arg_data_base);
289  DPRINTF(Stack, "0x%x - platform base\n", platform_base);
290  DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base);
291  DPRINTF(Stack, "0x%x - envp array\n", envp_array_base);
292  DPRINTF(Stack, "0x%x - argv array\n", argv_array_base);
293  DPRINTF(Stack, "0x%x - argc \n", argc_base);
294  DPRINTF(Stack, "0x%x - stack min\n", stack_min);
295 
296  // write contents to stack
297 
298  // figure out argc
299  IntType argc = argv.size();
300  IntType guestArgc = htog(argc, byteOrder);
301 
302  //Write out the sentry void *
303  IntType sentry_NULL = 0;
304  initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
305 
306  //Fix up the aux vectors which point to other data
307  for (int i = auxv.size() - 1; i >= 0; i--) {
308  if (auxv[i].type == gem5::auxv::Platform) {
309  auxv[i].val = platform_base;
310  initVirtMem->writeString(platform_base, platform.c_str());
311  } else if (auxv[i].type == gem5::auxv::Execfn) {
312  auxv[i].val = aux_data_base + numRandomBytes;
313  initVirtMem->writeString(aux_data_base, filename.c_str());
314  } else if (auxv[i].type == gem5::auxv::Random) {
315  auxv[i].val = aux_data_base;
316  }
317  }
318 
319  //Copy the aux stuff
320  Addr auxv_array_end = auxv_array_base;
321  for (const auto &aux: auxv) {
322  initVirtMem->write(auxv_array_end, aux, byteOrder);
323  auxv_array_end += sizeof(aux);
324  }
325  //Write out the terminating zeroed auxilliary vector
326  const gem5::auxv::AuxVector<uint64_t> zero(0, 0);
327  initVirtMem->write(auxv_array_end, zero);
328  auxv_array_end += sizeof(zero);
329 
330  copyStringArray(envp, envp_array_base, env_data_base,
332  copyStringArray(argv, argv_array_base, arg_data_base,
334 
335  initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
336 
338 
339  //Set the stack pointer register
340  tc->setReg(StackPointerReg, stack_min);
341 
342  //Reset the special-purpose registers
343  for (int i = int_reg::NumArchRegs; i < int_reg::NumRegs; i++)
344  tc->setReg(intRegClass[i], (RegVal)0);
345 
346  //Set the machine status for a typical userspace
347  Msr msr = 0;
348  msr.sf = is64bit;
349  msr.hv = 1;
350  msr.ee = 1;
351  msr.pr = 1;
352  msr.me = 1;
353  msr.ir = 1;
354  msr.dr = 1;
355  msr.ri = 1;
356  msr.le = isLittleEndian;
357  tc->setReg(int_reg::Msr, msr);
358 
359  auto pc = tc->pcState().as<PowerISA::PCState>();
360  pc.set(getStartPC());
361  pc.byteOrder(byteOrder);
362  tc->pcState(pc);
363 
364  //Align the "stack_min" to a page boundary.
365  memState->setStackMin(roundDown(stack_min, pageSize));
366 }
367 
368 } // namespace gem5
@ HWCAP_FEATURE_PPC_LE
Definition: process.hh:83
@ HWCAP_FEATURE_TRUE_LE
Definition: process.hh:82
@ HWCAP_FEATURE_64
Definition: process.hh:62
@ HWCAP_FEATURE_32
Definition: process.hh:61
#define DPRINTF(x,...)
Definition: trace.hh:186
Target & as()
Definition: pcstate.hh:72
PowerProcess(const ProcessParams &params, loader::ObjectFile *objFile)
Definition: process.cc:55
void argsInit(int pageSize)
Definition: process.cc:139
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:82
loader::MemoryImage image
Definition: process.hh:225
uint64_t egid()
Definition: process.hh:86
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:188
std::shared_ptr< MemState > memState
Definition: process.hh:290
uint64_t uid()
Definition: process.hh:83
std::vector< std::string > argv
Definition: process.hh:227
loader::MemoryImage interpImage
Definition: process.hh:226
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
uint64_t gid()
Definition: process.hh:85
Addr getStartPC()
Definition: process.cc:497
loader::ObjectFile * objFile
Definition: process.hh:224
Addr getBias()
Definition: process.cc:489
uint64_t euid()
Definition: process.hh:84
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)
bool write(const PortProxy &proxy) const
Definition: memory_image.cc:54
ByteOrder getByteOrder() const
Definition: object_file.hh:129
void clear()
Clears the table.
Definition: symtab.cc:47
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition: symtab.cc:55
STL vector class.
Definition: stl.hh:37
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
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:357
constexpr auto & StackPointerReg
Definition: int.hh:654
Bitfield< 7 > i
Definition: misc_types.hh:67
constexpr RegClass intRegClass
Definition: int.hh:173
Bitfield< 4 > pc
constexpr RegId Msr
Definition: int.hh:144
constexpr auto & TOCPointerReg
Definition: int.hh:161
const Addr PageBytes
Definition: page_size.hh:44
const Addr PageBytes
Definition: page_size.hh:42
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:44
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
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:194
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
uint64_t RegVal
Definition: types.hh:173
void copyStringArray(std::vector< std::string > &strings, AddrType array_ptr, AddrType data_ptr, const ByteOrder bo, PortProxy &memProxy)
Definition: process_impl.hh:43
void align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
Definition: scfx_rep.cc:2051
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