gem5 v24.0.0.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),
120 pTable(pTable),
121 objFile(obj_file),
122 argv(params.cmd), envp(params.env),
124 tgtCwd(normalize(params.cwd)),
131 fds(std::make_shared<FDArray>(
132 params.input, params.output, params.errout)),
133 childClearTID(0),
134 ADD_STAT(numSyscalls, statistics::units::Count::get(),
135 "Number of system calls")
136{
137 fatal_if(!seWorkload, "Couldn't find appropriate workload object.");
138 fatal_if(_pid >= System::maxPID, "_pid is too large: %d", _pid);
139
140 auto ret_pair = system->PIDs.emplace(_pid);
141 fatal_if(!ret_pair.second, "_pid %d is already used", _pid);
142
155 _tgid = params.pid;
156
157 exitGroup = new bool();
158 sigchld = new bool();
159
161
162 if (loader::debugSymbolTable.empty())
164}
165
166void
168 Process *np, RegVal flags)
169{
170#ifndef CLONE_VM
171#define CLONE_VM 0
172#endif
173#ifndef CLONE_FILES
174#define CLONE_FILES 0
175#endif
176#ifndef CLONE_THREAD
177#define CLONE_THREAD 0
178#endif
179#ifndef CLONE_VFORK
180#define CLONE_VFORK 0
181#endif
182 if (CLONE_VM & flags) {
188 delete np->pTable;
189 np->pTable = pTable;
190
191 np->memState = memState;
192 } else {
197 typedef std::vector<std::pair<Addr,Addr>> MapVec;
198 MapVec mappings;
199 pTable->getMappings(&mappings);
200
201 for (auto map : mappings) {
202 Addr paddr, vaddr = map.first;
203 bool alloc_page = !(np->pTable->translate(vaddr, paddr));
204 np->replicatePage(vaddr, paddr, otc, ntc, alloc_page);
205 }
206
207 *np->memState = *memState;
208 }
209
210 if (CLONE_FILES & flags) {
216 np->fds = fds;
217 } else {
225 std::shared_ptr<FDArray> nfds = np->fds;
226 for (int tgt_fd = 0; tgt_fd < fds->getSize(); tgt_fd++) {
227 std::shared_ptr<FDEntry> this_fde = (*fds)[tgt_fd];
228 if (!this_fde) {
229 nfds->setFDEntry(tgt_fd, nullptr);
230 continue;
231 }
232 nfds->setFDEntry(tgt_fd, this_fde->clone());
233
234 auto this_hbfd = std::dynamic_pointer_cast<HBFDEntry>(this_fde);
235 if (!this_hbfd)
236 continue;
237
238 int this_sim_fd = this_hbfd->getSimFD();
239 if (this_sim_fd <= 2)
240 continue;
241
242 int np_sim_fd = dup(this_sim_fd);
243 assert(np_sim_fd != -1);
244
245 auto nhbfd = std::dynamic_pointer_cast<HBFDEntry>((*nfds)[tgt_fd]);
246 nhbfd->setSimFD(np_sim_fd);
247 }
248 }
249
250 if (CLONE_THREAD & flags) {
251 np->_tgid = _tgid;
252 delete np->exitGroup;
253 np->exitGroup = exitGroup;
254 }
255
256 if (CLONE_VFORK & flags) {
257 np->vforkContexts.push_back(otc->contextId());
258 }
259
260 np->argv.insert(np->argv.end(), argv.begin(), argv.end());
261 np->envp.insert(np->envp.end(), envp.begin(), envp.end());
262}
263
264void
266{
268 for (it = contextIds.begin(); it != contextIds.end(); it++) {
269 if (*it == context_id) {
270 contextIds.erase(it);
271 return;
272 }
273 }
274 warn("Unable to find thread context to revoke");
275}
276
277void
279{
280 // Patch the ld_bias for dynamic executables.
281 updateBias();
282
283 if (objFile->getInterpreter())
285}
286
287void
289{
290 if (contextIds.empty())
291 fatal("Process %s is not associated with any HW contexts!\n", name());
292
293 // first thread context for this process... initialize & enable
295
296 // mark this context as active so it will start ticking.
297 tc->activate();
298
299 pTable->initState();
300
303
304 // load object file into target memory
307}
308
311{
312 fds->updateFileOffsets();
313 return DrainState::Drained;
314}
315
316void
317Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
318{
319 const auto page_size = pTable->pageSize();
320
321 const Addr page_addr = roundDown(vaddr, page_size);
322
323 // Check if the page has been mapped by other cores if not to clobber.
324 // When running multithreaded programs in SE-mode with DerivO3CPU model,
325 // there are cases where two or more cores have page faults on the same
326 // page in nearby ticks. When the cores try to handle the faults at the
327 // commit stage (also in nearby ticks/cycles), the first core will ask for
328 // a physical page frame to map with the virtual page. Other cores can
329 // return if the page has been mapped and `!clobber`.
330 if (!clobber) {
331 const EmulationPageTable::Entry *pte = pTable->lookup(page_addr);
332 if (pte) {
333 warn("Process::allocateMem: addr %#x already mapped\n", vaddr);
334 return;
335 }
336 }
337
338 const int npages = divCeil(size, page_size);
339 const Addr paddr = seWorkload->allocPhysPages(npages);
340 const Addr pages_size = npages * page_size;
341 pTable->map(page_addr, paddr, pages_size,
344}
345
346void
348 ThreadContext *new_tc, bool allocate_page)
349{
350 if (allocate_page)
351 new_paddr = seWorkload->allocPhysPages(1);
352
353 // Read from old physical page.
354 uint8_t buf_p[pTable->pageSize()];
355 SETranslatingPortProxy(old_tc).readBlob(vaddr, buf_p, sizeof(buf_p));
356
357 // Create new mapping in process address space by clobbering existing
358 // mapping (if any existed) and then write to the new physical page.
359 bool clobber = true;
360 pTable->map(vaddr, new_paddr, sizeof(buf_p), clobber);
361 SETranslatingPortProxy(new_tc).writeBlob(vaddr, buf_p, sizeof(buf_p));
362}
363
364bool
366{
367 return memState->fixupFault(vaddr);
368}
369
370void
372{
373 memState->serialize(cp);
374 pTable->serialize(cp);
375 fds->serialize(cp);
376
382 warn("Checkpoints for pipes, device drivers and sockets do not work.");
383}
384
385void
387{
388 memState->unserialize(cp);
389 pTable->unserialize(cp);
390 fds->unserialize(cp, this);
391
396 warn("Checkpoints for pipes, device drivers and sockets do not work.");
397 // The above returns a bool so that you could do something if you don't
398 // find the param in the checkpoint if you wanted to, like set a default
399 // but in this case we'll just stick with the instantiated value if not
400 // found.
401}
402
403bool
404Process::map(Addr vaddr, Addr paddr, int64_t size, bool cacheable)
405{
406 pTable->map(vaddr, paddr, size,
407 cacheable ? EmulationPageTable::MappingFlags(0) :
409 return true;
410}
411
413Process::findDriver(std::string filename)
414{
415 for (EmulatedDriver *d : drivers) {
416 if (d->match(filename))
417 return d;
418 }
419
420 return nullptr;
421}
422
423std::string
424Process::checkPathRedirect(const std::string &filename)
425{
426 // If the input parameter contains a relative path, convert it.
427 // The target version of the current working directory is fine since
428 // we immediately convert it using redirect paths into a host version.
429 auto abs_path = absolutePath(filename, false);
430
431 for (auto path : system->redirectPaths) {
432 // Search through the redirect paths to see if a starting substring of
433 // our path falls into any buckets which need to redirected.
434 if (startswith(abs_path, path->appPath())) {
435 std::string tail = abs_path.substr(path->appPath().size());
436
437 // If this path needs to be redirected, search through a list
438 // of targets to see if we can match a valid file (or directory).
439 for (auto host_path : path->hostPaths()) {
440 if (access((host_path + tail).c_str(), R_OK) == 0) {
441 // Return the valid match.
442 return host_path + tail;
443 }
444 }
445 // The path needs to be redirected, but the file or directory
446 // does not exist on the host filesystem. Return the first
447 // host path as a default.
448 return path->hostPaths()[0] + tail;
449 }
450 }
451
452 // The path does not need to be redirected.
453 return abs_path;
454}
455
456void
458{
459 auto *interp = objFile->getInterpreter();
460
461 if (!interp || !interp->relocatable())
462 return;
463
464 // Determine how large the interpreters footprint will be in the process
465 // address space.
466 Addr interp_mapsize = roundUp(interp->mapSize(), pTable->pageSize());
467
468 // We are allocating the memory area; set the bias to the lowest address
469 // in the allocated memory region.
470 Addr mmap_end = memState->getMmapEnd();
471 Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
472
473 // Adjust the process mmap area to give the interpreter room; the real
474 // execve system call would just invoke the kernel's internal mmap
475 // functions to make these adjustments.
476 mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
477 memState->setMmapEnd(mmap_end);
478
479 interp->updateBias(ld_bias);
480}
481
487
488Addr
490{
491 auto *interp = getInterpreter();
492
493 return interp ? interp->bias() : objFile->bias();
494}
495
496Addr
498{
499 auto *interp = getInterpreter();
500
501 return interp ? interp->entryPoint() : objFile->entryPoint();
502}
503
504std::string
505Process::absolutePath(const std::string &filename, bool host_filesystem)
506{
507 if (filename.empty() || startswith(filename, "/"))
508 return filename;
509
510 // Construct the absolute path given the current working directory for
511 // either the host filesystem or target filesystem. The distinction only
512 // matters if filesystem redirection is utilized in the simulation.
513 auto path_base = std::string();
514 if (host_filesystem) {
515 path_base = hostCwd;
516 assert(!hostCwd.empty());
517 } else {
518 path_base = tgtCwd;
519 assert(!tgtCwd.empty());
520 }
521
522 // Add a trailing '/' if the current working directory did not have one.
523 path_base = normalize(path_base);
524
525 // Append the filename onto the current working path.
526 auto absolute_path = path_base + filename;
527
528 return absolute_path;
529}
530
531Process *
532ProcessParams::create() const
533{
534 // If not specified, set the executable parameter equal to the
535 // simulated system's zeroth command line parameter
536 const std::string &exec = (executable == "") ? cmd[0] : executable;
537
538 auto *obj_file = loader::createObjectFile(exec);
539 fatal_if(!obj_file, "Cannot load object file %s.", exec);
540
541 Process *process = Process::tryLoaders(*this, obj_file);
542 fatal_if(!process, "Unknown error creating process object.");
543
544 return process;
545}
546
547} // namespace gem5
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
virtual void map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags=0)
Maps a virtual memory region to a physical memory region.
Definition page_table.cc:48
const Entry * lookup(Addr vaddr)
Lookup function.
void serialize(CheckpointOut &cp) const override
Serialize an object.
bool translate(Addr vaddr, Addr &paddr)
Translate function.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
virtual void initState()
void getMappings(std::vector< std::pair< Addr, Addr > > *addr_mappings)
Definition page_table.cc:97
virtual std::string name() const
Definition named.hh:47
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:224
virtual bool mmapGrowsDown() const
Does mmap region grow upward or downward from mmapEnd? Most platforms grow downward,...
Definition process.hh:146
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition process.cc:317
void replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, ThreadContext *new_tc, bool alloc_page)
Definition process.cc:347
uint64_t egid()
Definition process.hh:85
SEWorkload * seWorkload
Definition process.hh:175
void updateBias()
Definition process.cc:457
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:505
uint64_t _euid
Definition process.hh:273
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition process.hh:187
virtual void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *new_p, RegVal flags)
Definition process.cc:167
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition process.cc:278
std::shared_ptr< MemState > memState
Definition process.hh:289
bool fixupFault(Addr vaddr)
Attempt to fix up a fault at vaddr by allocating a page on the stack.
Definition process.cc:365
uint64_t pid()
Definition process.hh:86
uint64_t _tgid
Definition process.hh:281
uint64_t uid()
Definition process.hh:82
std::vector< std::string > argv
Definition process.hh:226
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition process.cc:310
uint64_t pgid()
Definition process.hh:88
uint64_t _egid
Definition process.hh:275
std::shared_ptr< FDArray > fds
Definition process.hh:286
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:404
uint64_t _pid
Definition process.hh:278
uint64_t _gid
Definition process.hh:274
bool useForClone
Definition process.hh:182
uint64_t _ppid
Definition process.hh:279
loader::ObjectFile * getInterpreter()
Definition process.cc:483
loader::MemoryImage interpImage
Definition process.hh:225
bool * sigchld
Definition process.hh:298
uint64_t ppid()
Definition process.hh:87
std::string executable
Definition process.hh:228
std::vector< ContextID > vforkContexts
Definition process.hh:301
std::string hostCwd
Definition process.hh:266
std::vector< ContextID > contextIds
Definition process.hh:170
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition process.cc:424
System * system
Definition process.hh:173
uint64_t _pgid
Definition process.hh:280
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition process.cc:288
bool * exitGroup
Definition process.hh:288
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition process.cc:371
std::vector< std::string > envp
Definition process.hh:227
std::string tgtCwd
The cwd members are used to track changes to the current working directory for the purpose of executi...
Definition process.hh:265
std::string release
Definition process.hh:269
uint64_t gid()
Definition process.hh:84
EmulatedDriver * findDriver(std::string filename)
Find an emulated device driver.
Definition process.cc:413
Addr getStartPC()
Definition process.cc:497
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition process.cc:386
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:265
uint64_t _uid
Definition process.hh:272
loader::ObjectFile * objFile
Definition process.hh:223
Addr getBias()
Definition process.cc:489
statistics::Scalar numSyscalls
Definition process.hh:304
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:284
EmulationPageTable * pTable
Definition process.hh:184
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition process.hh:295
Addr allocPhysPages(int npages, int pool_id=0)
static std::stack< std::string > path
Definition serialize.hh:315
Abstract superclass for simulation objects.
std::set< int > PIDs
Process set to track which PIDs have already been allocated.
Definition system.hh:603
static const int maxPID
Definition system.hh:600
std::vector< RedirectPath * > redirectPaths
Definition system.hh:612
Threads threads
Definition system.hh:310
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
virtual MemoryImage buildImage() const =0
bool write(const PortProxy &proxy) const
virtual ObjectFile * getInterpreter() const
virtual Addr bias() const
const SymbolTable & symtab() const
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.
#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
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
const Params & params() const
uint8_t flags
Definition helpers.cc:87
#define warn(...)
Definition logging.hh:256
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)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria 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 Tue Jun 18 2024 16:24:06 for gem5 by doxygen 1.11.0