gem5 v24.0.0.0
Loading...
Searching...
No Matches
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
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
50namespace gem5
51{
52
53using 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
81void
83{
85
88 else
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>();
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.relocate(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
137template <typename IntType>
138void
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:82
@ HWCAP_FEATURE_TRUE_LE
Definition process.hh:81
@ HWCAP_FEATURE_64
Definition process.hh:61
@ HWCAP_FEATURE_32
Definition process.hh:60
#define DPRINTF(x,...)
Definition trace.hh:210
void set(Addr val) override
Force this PC to reflect a particular value, resetting all its other fields around it.
Definition pcstate.hh:378
Target & as()
Definition pcstate.hh:73
ByteOrder byteOrder() const
Definition pcstate.hh:67
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:224
uint64_t egid()
Definition process.hh:85
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition process.hh:187
std::shared_ptr< MemState > memState
Definition process.hh:289
uint64_t uid()
Definition process.hh:82
std::vector< std::string > argv
Definition process.hh:226
loader::MemoryImage interpImage
Definition process.hh:225
std::vector< ContextID > contextIds
Definition process.hh:170
System * system
Definition process.hh:173
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:227
uint64_t gid()
Definition process.hh:84
Addr getStartPC()
Definition process.cc:497
loader::ObjectFile * objFile
Definition process.hh:223
Addr getBias()
Definition process.cc:489
uint64_t euid()
Definition process.hh:83
Threads threads
Definition system.hh:310
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void setReg(const RegId &reg, RegVal val)
virtual const PCStateBase & pcState() const =0
bool write(const PortProxy &proxy) const
ByteOrder getByteOrder() const
void clear()
Clears the table.
Definition symtab.cc:58
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition symtab.cc:66
void relocate(const Addr new_addr)
Definition symtab.hh:118
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:236
const Params & params() const
ByteOrder byteOrder(const ThreadContext *tc)
Definition utility.hh:359
constexpr auto & StackPointerReg
Definition int.hh:654
Bitfield< 7 > i
Definition misc_types.hh:67
constexpr RegClass intRegClass
Definition int.hh:173
const Addr PageBytes
Definition page_size.hh:53
Bitfield< 4 > pc
constexpr RegId Msr
Definition int.hh:144
constexpr auto & TOCPointerReg
Definition int.hh:161
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition symtab.cc:55
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t RegVal
Definition types.hh:173
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
void copyStringArray(std::vector< std::string > &strings, AddrType array_ptr, AddrType data_ptr, const ByteOrder bo, PortProxy &memProxy)
Declarations of a non-full system Page Table.
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:06 for gem5 by doxygen 1.11.0