gem5  v22.1.0.0
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 
70 namespace gem5
71 {
72 
73 namespace
74 {
75 
76 typedef std::vector<Process::Loader *> LoaderList;
77 
78 LoaderList &
79 process_loaders()
80 {
81  static LoaderList loaders;
82  return loaders;
83 }
84 
85 } // anonymous namespace
86 
88 {
89  process_loaders().emplace_back(this);
90 }
91 
92 Process *
93 Process::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 
105 static std::string
106 normalize(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 
160  image = objFile->buildImage();
161 
162  if (loader::debugSymbolTable.empty())
164 }
165 
166 void
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 
264 void
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 
277 void
279 {
280  // Patch the ld_bias for dynamic executables.
281  updateBias();
282 
283  if (objFile->getInterpreter())
285 }
286 
287 void
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 
316 void
317 Process::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,
342  clobber ? EmulationPageTable::Clobber :
344 }
345 
346 void
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 
364 bool
366 {
367  return memState->fixupFault(vaddr);
368 }
369 
370 void
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 
385 void
387 {
388  memState->unserialize(cp);
389  pTable->unserialize(cp);
390  fds->unserialize(cp);
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 
403 bool
404 Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
405 {
406  pTable->map(vaddr, paddr, size,
407  cacheable ? EmulationPageTable::MappingFlags(0) :
409  return true;
410 }
411 
413 Process::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 
423 std::string
424 Process::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 
456 void
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 
484 {
485  return objFile->getInterpreter();
486 }
487 
488 Addr
490 {
491  auto *interp = getInterpreter();
492 
493  return interp ? interp->bias() : objFile->bias();
494 }
495 
496 Addr
498 {
499  auto *interp = getInterpreter();
500 
501  return interp ? interp->entryPoint() : objFile->entryPoint();
502 }
503 
504 std::string
505 Process::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 
531 Process *
532 ProcessParams::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.
Definition: emul_driver.hh:56
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.
Definition: page_table.cc:133
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: page_table.cc:186
bool translate(Addr vaddr, Addr &paddr)
Translate function.
Definition: page_table.cc:143
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: page_table.cc:203
virtual void initState()
Definition: page_table.hh:106
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 writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:192
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:182
loader::MemoryImage image
Definition: process.hh:225
virtual bool mmapGrowsDown() const
Does mmap region grow upward or downward from mmapEnd? Most platforms grow downward,...
Definition: process.hh:147
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:86
SEWorkload * seWorkload
Definition: process.hh:176
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:274
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:188
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:290
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:87
uint64_t _tgid
Definition: process.hh:282
uint64_t uid()
Definition: process.hh:83
std::vector< std::string > argv
Definition: process.hh:227
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:89
uint64_t _egid
Definition: process.hh:276
std::shared_ptr< FDArray > fds
Definition: process.hh:287
bool kvmInSE
Definition: process.hh:181
uint64_t _pid
Definition: process.hh:279
uint64_t _gid
Definition: process.hh:275
bool useForClone
Definition: process.hh:183
uint64_t _ppid
Definition: process.hh:280
loader::ObjectFile * getInterpreter()
Definition: process.cc:483
loader::MemoryImage interpImage
Definition: process.hh:226
bool * sigchld
Definition: process.hh:299
uint64_t ppid()
Definition: process.hh:88
std::string executable
Definition: process.hh:229
std::vector< ContextID > vforkContexts
Definition: process.hh:302
std::string hostCwd
Definition: process.hh:267
std::vector< ContextID > contextIds
Definition: process.hh:171
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:174
bool useArchPT
Definition: process.hh:179
uint64_t _pgid
Definition: process.hh:281
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:288
bool * exitGroup
Definition: process.hh:289
bool map(Addr vaddr, Addr paddr, int 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
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: process.cc:371
std::vector< std::string > envp
Definition: process.hh:228
std::string tgtCwd
The cwd members are used to track changes to the current working directory for the purpose of executi...
Definition: process.hh:266
std::string release
Definition: process.hh:270
uint64_t gid()
Definition: process.hh:85
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:273
loader::ObjectFile * objFile
Definition: process.hh:224
Addr getBias()
Definition: process.cc:489
statistics::Scalar numSyscalls
Definition: process.hh:305
static Process * tryLoaders(const ProcessParams &params, loader::ObjectFile *obj_file)
Definition: process.cc:93
uint64_t euid()
Definition: process.hh:84
std::vector< EmulatedDriver * > drivers
Definition: process.hh:285
EmulationPageTable * pTable
Definition: process.hh:185
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:296
Addr allocPhysPages(int npages, int pool_id=0)
Definition: se_workload.cc:75
static std::stack< std::string > path
Definition: serialize.hh:315
Abstract superclass for simulation objects.
Definition: sim_object.hh:148
std::set< int > PIDs
Process set to track which PIDs have already been allocated.
Definition: system.hh:606
static const int maxPID
Definition: system.hh:603
std::vector< RedirectPath * > redirectPaths
Definition: system.hh:615
Threads threads
Definition: system.hh:313
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
Definition: memory_image.cc:54
virtual ObjectFile * getInterpreter() const
Definition: object_file.hh:111
virtual Addr bias() const
Definition: object_file.hh:123
const SymbolTable & symtab() const
Definition: object_file.hh:131
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:226
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
const Params & params() const
Definition: sim_object.hh:176
uint8_t flags
Definition: helpers.cc:66
#define warn(...)
Definition: logging.hh:246
Bitfield< 9 > d
Definition: misc_types.hh:64
Bitfield< 54 > p
Definition: pagetable.hh:70
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:44
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:135
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:229
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
uint64_t RegVal
Definition: types.hh:173
Overload hash function for BasicBlockRange type.
Definition: misc.hh:2826
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 Wed Dec 21 2022 10:22:26 for gem5 by doxygen 1.9.1