gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 "config/the_isa.hh"
59 #include "cpu/thread_context.hh"
60 #include "mem/page_table.hh"
62 #include "params/Process.hh"
63 #include "sim/emul_driver.hh"
64 #include "sim/fd_array.hh"
65 #include "sim/fd_entry.hh"
66 #include "sim/redirect_path.hh"
67 #include "sim/syscall_desc.hh"
68 #include "sim/system.hh"
69 
70 using namespace std;
71 using namespace TheISA;
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(ProcessParams *params, ::Loader::ObjectFile *obj_file)
94 {
95  for (auto &loader: process_loaders()) {
96  Process *p = loader->load(params, obj_file);
97  if (p)
98  return p;
99  }
100 
101  return nullptr;
102 }
103 
104 static std::string
105 normalize(std::string& directory)
106 {
107  if (directory.back() != '/')
108  directory += '/';
109  return directory;
110 }
111 
112 Process::Process(ProcessParams *params, EmulationPageTable *pTable,
113  ::Loader::ObjectFile *obj_file)
114  : SimObject(params), system(params->system),
115  useArchPT(params->useArchPT),
116  kvmInSE(params->kvmInSE),
117  useForClone(false),
118  pTable(pTable),
119  objFile(obj_file),
120  argv(params->cmd), envp(params->env),
121  executable(params->executable),
122  tgtCwd(normalize(params->cwd)),
123  hostCwd(checkPathRedirect(tgtCwd)),
124  release(params->release),
125  _uid(params->uid), _euid(params->euid),
126  _gid(params->gid), _egid(params->egid),
127  _pid(params->pid), _ppid(params->ppid),
128  _pgid(params->pgid), drivers(params->drivers),
129  fds(make_shared<FDArray>(params->input, params->output, params->errout)),
130  childClearTID(0)
131 {
132  if (_pid >= System::maxPID)
133  fatal("_pid is too large: %d", _pid);
134 
135  auto ret_pair = system->PIDs.emplace(_pid);
136  if (!ret_pair.second)
137  fatal("_pid %d is already used", _pid);
138 
151  _tgid = params->pid;
152 
153  exitGroup = new bool();
154  sigchld = new bool();
155 
156  image = objFile->buildImage();
157 
158  if (::Loader::debugSymbolTable.empty()) {
163  }
164  }
165 }
166 
167 void
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  if (CLONE_VM & flags) {
186  delete np->pTable;
187  np->pTable = pTable;
188 
189  np->memState = memState;
190  } else {
195  typedef std::vector<pair<Addr,Addr>> MapVec;
196  MapVec mappings;
197  pTable->getMappings(&mappings);
198 
199  for (auto map : mappings) {
200  Addr paddr, vaddr = map.first;
201  bool alloc_page = !(np->pTable->translate(vaddr, paddr));
202  np->replicatePage(vaddr, paddr, otc, ntc, alloc_page);
203  }
204 
205  *np->memState = *memState;
206  }
207 
208  if (CLONE_FILES & flags) {
214  np->fds = fds;
215  } else {
223  std::shared_ptr<FDArray> nfds = np->fds;
224  for (int tgt_fd = 0; tgt_fd < fds->getSize(); tgt_fd++) {
225  std::shared_ptr<FDEntry> this_fde = (*fds)[tgt_fd];
226  if (!this_fde) {
227  nfds->setFDEntry(tgt_fd, nullptr);
228  continue;
229  }
230  nfds->setFDEntry(tgt_fd, this_fde->clone());
231 
232  auto this_hbfd = std::dynamic_pointer_cast<HBFDEntry>(this_fde);
233  if (!this_hbfd)
234  continue;
235 
236  int this_sim_fd = this_hbfd->getSimFD();
237  if (this_sim_fd <= 2)
238  continue;
239 
240  int np_sim_fd = dup(this_sim_fd);
241  assert(np_sim_fd != -1);
242 
243  auto nhbfd = std::dynamic_pointer_cast<HBFDEntry>((*nfds)[tgt_fd]);
244  nhbfd->setSimFD(np_sim_fd);
245  }
246  }
247 
248  if (CLONE_THREAD & flags) {
249  np->_tgid = _tgid;
250  delete np->exitGroup;
251  np->exitGroup = exitGroup;
252  }
253 
254  np->argv.insert(np->argv.end(), argv.begin(), argv.end());
255  np->envp.insert(np->envp.end(), envp.begin(), envp.end());
256 }
257 
258 void
260 {
262 
263  using namespace Stats;
264 
266  .name(name() + ".numSyscalls")
267  .desc("Number of system calls")
268  ;
269 }
270 
271 void
273 {
275  for (it = contextIds.begin(); it != contextIds.end(); it++) {
276  if (*it == context_id) {
277  contextIds.erase(it);
278  return;
279  }
280  }
281  warn("Unable to find thread context to revoke");
282 }
283 
284 void
286 {
287  // Patch the ld_bias for dynamic executables.
288  updateBias();
289 
290  if (objFile->getInterpreter())
292 }
293 
294 void
296 {
297  if (contextIds.empty())
298  fatal("Process %s is not associated with any HW contexts!\n", name());
299 
300  // first thread context for this process... initialize & enable
302 
303  // mark this context as active so it will start ticking.
304  tc->activate();
305 
306  pTable->initState();
307 
310 
311  // load object file into target memory
314 }
315 
318 {
319  fds->updateFileOffsets();
320  return DrainState::Drained;
321 }
322 
323 void
324 Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
325 {
326  int npages = divCeil(size, (int64_t)PageBytes);
327  Addr paddr = system->allocPhysPages(npages);
328  pTable->map(vaddr, paddr, size,
329  clobber ? EmulationPageTable::Clobber :
331 }
332 
333 void
335  ThreadContext *new_tc, bool allocate_page)
336 {
337  if (allocate_page)
338  new_paddr = system->allocPhysPages(1);
339 
340  // Read from old physical page.
341  uint8_t *buf_p = new uint8_t[PageBytes];
342  old_tc->getVirtProxy().readBlob(vaddr, buf_p, PageBytes);
343 
344  // Create new mapping in process address space by clobbering existing
345  // mapping (if any existed) and then write to the new physical page.
346  bool clobber = true;
347  pTable->map(vaddr, new_paddr, PageBytes, clobber);
348  new_tc->getVirtProxy().writeBlob(vaddr, buf_p, PageBytes);
349  delete[] buf_p;
350 }
351 
352 bool
354 {
355  return memState->fixupFault(vaddr);
356 }
357 
358 void
360 {
361  memState->serialize(cp);
362  pTable->serialize(cp);
368  warn("Checkpoints for file descriptors currently do not work.");
369 }
370 
371 void
373 {
374  memState->unserialize(cp);
375  pTable->unserialize(cp);
380  warn("Checkpoints for file descriptors currently do not work.");
381  // The above returns a bool so that you could do something if you don't
382  // find the param in the checkpoint if you wanted to, like set a default
383  // but in this case we'll just stick with the instantiated value if not
384  // found.
385 }
386 
387 bool
388 Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
389 {
390  pTable->map(vaddr, paddr, size,
391  cacheable ? EmulationPageTable::MappingFlags(0) :
393  return true;
394 }
395 
397 Process::findDriver(std::string filename)
398 {
399  for (EmulatedDriver *d : drivers) {
400  if (d->match(filename))
401  return d;
402  }
403 
404  return nullptr;
405 }
406 
407 std::string
408 Process::checkPathRedirect(const std::string &filename)
409 {
410  // If the input parameter contains a relative path, convert it.
411  // The target version of the current working directory is fine since
412  // we immediately convert it using redirect paths into a host version.
413  auto abs_path = absolutePath(filename, false);
414 
415  for (auto path : system->redirectPaths) {
416  // Search through the redirect paths to see if a starting substring of
417  // our path falls into any buckets which need to redirected.
418  if (startswith(abs_path, path->appPath())) {
419  std::string tail = abs_path.substr(path->appPath().size());
420 
421  // If this path needs to be redirected, search through a list
422  // of targets to see if we can match a valid file (or directory).
423  for (auto host_path : path->hostPaths()) {
424  if (access((host_path + tail).c_str(), R_OK) == 0) {
425  // Return the valid match.
426  return host_path + tail;
427  }
428  }
429  // The path needs to be redirected, but the file or directory
430  // does not exist on the host filesystem. Return the first
431  // host path as a default.
432  return path->hostPaths()[0] + tail;
433  }
434  }
435 
436  // The path does not need to be redirected.
437  return abs_path;
438 }
439 
440 void
442 {
443  auto *interp = objFile->getInterpreter();
444 
445  if (!interp || !interp->relocatable())
446  return;
447 
448  // Determine how large the interpreters footprint will be in the process
449  // address space.
450  Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes);
451 
452  // We are allocating the memory area; set the bias to the lowest address
453  // in the allocated memory region.
454  Addr mmap_end = memState->getMmapEnd();
455  Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
456 
457  // Adjust the process mmap area to give the interpreter room; the real
458  // execve system call would just invoke the kernel's internal mmap
459  // functions to make these adjustments.
460  mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
461  memState->setMmapEnd(mmap_end);
462 
463  interp->updateBias(ld_bias);
464 }
465 
468 {
469  return objFile->getInterpreter();
470 }
471 
472 Addr
474 {
475  auto *interp = getInterpreter();
476 
477  return interp ? interp->bias() : objFile->bias();
478 }
479 
480 Addr
482 {
483  auto *interp = getInterpreter();
484 
485  return interp ? interp->entryPoint() : objFile->entryPoint();
486 }
487 
488 std::string
489 Process::absolutePath(const std::string &filename, bool host_filesystem)
490 {
491  if (filename.empty() || startswith(filename, "/"))
492  return filename;
493 
494  // Construct the absolute path given the current working directory for
495  // either the host filesystem or target filesystem. The distinction only
496  // matters if filesystem redirection is utilized in the simulation.
497  auto path_base = std::string();
498  if (host_filesystem) {
499  path_base = hostCwd;
500  assert(!hostCwd.empty());
501  } else {
502  path_base = tgtCwd;
503  assert(!tgtCwd.empty());
504  }
505 
506  // Add a trailing '/' if the current working directory did not have one.
507  normalize(path_base);
508 
509  // Append the filename onto the current working path.
510  auto absolute_path = path_base + filename;
511 
512  return absolute_path;
513 }
514 
515 Process *
516 ProcessParams::create()
517 {
518  // If not specified, set the executable parameter equal to the
519  // simulated system's zeroth command line parameter
520  if (executable == "") {
521  executable = cmd[0];
522  }
523 
524  auto *obj_file = Loader::createObjectFile(executable);
525  fatal_if(!obj_file, "Cannot load object file %s.", executable);
526 
527  Process *process = Process::tryLoaders(this, obj_file);
528  fatal_if(!process, "Unknown error creating process object.");
529 
530  return process;
531 }
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=MaxAddr)
Definition: object_file.hh:87
Process(ProcessParams *params, EmulationPageTable *pTable, ::Loader::ObjectFile *obj_file)
Definition: process.cc:112
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:45
ObjectFile * createObjectFile(const std::string &fname, bool raw)
Definition: object_file.cc:61
void revokeThreadContext(int context_id)
After delegating a thread context to a child process no longer should relate to the ThreadContext...
Definition: process.cc:272
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
static void output(const char *filename)
Definition: debug.cc:60
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: page_table.cc:185
std::vector< RedirectPath * > redirectPaths
Definition: system.hh:509
static std::stack< std::string > path
Definition: serialize.hh:310
std::unique_ptr< SETranslatingPortProxy > initVirtMem
Definition: process.hh:177
std::vector< ContextID > contextIds
Definition: process.hh:160
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition: process.cc:324
bool * sigchld
Definition: process.hh:288
#define CLONE_VM
virtual MemoryImage buildImage() const =0
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: process.cc:372
void regStats() override
Callback to set stat parameters.
Definition: process.cc:259
Stats::Scalar numSyscalls
Definition: process.hh:165
virtual PortProxy & getVirtProxy()=0
uint64_t _tgid
Definition: process.hh:271
Addr allocPhysPages(int npages)
Allocate npages contiguous unused physical pages.
Definition: system.cc:323
uint64_t RegVal
Definition: types.hh:166
void setSimFD(int sim_fd)
Definition: fd_entry.hh:95
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:47
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:295
std::string executable
Definition: process.hh:218
static Process * tryLoaders(ProcessParams *params, ::Loader::ObjectFile *obj_file)
Definition: process.cc:93
Definition: cprintf.cc:40
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:114
std::shared_ptr< MemState > memState
Definition: process.hh:279
ThreadContext is the external interface to all thread state for anything outside of the CPU...
Declaration of Statistics objects.
DrainState
Object drain/handover states.
Definition: drain.hh:71
STL vector class.
Definition: stl.hh:37
ThreadContext * getThreadContext(ContextID tid) const
Definition: system.hh:186
DrainState drain() override
Notify an object that it needs to drain its state.
Definition: process.cc:317
void replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, ThreadContext *new_tc, bool alloc_page)
Definition: process.cc:334
bool write(const PortProxy &proxy) const
Definition: memory_image.cc:50
int getSimFD() const
Definition: fd_entry.hh:92
Draining buffers pending serialization/handover.
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:489
static const int maxPID
Definition: system.hh:497
bool translate(Addr vaddr, Addr &paddr)
Translate function.
Definition: page_table.cc:140
bool map(Addr vaddr, Addr paddr, int size, bool cacheable=true)
Maps a contiguous range of virtual addresses in this process&#39;s address space to a contiguous range of...
Definition: process.cc:388
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:187
uint64_t _pid
Definition: process.hh:268
std::set< int > PIDs
Process set to track which PIDs have already been allocated.
Definition: system.hh:500
static std::string normalize(std::string &directory)
Definition: process.cc:105
Bitfield< 9 > d
Addr getStartPC()
Definition: process.cc:481
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:74
System * system
Definition: process.hh:163
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:199
std::string tgtCwd
The cwd members are used to track changes to the current working directory for the purpose of executi...
Definition: process.hh:255
std::vector< std::string > envp
Definition: process.hh:217
virtual void activate()=0
Set the status to Active.
virtual void initState()
Definition: page_table.hh:100
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
EmulatedDriver * findDriver(std::string filename)
Find an emulated device driver.
Definition: process.cc:397
bool startswith(const char *s, const char *prefix)
Return true if &#39;s&#39; starts with the prefix string &#39;prefix&#39;.
Definition: str.hh:224
Bitfield< 15 > system
Definition: misc.hh:997
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:177
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:276
virtual const std::string name() const
Definition: sim_object.hh:128
::Loader::ObjectFile * getInterpreter()
Definition: process.cc:467
EmulationPageTable * pTable
Definition: process.hh:174
Declarations of a non-full system Page Table.
bool fixupFault(Addr vaddr)
Attempt to fix up a fault at vaddr by allocating a page on the stack.
Definition: process.cc:353
virtual ObjectFile * getInterpreter() const
Definition: object_file.hh:105
::Loader::MemoryImage image
Definition: process.hh:214
std::ostream CheckpointOut
Definition: serialize.hh:63
void updateBias()
Definition: process.cc:441
virtual void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *new_p, RegVal flags)
Definition: process.cc:168
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:408
::Loader::MemoryImage interpImage
Definition: process.hh:215
Addr entryPoint() const
Definition: object_file.hh:128
T divCeil(const T &a, const U &b)
Definition: intmath.hh:99
#define CLONE_FILES
virtual Addr bias() const
Definition: object_file.hh:117
const Addr PageBytes
Definition: isa_traits.hh:56
EmulatedDriver is an abstract base class for fake SE-mode device drivers.
Definition: emul_driver.hh:52
virtual bool mmapGrowsDown() const
Does mmap region grow upward or downward from mmapEnd? Most platforms grow downward, but a few (such as Alpha) grow upward instead, so they can override this method to return false.
Definition: process.hh:136
void getMappings(std::vector< std::pair< Addr, Addr >> *addr_mappings)
Definition: page_table.cc:94
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: page_table.cc:169
#define CLONE_THREAD
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:309
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: process.cc:359
#define warn(...)
Definition: logging.hh:208
std::string hostCwd
Definition: process.hh:256
std::vector< std::string > argv
Definition: process.hh:216
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:64
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: process.cc:285
Bitfield< 0 > p
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=MaxAddr)
Definition: object_file.hh:93
virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base=0, Addr offset=0, Addr mask=MaxAddr)
Definition: object_file.hh:99
Abstract superclass for simulation objects.
Definition: sim_object.hh:92
::Loader::ObjectFile * objFile
Definition: process.hh:213
Addr getBias()
Definition: process.cc:473
bool * exitGroup
Definition: process.hh:278
std::shared_ptr< FDArray > fds
Definition: process.hh:276
std::vector< EmulatedDriver * > drivers
Definition: process.hh:274

Generated on Mon Jun 8 2020 15:34:39 for gem5 by doxygen 1.8.13