gem5  v20.0.0.0
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) {
159  ::Loader::debugSymbolTable = new ::Loader::SymbolTable();
164  ::Loader::debugSymbolTable = nullptr;
165  }
166  }
167 }
168 
169 void
171  Process *np, RegVal flags)
172 {
173 #ifndef CLONE_VM
174 #define CLONE_VM 0
175 #endif
176 #ifndef CLONE_FILES
177 #define CLONE_FILES 0
178 #endif
179 #ifndef CLONE_THREAD
180 #define CLONE_THREAD 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<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  np->argv.insert(np->argv.end(), argv.begin(), argv.end());
257  np->envp.insert(np->envp.end(), envp.begin(), envp.end());
258 }
259 
260 void
262 {
264 
265  using namespace Stats;
266 
268  .name(name() + ".numSyscalls")
269  .desc("Number of system calls")
270  ;
271 }
272 
273 void
275 {
277  for (it = contextIds.begin(); it != contextIds.end(); it++) {
278  if (*it == context_id) {
279  contextIds.erase(it);
280  return;
281  }
282  }
283  warn("Unable to find thread context to revoke");
284 }
285 
286 void
288 {
289  // Patch the ld_bias for dynamic executables.
290  updateBias();
291 
292  if (objFile->getInterpreter())
294 }
295 
296 void
298 {
299  if (contextIds.empty())
300  fatal("Process %s is not associated with any HW contexts!\n", name());
301 
302  // first thread context for this process... initialize & enable
304 
305  // mark this context as active so it will start ticking.
306  tc->activate();
307 
308  pTable->initState();
309 
312 
313  // load object file into target memory
316 }
317 
320 {
321  fds->updateFileOffsets();
322  return DrainState::Drained;
323 }
324 
325 void
326 Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
327 {
328  int npages = divCeil(size, (int64_t)PageBytes);
329  Addr paddr = system->allocPhysPages(npages);
330  pTable->map(vaddr, paddr, size,
331  clobber ? EmulationPageTable::Clobber :
333 }
334 
335 void
337  ThreadContext *new_tc, bool allocate_page)
338 {
339  if (allocate_page)
340  new_paddr = system->allocPhysPages(1);
341 
342  // Read from old physical page.
343  uint8_t *buf_p = new uint8_t[PageBytes];
344  old_tc->getVirtProxy().readBlob(vaddr, buf_p, PageBytes);
345 
346  // Create new mapping in process address space by clobbering existing
347  // mapping (if any existed) and then write to the new physical page.
348  bool clobber = true;
349  pTable->map(vaddr, new_paddr, PageBytes, clobber);
350  new_tc->getVirtProxy().writeBlob(vaddr, buf_p, PageBytes);
351  delete[] buf_p;
352 }
353 
354 bool
356 {
357  return memState->fixupFault(vaddr);
358 }
359 
360 void
362 {
363  memState->serialize(cp);
364  pTable->serialize(cp);
370  warn("Checkpoints for file descriptors currently do not work.");
371 }
372 
373 void
375 {
376  memState->unserialize(cp);
377  pTable->unserialize(cp);
382  warn("Checkpoints for file descriptors currently do not work.");
383  // The above returns a bool so that you could do something if you don't
384  // find the param in the checkpoint if you wanted to, like set a default
385  // but in this case we'll just stick with the instantiated value if not
386  // found.
387 }
388 
389 bool
390 Process::map(Addr vaddr, Addr paddr, int size, bool cacheable)
391 {
392  pTable->map(vaddr, paddr, size,
393  cacheable ? EmulationPageTable::MappingFlags(0) :
395  return true;
396 }
397 
399 Process::findDriver(std::string filename)
400 {
401  for (EmulatedDriver *d : drivers) {
402  if (d->match(filename))
403  return d;
404  }
405 
406  return nullptr;
407 }
408 
409 std::string
410 Process::checkPathRedirect(const std::string &filename)
411 {
412  // If the input parameter contains a relative path, convert it.
413  // The target version of the current working directory is fine since
414  // we immediately convert it using redirect paths into a host version.
415  auto abs_path = absolutePath(filename, false);
416 
417  for (auto path : system->redirectPaths) {
418  // Search through the redirect paths to see if a starting substring of
419  // our path falls into any buckets which need to redirected.
420  if (startswith(abs_path, path->appPath())) {
421  std::string tail = abs_path.substr(path->appPath().size());
422 
423  // If this path needs to be redirected, search through a list
424  // of targets to see if we can match a valid file (or directory).
425  for (auto host_path : path->hostPaths()) {
426  if (access((host_path + tail).c_str(), R_OK) == 0) {
427  // Return the valid match.
428  return host_path + tail;
429  }
430  }
431  // The path needs to be redirected, but the file or directory
432  // does not exist on the host filesystem. Return the first
433  // host path as a default.
434  return path->hostPaths()[0] + tail;
435  }
436  }
437 
438  // The path does not need to be redirected.
439  return abs_path;
440 }
441 
442 void
444 {
445  auto *interp = objFile->getInterpreter();
446 
447  if (!interp || !interp->relocatable())
448  return;
449 
450  // Determine how large the interpreters footprint will be in the process
451  // address space.
452  Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes);
453 
454  // We are allocating the memory area; set the bias to the lowest address
455  // in the allocated memory region.
456  Addr mmap_end = memState->getMmapEnd();
457  Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
458 
459  // Adjust the process mmap area to give the interpreter room; the real
460  // execve system call would just invoke the kernel's internal mmap
461  // functions to make these adjustments.
462  mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
463  memState->setMmapEnd(mmap_end);
464 
465  interp->updateBias(ld_bias);
466 }
467 
470 {
471  return objFile->getInterpreter();
472 }
473 
474 Addr
476 {
477  auto *interp = getInterpreter();
478 
479  return interp ? interp->bias() : objFile->bias();
480 }
481 
482 Addr
484 {
485  auto *interp = getInterpreter();
486 
487  return interp ? interp->entryPoint() : objFile->entryPoint();
488 }
489 
490 std::string
491 Process::absolutePath(const std::string &filename, bool host_filesystem)
492 {
493  if (filename.empty() || startswith(filename, "/"))
494  return filename;
495 
496  // Construct the absolute path given the current working directory for
497  // either the host filesystem or target filesystem. The distinction only
498  // matters if filesystem redirection is utilized in the simulation.
499  auto path_base = std::string();
500  if (host_filesystem) {
501  path_base = hostCwd;
502  assert(!hostCwd.empty());
503  } else {
504  path_base = tgtCwd;
505  assert(!tgtCwd.empty());
506  }
507 
508  // Add a trailing '/' if the current working directory did not have one.
509  normalize(path_base);
510 
511  // Append the filename onto the current working path.
512  auto absolute_path = path_base + filename;
513 
514  return absolute_path;
515 }
516 
517 Process *
518 ProcessParams::create()
519 {
520  // If not specified, set the executable parameter equal to the
521  // simulated system's zeroth command line parameter
522  if (executable == "") {
523  executable = cmd[0];
524  }
525 
526  auto *obj_file = Loader::createObjectFile(executable);
527  fatal_if(!obj_file, "Cannot load object file %s.", executable);
528 
529  Process *process = Process::tryLoaders(this, obj_file);
530  fatal_if(!process, "Unknown error creating process object.");
531 
532  return process;
533 }
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:274
#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:326
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:374
void regStats() override
Callback to set stat parameters.
Definition: process.cc:261
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
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
Definition: process.cc:297
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:319
void replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, ThreadContext *new_tc, bool alloc_page)
Definition: process.cc:336
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:491
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:390
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:483
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:399
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:129
::Loader::ObjectFile * getInterpreter()
Definition: process.cc:469
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:355
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:443
virtual void clone(ThreadContext *old_tc, ThreadContext *new_tc, Process *new_p, RegVal flags)
Definition: process.cc:170
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:410
::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
SymbolTable * debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:46
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:361
#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:287
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:93
::Loader::ObjectFile * objFile
Definition: process.hh:213
Addr getBias()
Definition: process.cc:475
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 Thu May 28 2020 16:11:01 for gem5 by doxygen 1.8.13