gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
process.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
3 * Copyright (c) 2012 ARM Limited
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2001-2005 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#include "sim/process.hh"
43
44#include <fcntl.h>
45#include <unistd.h>
46
47#include <array>
48#include <climits>
49#include <csignal>
50#include <map>
51#include <string>
52#include <vector>
53
54#include "base/intmath.hh"
56#include "base/loader/symtab.hh"
57#include "base/statistics.hh"
58#include "cpu/thread_context.hh"
59#include "mem/page_table.hh"
61#include "params/Process.hh"
62#include "sim/emul_driver.hh"
63#include "sim/fd_array.hh"
64#include "sim/fd_entry.hh"
65#include "sim/redirect_path.hh"
66#include "sim/se_workload.hh"
67#include "sim/syscall_desc.hh"
68#include "sim/system.hh"
69
70namespace gem5
71{
72
73namespace
74{
75
76typedef std::vector<Process::Loader *> LoaderList;
77
78LoaderList &
79process_loaders()
80{
81 static LoaderList loaders;
82 return loaders;
83}
84
85} // anonymous namespace
86
88{
89 process_loaders().emplace_back(this);
90}
91
92Process *
93Process::tryLoaders(const ProcessParams &params,
94 loader::ObjectFile *obj_file)
95{
96 for (auto &loader_it : process_loaders()) {
97 Process *p = loader_it->load(params, obj_file);
98 if (p)
99 return p;
100 }
101
102 return nullptr;
103}
104
105static std::string
106normalize(const std::string& directory)
107{
108 if (directory.back() != '/')
109 return directory + '/';
110 return directory;
111}
112
114 loader::ObjectFile *obj_file)
116 seWorkload(dynamic_cast<SEWorkload *>(system->workload)),
119 useForClone(false),
121 pTable(pTable),
122 objFile(obj_file),
123 argv(params.cmd), envp(params.env),
125 tgtCwd(normalize(params.cwd)),
132 fds(std::make_shared<FDArray>(
133 params.input, params.output, params.errout)),
134 childClearTID(0),
135 ADD_STAT(numSyscalls, statistics::units::Count::get(),
136 "Number of system calls")
137{
138 fatal_if(!seWorkload, "Couldn't find appropriate workload object.");
139 fatal_if(_pid >= System::maxPID, "_pid is too large: %d", _pid);
140
141 auto ret_pair = system->PIDs.emplace(_pid);
142 fatal_if(!ret_pair.second, "_pid %d is already used", _pid);
143
156 _tgid = params.pid;
157
158 exitGroup = new bool();
159 sigchld = new bool();
160
161 image = objFile->buildImage();
162
163 if (loader::debugSymbolTable.empty())
165}
166
167void
169 Process *np, RegVal flags)
170{
171#ifndef CLONE_VM
172#define CLONE_VM 0
173#endif
174#ifndef CLONE_FILES
175#define CLONE_FILES 0
176#endif
177#ifndef CLONE_THREAD
178#define CLONE_THREAD 0
179#endif
180#ifndef CLONE_VFORK
181#define CLONE_VFORK 0
182#endif
183 if (CLONE_VM & flags) {
189 delete np->pTable;
190 np->pTable = pTable;
191
192 np->memState = memState;
193 } else {
198 typedef std::vector<std::pair<Addr,Addr>> MapVec;
199 MapVec mappings;
200 pTable->getMappings(&mappings);
201
202 for (auto map : mappings) {
203 Addr paddr, vaddr = map.first;
204 bool alloc_page = !(np->pTable->translate(vaddr, paddr));
205 np->replicatePage(vaddr, paddr, otc, ntc, alloc_page);
206 }
207
208 *np->memState = *memState;
209 }
210
211 if (CLONE_FILES & flags) {
217 np->fds = fds;
218 } else {
226 std::shared_ptr<FDArray> nfds = np->fds;
227 for (int tgt_fd = 0; tgt_fd < fds->getSize(); tgt_fd++) {
228 std::shared_ptr<FDEntry> this_fde = (*fds)[tgt_fd];
229 if (!this_fde) {
230 nfds->setFDEntry(tgt_fd, nullptr);
231 continue;
232 }
233 nfds->setFDEntry(tgt_fd, this_fde->clone());
234
235 auto this_hbfd = std::dynamic_pointer_cast<HBFDEntry>(this_fde);
236 if (!this_hbfd)
237 continue;
238
239 int this_sim_fd = this_hbfd->getSimFD();
240 if (this_sim_fd <= 2)
241 continue;
242
243 int np_sim_fd = dup(this_sim_fd);
244 assert(np_sim_fd != -1);
245
246 auto nhbfd = std::dynamic_pointer_cast<HBFDEntry>((*nfds)[tgt_fd]);
247 nhbfd->setSimFD(np_sim_fd);
248 }
249 }
250
251 if (CLONE_THREAD & flags) {
252 np->_tgid = _tgid;
253 delete np->exitGroup;
254 np->exitGroup = exitGroup;
255 }
256
257 if (CLONE_VFORK & flags) {
258 np->vforkContexts.push_back(otc->contextId());
259 }
260
261 np->argv.insert(np->argv.end(), argv.begin(), argv.end());
262 np->envp.insert(np->envp.end(), envp.begin(), envp.end());
263}
264
265void
267{
269 for (it = contextIds.begin(); it != contextIds.end(); it++) {
270 if (*it == context_id) {
271 contextIds.erase(it);
272 return;
273 }
274 }
275 warn("Unable to find thread context to revoke");
276}
277
278void
280{
281 // Patch the ld_bias for dynamic executables.
282 updateBias();
283
284 if (objFile->getInterpreter())
285 interpImage = objFile->getInterpreter()->buildImage();
286}
287
288void
290{
291 if (contextIds.empty())
292 fatal("Process %s is not associated with any HW contexts!\n", name());
293
294 // first thread context for this process... initialize & enable
295 ThreadContext *tc = system->threads[contextIds[0]];
296
297 // mark this context as active so it will start ticking.
298 tc->activate();
299
300 pTable->initState();
301
304
305 // load object file into target memory
306 image.write(*initVirtMem);
307 interpImage.write(*initVirtMem);
308}
309
312{
313 fds->updateFileOffsets();
314 return DrainState::Drained;
315}
316
317void
318Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
319{
320 const auto page_size = pTable->pageSize();
321
322 const Addr page_addr = roundDown(vaddr, page_size);
323
324 // Check if the page has been mapped by other cores if not to clobber.
325 // When running multithreaded programs in SE-mode with DerivO3CPU model,
326 // there are cases where two or more cores have page faults on the same
327 // page in nearby ticks. When the cores try to handle the faults at the
328 // commit stage (also in nearby ticks/cycles), the first core will ask for
329 // a physical page frame to map with the virtual page. Other cores can
330 // return if the page has been mapped and `!clobber`.
331 if (!clobber) {
332 const EmulationPageTable::Entry *pte = pTable->lookup(page_addr);
333 if (pte) {
334 warn("Process::allocateMem: addr %#x already mapped\n", vaddr);
335 return;
336 }
337 }
338
339 const int npages = divCeil(size, page_size);
340 const Addr paddr = seWorkload->allocPhysPages(npages);
341 const Addr pages_size = npages * page_size;
342 pTable->map(page_addr, paddr, pages_size,
345}
346
347void
349{
350 const auto page_size = pTable->pageSize();
351 const Addr page_vbase = roundDown(vaddr, page_size);
352 const Addr page_vend = roundUp(vaddr + size, page_size);
353 const int npages = (page_vend - page_vbase) / page_size;
354
355 // Free any physical pages that were mapped to by this virtual
356 // address range.
357 for (int i = 0; i < npages; ++i) {
358 const Addr page_vaddr = page_vbase + page_size * i;
359 Addr page_paddr;
360 if (pTable->translate(page_vaddr, page_paddr)) {
361 if (zeroPages) {
362 // Zero out the physical page upon deallocation.
363 // Pages that have never been allocated before are already
364 // zero-filled. Zeroing out deallocated pages ensures that
365 // if they're ever reallocated, they will be zero-filled.
366 // Note that zeroing out pages before allocation would
367 // achieve the same result, but would be more expensive
368 // because it would unnecessarily zero out pages that
369 // were allocated for the first time.
370 SETranslatingPortProxy virt_mem(
372 const std::vector<uint8_t> zero_page(page_size, 0);
373 virt_mem.writeBlob(page_vaddr, zero_page.data(), page_size);
374 }
375
376 // Unmap the virtual page.
377 pTable->unmap(page_vaddr, page_size);
378
379 // Deallocate the physical page.
380 seWorkload->deallocPhysPage(page_paddr);
381 }
382 }
383}
384
385void
387 ThreadContext *new_tc, bool allocate_page)
388{
389 if (allocate_page)
390 new_paddr = seWorkload->allocPhysPages(1);
391
392 // Read from old physical page.
393 const size_t buf_size = pTable->pageSize();
394 auto buf_p = std::make_unique<uint8_t[]>(buf_size);
395 SETranslatingPortProxy(old_tc).readBlob(vaddr, buf_p.get(), buf_size);
396
397 // Create new mapping in process address space by clobbering existing
398 // mapping (if any existed) and then write to the new physical page.
399 bool clobber = true;
400 pTable->map(vaddr, new_paddr, buf_size, clobber);
401 SETranslatingPortProxy(new_tc).writeBlob(vaddr, buf_p.get(), buf_size);
402}
403
404bool
406{
407 return memState->fixupFault(vaddr);
408}
409
410void
412{
413 memState->serialize(cp);
414 pTable->serialize(cp);
415 fds->serialize(cp);
416
421
422 warn("Checkpoints for pipes, device drivers and sockets do not work.");
423}
424
425void
427{
428 memState->unserialize(cp);
429 pTable->unserialize(cp);
430 fds->unserialize(cp, this);
431
436 warn("Checkpoints for pipes, device drivers and sockets do not work.");
437 // The above returns a bool so that you could do something if you don't
438 // find the param in the checkpoint if you wanted to, like set a default
439 // but in this case we'll just stick with the instantiated value if not
440 // found.
441}
442
443bool
444Process::map(Addr vaddr, Addr paddr, int64_t size, bool cacheable)
445{
446 pTable->map(vaddr, paddr, size,
447 cacheable ? EmulationPageTable::MappingFlags(0) :
449 return true;
450}
451
453Process::findDriver(std::string filename)
454{
455 for (EmulatedDriver *d : drivers) {
456 if (d->match(filename))
457 return d;
458 }
459
460 return nullptr;
461}
462
463std::string
464Process::checkPathRedirect(const std::string &filename)
465{
466 // If the input parameter contains a relative path, convert it.
467 // The target version of the current working directory is fine since
468 // we immediately convert it using redirect paths into a host version.
469 auto abs_path = absolutePath(filename, false);
470
471 for (auto path : system->redirectPaths) {
472 // Search through the redirect paths to see if a starting substring of
473 // our path falls into any buckets which need to redirected.
474 if (startswith(abs_path, path->appPath())) {
475 std::string tail = abs_path.substr(path->appPath().size());
476
477 // If this path needs to be redirected, search through a list
478 // of targets to see if we can match a valid file (or directory).
479 for (auto host_path : path->hostPaths()) {
480 if (access((host_path + tail).c_str(), R_OK) == 0) {
481 // Return the valid match.
482 return host_path + tail;
483 }
484 }
485 // The path needs to be redirected, but the file or directory
486 // does not exist on the host filesystem. Return the first
487 // host path as a default.
488 return path->hostPaths()[0] + tail;
489 }
490 }
491
492 // The path does not need to be redirected.
493 return abs_path;
494}
495
496void
498{
499 auto *interp = objFile->getInterpreter();
500
501 if (!interp || !interp->relocatable())
502 return;
503
504 // Determine how large the interpreters footprint will be in the process
505 // address space.
506 Addr interp_mapsize = roundUp(interp->mapSize(), pTable->pageSize());
507
508 // We are allocating the memory area; set the bias to the lowest address
509 // in the allocated memory region.
510 Addr mmap_end = memState->getMmapEnd();
511 Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
512
513 // Adjust the process mmap area to give the interpreter room; the real
514 // execve system call would just invoke the kernel's internal mmap
515 // functions to make these adjustments.
516 mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
517 memState->setMmapEnd(mmap_end);
518
519 interp->updateBias(ld_bias);
520}
521
524{
525 return objFile->getInterpreter();
526}
527
528Addr
530{
531 auto *interp = getInterpreter();
532
533 return interp ? interp->bias() : objFile->bias();
534}
535
536Addr
538{
539 auto *interp = getInterpreter();
540
541 return interp ? interp->entryPoint() : objFile->entryPoint();
542}
543
544std::string
545Process::absolutePath(const std::string &filename, bool host_filesystem)
546{
547 if (filename.empty() || startswith(filename, "/"))
548 return filename;
549
550 // Construct the absolute path given the current working directory for
551 // either the host filesystem or target filesystem. The distinction only
552 // matters if filesystem redirection is utilized in the simulation.
553 auto path_base = std::string();
554 if (host_filesystem) {
555 path_base = hostCwd;
556 assert(!hostCwd.empty());
557 } else {
558 path_base = tgtCwd;
559 assert(!tgtCwd.empty());
560 }
561
562 // Add a trailing '/' if the current working directory did not have one.
563 path_base = normalize(path_base);
564
565 // Append the filename onto the current working path.
566 auto absolute_path = path_base + filename;
567
568 return absolute_path;
569}
570
571Process *
572ProcessParams::create() const
573{
574 // If not specified, set the executable parameter equal to the
575 // simulated system's zeroth command line parameter
576 const std::string &exec = (executable == "") ? cmd[0] : executable;
577
578 auto *obj_file = loader::createObjectFile(exec);
579 fatal_if(!obj_file, "Cannot load object file %s.", exec);
580
581 Process *process = Process::tryLoaders(*this, obj_file);
582 fatal_if(!process, "Unknown error creating process object.");
583
584 return process;
585}
586
587} // namespace gem5
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
bool translate(Addr vaddr, Addr &paddr)
Translate function.
virtual std::string name() const
Definition named.hh:60
void readBlob(Addr addr, void *p, uint64_t size) const
Higher level interfaces based on the above.
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
loader::MemoryImage image
Definition process.hh:236
virtual bool mmapGrowsDown() const
Does mmap region grow upward or downward from mmapEnd?
Definition process.hh:152
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition process.cc:318
void replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, ThreadContext *new_tc, bool alloc_page)
Definition process.cc:386
uint64_t egid()
Definition process.hh:85
SEWorkload * seWorkload
Definition process.hh:181
void updateBias()
Definition process.cc:497
std::string absolutePath(const std::string &path, bool host_fs)
Return an absolute path given a relative path paired with the current working directory of the proces...
Definition process.cc:545
uint64_t _euid
Definition process.hh:285
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition process.hh:199
virtual void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *new_p, RegVal flags)
Definition process.cc:168
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition process.cc:279
std::shared_ptr< MemState > memState
Definition process.hh:301
bool fixupFault(Addr vaddr)
Attempt to fix up a fault at vaddr by allocating a page on the stack.
Definition process.cc:405
void deallocateMem(Addr vaddr, int64_t size)
Unmap the given virtual address range and deallocate any physical pages that it mapped to.
Definition process.cc:348
uint64_t pid()
Definition process.hh:86
uint64_t _tgid
Definition process.hh:293
uint64_t uid()
Definition process.hh:82
std::vector< std::string > argv
Definition process.hh:238
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition process.cc:311
uint64_t pgid()
Definition process.hh:88
uint64_t _egid
Definition process.hh:287
std::shared_ptr< FDArray > fds
Definition process.hh:298
bool map(Addr vaddr, Addr paddr, int64_t size, bool cacheable=true)
Maps a contiguous range of virtual addresses in this process's address space to a contiguous range of...
Definition process.cc:444
uint64_t _pid
Definition process.hh:290
uint64_t _gid
Definition process.hh:286
bool useForClone
Definition process.hh:188
uint64_t _ppid
Definition process.hh:291
loader::ObjectFile * getInterpreter()
Definition process.cc:523
loader::MemoryImage interpImage
Definition process.hh:237
bool * sigchld
Definition process.hh:310
bool zeroPages
Whether to ensure that all newly allocated pages are zero-filled.
Definition process.hh:194
uint64_t ppid()
Definition process.hh:87
std::string executable
Definition process.hh:240
std::vector< ContextID > vforkContexts
Definition process.hh:313
std::string hostCwd
Definition process.hh:278
std::vector< ContextID > contextIds
Definition process.hh:176
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition process.cc:464
System * system
Definition process.hh:179
uint64_t _pgid
Definition process.hh:292
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition process.cc:289
bool * exitGroup
Definition process.hh:300
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition process.cc:411
std::vector< std::string > envp
Definition process.hh:239
std::string tgtCwd
The cwd members are used to track changes to the current working directory for the purpose of executi...
Definition process.hh:277
std::string release
Definition process.hh:281
uint64_t gid()
Definition process.hh:84
EmulatedDriver * findDriver(std::string filename)
Find an emulated device driver.
Definition process.cc:453
Addr getStartPC()
Definition process.cc:537
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition process.cc:426
Process(const ProcessParams &params, EmulationPageTable *pTable, loader::ObjectFile *obj_file)
Definition process.cc:113
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext.
Definition process.cc:266
uint64_t _uid
Definition process.hh:284
loader::ObjectFile * objFile
Definition process.hh:235
Addr getBias()
Definition process.cc:529
statistics::Scalar numSyscalls
Definition process.hh:316
static Process * tryLoaders(const ProcessParams &params, loader::ObjectFile *obj_file)
Definition process.cc:93
uint64_t euid()
Definition process.hh:83
std::vector< EmulatedDriver * > drivers
Definition process.hh:296
EmulationPageTable * pTable
Definition process.hh:196
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition process.hh:307
static std::stack< std::string > path
Definition serialize.hh:315
static const int maxPID
Definition system.hh:605
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void activate()=0
Set the status to Active.
virtual ContextID contextId() const =0
STL vector class.
Definition stl.hh:37
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
static constexpr T divCeil(const T &a, const U &b)
Definition intmath.hh:110
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
DrainState
Object drain/handover states.
Definition drain.hh:75
@ Drained
Buffers drained, ready for serialization/handover.
Definition drain.hh:78
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
const Params & params() const
SimObject(const Params &p)
Definition sim_object.cc:58
#define warn(...)
Definition logging.hh:288
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9 > d
Definition misc_types.hh:64
Bitfield< 0 > p
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition symtab.cc:55
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Units for Stats.
Definition units.hh:113
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition str.hh:230
uint64_t RegVal
Definition types.hh:173
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
static void output(const char *filename)
Definition debug.cc:60
static std::string normalize(const std::string &directory)
Definition process.cc:106
Overload hash function for BasicBlockRange type.
Definition binary32.hh:81
Declarations of a non-full system Page Table.
#define CLONE_THREAD
#define CLONE_FILES
#define CLONE_VFORK
#define CLONE_VM
Declaration of Statistics objects.

Generated on Mon May 26 2025 09:19:13 for gem5 by doxygen 1.13.2