gem5  v22.1.0.0
syscall_emul.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003-2005 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "sim/syscall_emul.hh"
30 
31 #include <fcntl.h>
32 #include <sys/syscall.h>
33 #include <unistd.h>
34 
35 #include <csignal>
36 #include <iostream>
37 #include <mutex>
38 #include <string>
39 #include <unordered_map>
40 
41 #include "base/chunk_generator.hh"
42 #include "base/trace.hh"
43 #include "cpu/thread_context.hh"
44 #include "dev/net/dist_iface.hh"
45 #include "mem/page_table.hh"
47 #include "sim/byteswap.hh"
48 #include "sim/process.hh"
49 #include "sim/proxy_ptr.hh"
50 #include "sim/sim_exit.hh"
52 #include "sim/syscall_desc.hh"
53 #include "sim/system.hh"
54 
55 namespace gem5
56 {
57 
58 void
59 warnUnsupportedOS(std::string syscall_name)
60 {
61  warn("Cannot invoke %s on host operating system.", syscall_name);
62 }
63 
64 SyscallReturn
66 {
67  fatal("syscall %s (#%d) unimplemented.", desc->name(), desc->num());
68 }
69 
70 
71 SyscallReturn
73 {
74  warn("ignoring syscall %s(...)", desc->name());
75  return 0;
76 }
77 
78 SyscallReturn
80 {
81  static std::unordered_map<SyscallDesc *, bool> bool_map;
82 
83  bool &warned = bool_map[desc];
84  if (!warned) {
85  warn("ignoring syscall %s(...)\n"
86  " (further warnings will be suppressed)", desc->name());
87  warned = true;
88  }
89 
90  return 0;
91 }
92 
93 static void
94 exitFutexWake(ThreadContext *tc, VPtr<> addr, uint64_t tgid)
95 {
96  // Clear value at address pointed to by thread's childClearTID field.
97  BufferArg ctidBuf(addr, sizeof(long));
98  long *ctid = (long *)ctidBuf.bufferPtr();
99  *ctid = 0;
100  ctidBuf.copyOut(SETranslatingPortProxy(tc));
101 
102  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
103  // Wake one of the waiting threads.
104  futex_map.wakeup(addr, tgid, 1);
105 }
106 
107 static SyscallReturn
108 exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
109 {
110  auto p = tc->getProcessPtr();
111 
112  System *sys = tc->getSystemPtr();
113 
114  if (group)
115  *p->exitGroup = true;
116 
117  if (p->childClearTID)
118  exitFutexWake(tc, p->childClearTID, p->tgid());
119 
120  bool last_thread = true;
121  Process *parent = nullptr, *tg_lead = nullptr;
122  for (int i = 0; last_thread && i < sys->threads.size(); i++) {
123  Process *walk;
124  if (!(walk = sys->threads[i]->getProcessPtr()))
125  continue;
126 
133  if (walk->pid() == p->tgid())
134  tg_lead = walk;
135 
136  auto *tc = sys->threads[i];
137  if ((tc->status() != ThreadContext::Halted) &&
138  (tc->status() != ThreadContext::Halting) &&
139  (walk != p)) {
146  if (walk->tgid() == p->tgid()) {
159  if (*(p->exitGroup)) {
160  tc->halt();
161  } else {
162  last_thread = false;
163  }
164  }
165 
175  if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
176  parent = walk;
177  }
178  }
179 
180  if (last_thread) {
181  if (parent) {
182  assert(tg_lead);
183  sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
184  }
185 
191  for (int i = 0; i < p->fds->getSize(); i++) {
192  if ((*p->fds)[i])
193  p->fds->closeFDEntry(i);
194  }
195  }
196 
201  if (!p->vforkContexts.empty()) {
202  ThreadContext *vtc = sys->threads[p->vforkContexts.front()];
203  assert(vtc->status() == ThreadContext::Suspended);
204  vtc->activate();
205  }
206 
207  tc->halt();
208 
213  int activeContexts = 0;
214  for (auto &system: sys->systemList)
215  activeContexts += system->threads.numRunning();
216 
217  if (activeContexts == 0) {
227  if (!DistIface::readyToExit(0)) {
228  return status;
229  }
230 
231  exitSimLoop("exiting with last active thread context", status & 0xff);
232  return status;
233  }
234 
235  return status;
236 }
237 
238 SyscallReturn
240 {
241  return exitImpl(desc, tc, false, status);
242 }
243 
244 SyscallReturn
246 {
247  return exitImpl(desc, tc, true, status);
248 }
249 
250 SyscallReturn
252 {
253  return (int)tc->getProcessPtr()->pTable->pageSize();
254 }
255 
256 
257 SyscallReturn
259 {
260  // change brk addr to first arg
261  auto p = tc->getProcessPtr();
262 
263  std::shared_ptr<MemState> mem_state = p->memState;
264  Addr brk_point = mem_state->getBrkPoint();
265 
266  // in Linux at least, brk(0) returns the current break value
267  // (note that the syscall and the glibc function have different behavior)
268  if (new_brk == 0 || (new_brk == brk_point))
269  return brk_point;
270 
271  mem_state->updateBrkRegion(brk_point, new_brk);
272 
273  DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
274  mem_state->getBrkPoint());
275 
276  return mem_state->getBrkPoint();
277 }
278 
279 SyscallReturn
280 setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
281 {
282  auto process = tc->getProcessPtr();
283 
284  process->childClearTID = tidPtr;
285  return process->pid();
286 }
287 
288 SyscallReturn
289 closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
290 {
291  auto p = tc->getProcessPtr();
292  return p->fds->closeFDEntry(tgt_fd);
293 }
294 
295 SyscallReturn
297  int tgt_fd, uint64_t offs, int whence)
298 {
299  auto p = tc->getProcessPtr();
300 
301  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
302  if (!ffdp)
303  return -EBADF;
304  int sim_fd = ffdp->getSimFD();
305 
306  off_t result = lseek(sim_fd, offs, whence);
307 
308  return (result == (off_t)-1) ? -errno : result;
309 }
310 
311 
312 SyscallReturn
314  int tgt_fd, uint64_t offset_high, uint32_t offset_low,
315  VPtr<> result_ptr, int whence)
316 {
317  auto p = tc->getProcessPtr();
318 
319  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
320  if (!ffdp)
321  return -EBADF;
322  int sim_fd = ffdp->getSimFD();
323 
324  uint64_t offset = (offset_high << 32) | offset_low;
325 
326  uint64_t result = lseek(sim_fd, offset, whence);
327  result = htog(result, tc->getSystemPtr()->getGuestByteOrder());
328 
329  if (result == (off_t)-1)
330  return -errno;
331  // Assuming that the size of loff_t is 64 bits on the target platform
332  BufferArg result_buf(result_ptr, sizeof(result));
333  std::memcpy(result_buf.bufferPtr(), &result, sizeof(result));
334  result_buf.copyOut(SETranslatingPortProxy(tc));
335  return 0;
336 }
337 
338 
339 const char *hostname = "m5.eecs.umich.edu";
340 
343  VPtr<> buf_ptr, int name_len)
344 {
345  BufferArg name(buf_ptr, name_len);
346  strncpy((char *)name.bufferPtr(), hostname, name_len);
347  name.copyOut(SETranslatingPortProxy(tc));
348  return 0;
349 }
350 
351 SyscallReturn
353  VPtr<> buf_ptr, unsigned long size)
354 {
355  int result = 0;
356  auto p = tc->getProcessPtr();
357  BufferArg buf(buf_ptr, size);
358 
359  // Is current working directory defined?
360  std::string cwd = p->tgtCwd;
361  if (!cwd.empty()) {
362  if (cwd.length() >= size) {
363  // Buffer too small
364  return -ERANGE;
365  }
366  strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
367  result = cwd.length();
368  } else {
369  if (getcwd((char *)buf.bufferPtr(), size)) {
370  result = strlen((char *)buf.bufferPtr());
371  } else {
372  result = -1;
373  }
374  }
375 
377 
378  return (result == -1) ? -errno : result;
379 }
380 
381 SyscallReturn
383 {
384  std::string path;
385  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
386  return -EFAULT;
387 
388  return unlinkImpl(desc, tc, path);
389 }
390 
391 SyscallReturn
392 unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
393 {
394  auto p = tc->getProcessPtr();
395  path = p->checkPathRedirect(path);
396 
397  int result = unlink(path.c_str());
398  return (result == -1) ? -errno : result;
399 }
400 
401 SyscallReturn
403  VPtr<> pathname, VPtr<> new_pathname)
404 {
405  std::string path;
406  std::string new_path;
407  auto p = tc->getProcessPtr();
408 
409  SETranslatingPortProxy virt_mem(tc);
410  if (!virt_mem.tryReadString(path, pathname))
411  return -EFAULT;
412  if (!virt_mem.tryReadString(new_path, new_pathname))
413  return -EFAULT;
414 
415  path = p->absolutePath(path, true);
416  new_path = p->absolutePath(new_path, true);
417 
418  int result = link(path.c_str(), new_path.c_str());
419  return (result == -1) ? -errno : result;
420 }
421 
422 SyscallReturn
424  VPtr<> pathname, VPtr<> new_pathname)
425 {
426  std::string path;
427  std::string new_path;
428  auto p = tc->getProcessPtr();
429 
430  SETranslatingPortProxy virt_mem(tc);
431  if (!virt_mem.tryReadString(path, pathname))
432  return -EFAULT;
433  if (!virt_mem.tryReadString(new_path, new_pathname))
434  return -EFAULT;
435 
436  path = p->absolutePath(path, true);
437  new_path = p->absolutePath(new_path, true);
438 
439  int result = symlink(path.c_str(), new_path.c_str());
440  return (result == -1) ? -errno : result;
441 }
442 
443 SyscallReturn
444 mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
445 {
446  std::string path;
447  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
448  return -EFAULT;
449 
450  return mkdirImpl(desc, tc, path, mode);
451 }
452 
453 SyscallReturn
454 mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
455 {
456  auto p = tc->getProcessPtr();
457  path = p->checkPathRedirect(path);
458 
459  auto result = mkdir(path.c_str(), mode);
460  return (result == -1) ? -errno : result;
461 }
462 
463 SyscallReturn
465  VPtr<> newpath)
466 {
467  SETranslatingPortProxy proxy(tc);
468  std::string old_name;
469  if (!proxy.tryReadString(old_name, oldpath))
470  return -EFAULT;
471 
472  std::string new_name;
473  if (!proxy.tryReadString(new_name, newpath))
474  return -EFAULT;
475 
476  return renameImpl(desc, tc, old_name, new_name);
477 }
478 
479 SyscallReturn
481  std::string old_name, std::string new_name)
482 {
483  auto p = tc->getProcessPtr();
484 
485  // Adjust path for cwd and redirection
486  old_name = p->checkPathRedirect(old_name);
487  new_name = p->checkPathRedirect(new_name);
488 
489  int64_t result = rename(old_name.c_str(), new_name.c_str());
490  return (result == -1) ? -errno : result;
491 }
492 
493 
494 SyscallReturn
496  VPtr<> pathname, int64_t length)
497 {
498  auto process = tc->getProcessPtr();
499  std::string path;
500 
501  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
502  return -EFAULT;
503 
504  // Adjust path for cwd and redirection
505  path = process->checkPathRedirect(path);
506 
507 #if NO_STAT64
508  int result = truncate(path.c_str(), length);
509 #else
510  int result = truncate64(path.c_str(), length);
511 #endif
512  return (result == -1) ? -errno : result;
513 }
514 
515 SyscallReturn
517  int tgt_fd, int64_t length)
518 {
519  auto p = tc->getProcessPtr();
520 
521  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
522  if (!ffdp)
523  return -EBADF;
524  int sim_fd = ffdp->getSimFD();
525 
526 #if NO_STAT64
527  int result = ftruncate(sim_fd, length);
528 #else
529  int result = ftruncate64(sim_fd, length);
530 #endif
531  return (result == -1) ? -errno : result;
532 }
533 
534 SyscallReturn
536 {
537  // Letting the simulated program change the simulator's umask seems like
538  // a bad idea. Compromise by just returning the current umask but not
539  // changing anything.
540  mode_t oldMask = umask(0);
541  umask(oldMask);
542  return (int)oldMask;
543 }
544 
545 SyscallReturn
547  VPtr<> pathname, uint32_t owner, uint32_t group)
548 {
549  std::string path;
550  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
551  return -EFAULT;
552 
553  return chownImpl(desc, tc, path, owner, group);
554 }
555 
556 SyscallReturn
558  std::string path, uint32_t owner, uint32_t group)
559 {
560  auto p = tc->getProcessPtr();
561 
562  /* XXX endianess */
563  uid_t hostOwner = owner;
564  gid_t hostGroup = group;
565 
566  // Adjust path for cwd and redirection
567  path = p->checkPathRedirect(path);
568 
569  int result = chown(path.c_str(), hostOwner, hostGroup);
570  return (result == -1) ? -errno : result;
571 }
572 
573 SyscallReturn
575  int tgt_fd, uint32_t owner, uint32_t group)
576 {
577  auto p = tc->getProcessPtr();
578 
579  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
580  if (!ffdp)
581  return -EBADF;
582  int sim_fd = ffdp->getSimFD();
583 
584  /* XXX endianess */
585  uid_t hostOwner = owner;
586  gid_t hostGroup = group;
587 
588  int result = fchown(sim_fd, hostOwner, hostGroup);
589  return (result == -1) ? -errno : result;
590 }
591 
598 SyscallReturn
599 dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
600 {
601  auto p = tc->getProcessPtr();
602 
603  auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
604  if (!old_hbfdp)
605  return -EBADF;
606  int sim_fd = old_hbfdp->getSimFD();
607 
608  int result = dup(sim_fd);
609  if (result == -1)
610  return -errno;
611 
612  auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
613  new_hbfdp->setSimFD(result);
614  new_hbfdp->setCOE(false);
615  return p->fds->allocFD(new_hbfdp);
616 }
617 
618 SyscallReturn
619 dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
620 {
621  auto p = tc->getProcessPtr();
622  auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
623  if (!old_hbp)
624  return -EBADF;
625  int old_sim_fd = old_hbp->getSimFD();
626 
632  int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
633  if (res_fd == -1)
634  return -errno;
635 
636  auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
637  if (new_hbp)
638  p->fds->closeFDEntry(new_tgt_fd);
639  new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
640  new_hbp->setSimFD(res_fd);
641  new_hbp->setCOE(false);
642 
643  return p->fds->allocFD(new_hbp);
644 }
645 
646 SyscallReturn
648  int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs)
649 {
650  auto p = tc->getProcessPtr();
651 
652  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
653  if (!hbfdp)
654  return -EBADF;
655  int sim_fd = hbfdp->getSimFD();
656 
657  int coe = hbfdp->getCOE();
658 
659  switch (cmd) {
660  case F_GETFD:
661  return coe & FD_CLOEXEC;
662 
663  case F_SETFD: {
664  int arg = varargs.get<int>();
665  arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
666  return 0;
667  }
668 
669  // Rely on the host to maintain the file status flags for this file
670  // description rather than maintain it ourselves. Admittedly, this
671  // is suboptimal (and possibly error prone), but it is difficult to
672  // maintain the flags by tracking them across the different descriptors
673  // (that refer to this file description) caused by clone, dup, and
674  // subsequent fcntls.
675  case F_GETFL:
676  case F_SETFL: {
677  int arg = varargs.get<int>();
678  int rv = fcntl(sim_fd, cmd, arg);
679  return (rv == -1) ? -errno : rv;
680  }
681 
682  default:
683  warn("fcntl: unsupported command %d\n", cmd);
684  return 0;
685  }
686 }
687 
688 SyscallReturn
689 fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
690 {
691  auto p = tc->getProcessPtr();
692 
693  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
694  if (!hbfdp)
695  return -EBADF;
696  int sim_fd = hbfdp->getSimFD();
697 
698  switch (cmd) {
699  case 33: //F_GETLK64
700  warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
701  return -EMFILE;
702 
703  case 34: // F_SETLK64
704  case 35: // F_SETLKW64
705  warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
706  tgt_fd);
707  return -EMFILE;
708 
709  default:
710  // not sure if this is totally valid, but we'll pass it through
711  // to the underlying OS
712  warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
713  return fcntl(sim_fd, cmd);
714  }
715 }
716 
717 SyscallReturn
719 {
720  return pipe2Func(desc, tc, 0, 0);
721 }
722 
723 SyscallReturn
725 {
726  return pipe2Func(desc, tc, tgt_addr, 0);
727 }
728 
729 SyscallReturn
730 pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
731 {
732  auto p = tc->getProcessPtr();
733 
734  int sim_fds[2], tgt_fds[2];
735 
736  int pipe_retval = pipe(sim_fds);
737  if (pipe_retval == -1)
738  return -errno;
739 
740  auto rend = PipeFDEntry::EndType::read;
741  auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
742  tgt_fds[0] = p->fds->allocFD(rpfd);
743  int sim_fd_rpfd = rpfd->getSimFD();
744 
745  auto wend = PipeFDEntry::EndType::write;
746  auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
747  tgt_fds[1] = p->fds->allocFD(wpfd);
748  int sim_fd_wpfd = wpfd->getSimFD();
749 
754  rpfd->setPipeReadSource(tgt_fds[1]);
755 
761  if (tgt_addr == 0)
762  return SyscallReturn(tgt_fds[0], tgt_fds[1]);
763 
768  BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
769  int *buf_ptr = (int*)tgt_handle.bufferPtr();
770  buf_ptr[0] = tgt_fds[0];
771  buf_ptr[1] = tgt_fds[1];
772  tgt_handle.copyOut(SETranslatingPortProxy(tc));
773 
774  if (flags) {
775  // pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
776  // if flags set to anything else, return EINVAL
777  if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
778  (flags != (O_CLOEXEC | O_NONBLOCK))) {
779  return -EINVAL;
780  }
781 
782  /*
783  If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
784  status flag for two new open file descriptors.
785  */
786  if (flags & O_NONBLOCK) {
787  /*
788  O_NONBLOCK is set when the programmer wants to avoid a separate
789  call(s) to fcntl in their code, so mirror the fcntl
790  implementation for handling file descriptors -- rely on host to
791  maintain file status flags.
792  */
793  if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
794  return -errno;
795  }
796  if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
797  return -errno;
798  }
799  }
800 
801  /*
802  If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
803  (FD_CLOEXEC) file status flag for two new open file descriptors.
804  */
805  if (flags & O_CLOEXEC) {
806  rpfd->setCOE(true);
807  wpfd->setCOE(true);
808  }
809  }
810 
811  return 0;
812 }
813 
814 SyscallReturn
816 {
817  auto process = tc->getProcessPtr();
818  return process->pgid();
819 }
820 
821 SyscallReturn
822 setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
823 {
824  auto process = tc->getProcessPtr();
825 
826  if (pgid < 0)
827  return -EINVAL;
828 
829  if (pid == 0) {
830  process->pgid(process->pid());
831  return 0;
832  }
833 
834  Process *matched_ph = nullptr;
835  System *sysh = tc->getSystemPtr();
836 
837  // Retrieves process pointer from active/suspended thread contexts.
838  for (auto *tc: sysh->threads) {
839  if (tc->status() != ThreadContext::Halted) {
840  Process *temp_h = tc->getProcessPtr();
841  Process *walk_ph = (Process*)temp_h;
842 
843  if (walk_ph && walk_ph->pid() == process->pid())
844  matched_ph = walk_ph;
845  }
846  }
847 
848  assert(matched_ph);
849  matched_ph->pgid((pgid == 0) ? matched_ph->pid() : pgid);
850 
851  return 0;
852 }
853 
854 
855 SyscallReturn
857 {
858  auto process = tc->getProcessPtr();
859  return process->tgid();
860 }
861 
862 SyscallReturn
864 {
865  auto process = tc->getProcessPtr();
866  return process->pid();
867 }
868 
869 SyscallReturn
871 {
872  auto process = tc->getProcessPtr();
873  return process->ppid();
874 }
875 
876 SyscallReturn
878 {
879  auto process = tc->getProcessPtr();
880  return process->uid(); // UID
881 }
882 
883 SyscallReturn
885 {
886  auto process = tc->getProcessPtr();
887  return process->euid(); // UID
888 }
889 
890 SyscallReturn
892 {
893  auto process = tc->getProcessPtr();
894  return process->gid();
895 }
896 
897 SyscallReturn
899 {
900  auto process = tc->getProcessPtr();
901  return process->egid();
902 }
903 
904 SyscallReturn
906  VPtr<> pathname, mode_t mode)
907 {
908  std::string path;
909  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
910  return -EFAULT;
911 
912  return accessImpl(desc, tc, path, mode);
913 }
914 
915 SyscallReturn
917  std::string path, mode_t mode)
918 {
919  auto p = tc->getProcessPtr();
920  // Adjust path for cwd and redirection
921  path = p->checkPathRedirect(path);
922 
923  int result = access(path.c_str(), mode);
924  return (result == -1) ? -errno : result;
925 }
926 
927 SyscallReturn
929  VPtr<> pathname, mode_t mode, dev_t dev)
930 {
931  std::string path;
932  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
933  return -EFAULT;
934 
935  return mknodImpl(desc, tc, path, mode, dev);
936 }
937 
938 SyscallReturn
940  std::string path, mode_t mode, dev_t dev)
941 {
942  auto p = tc->getProcessPtr();
943  path = p->checkPathRedirect(path);
944 
945  auto result = mknod(path.c_str(), mode, dev);
946  return (result == -1) ? -errno : result;
947 }
948 
949 SyscallReturn
951 {
952  auto p = tc->getProcessPtr();
953  std::string path;
954  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
955  return -EFAULT;
956 
957  std::string tgt_cwd;
958  if (startswith(path, "/")) {
959  tgt_cwd = path;
960  } else {
961  char buf[PATH_MAX];
962  tgt_cwd = realpath((p->tgtCwd + "/" + path).c_str(), buf);
963  }
964  std::string host_cwd = p->checkPathRedirect(tgt_cwd);
965 
966  int result = chdir(host_cwd.c_str());
967 
968  if (result == -1)
969  return -errno;
970 
971  p->hostCwd = host_cwd;
972  p->tgtCwd = tgt_cwd;
973  return result;
974 }
975 
976 SyscallReturn
978 {
979  std::string path;
980  if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
981  return -EFAULT;
982 
983  return rmdirImpl(desc, tc, path);
984 }
985 
986 SyscallReturn
987 rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
988 {
989  auto p = tc->getProcessPtr();
990  path = p->checkPathRedirect(path);
991 
992  auto result = rmdir(path.c_str());
993  return (result == -1) ? -errno : result;
994 }
995 
996 #if defined(SYS_getdents) || defined(SYS_getdents64)
997 template<typename DE, int SYS_NUM>
998 static SyscallReturn
999 getdentsImpl(SyscallDesc *desc, ThreadContext *tc,
1000  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1001 {
1002  auto p = tc->getProcessPtr();
1003 
1004  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1005  if (!hbfdp)
1006  return -EBADF;
1007  int sim_fd = hbfdp->getSimFD();
1008 
1009  BufferArg buf_arg(buf_ptr, count);
1010  auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
1011 
1012  if (status == -1)
1013  return -errno;
1014 
1015  unsigned traversed = 0;
1016  while (traversed < status) {
1017  DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
1018 
1019  auto host_reclen = buffer->d_reclen;
1020 
1026  const ByteOrder bo = tc->getSystemPtr()->getGuestByteOrder();
1027  buffer->d_ino = htog(buffer->d_ino, bo);
1028  buffer->d_off = htog(buffer->d_off, bo);
1029  buffer->d_reclen = htog(buffer->d_reclen, bo);
1030 
1031  traversed += host_reclen;
1032  }
1033 
1034  buf_arg.copyOut(SETranslatingPortProxy(tc));
1035  return status;
1036 }
1037 #endif
1038 
1039 #if defined(SYS_getdents)
1040 SyscallReturn
1041 getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
1042  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1043 {
1044  typedef struct linux_dirent
1045  {
1046  unsigned long d_ino;
1047  unsigned long d_off;
1048  unsigned short d_reclen;
1049  char dname[];
1050  } LinDent;
1051 
1052  return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1053  tgt_fd, buf_ptr, count);
1054 }
1055 #endif
1056 
1057 #if defined(SYS_getdents64)
1058 SyscallReturn
1059 getdents64Func(SyscallDesc *desc, ThreadContext *tc,
1060  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1061 {
1062  typedef struct linux_dirent64
1063  {
1064  ino64_t d_ino;
1065  off64_t d_off;
1066  unsigned short d_reclen;
1067  char dname[];
1068  } LinDent64;
1069 
1070  return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1071  tgt_fd, buf_ptr, count);
1072 }
1073 #endif
1074 
1075 SyscallReturn
1076 shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
1077 {
1078  auto p = tc->getProcessPtr();
1079 
1080  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1081  if (!sfdp)
1082  return -EBADF;
1083  int sim_fd = sfdp->getSimFD();
1084 
1085  int retval = shutdown(sim_fd, how);
1086 
1087  return (retval == -1) ? -errno : retval;
1088 }
1089 
1090 SyscallReturn
1092  int tgt_fd, VPtr<> buf_ptr, int addrlen)
1093 {
1094  auto p = tc->getProcessPtr();
1095 
1096  BufferArg bufSock(buf_ptr, addrlen);
1097  bufSock.copyIn(SETranslatingPortProxy(tc));
1098 
1099  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1100  if (!sfdp)
1101  return -EBADF;
1102  int sim_fd = sfdp->getSimFD();
1103 
1104  int status = ::bind(sim_fd,
1105  (struct sockaddr *)bufSock.bufferPtr(),
1106  addrlen);
1107 
1108  return (status == -1) ? -errno : status;
1109 }
1110 
1111 SyscallReturn
1112 listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
1113 {
1114  auto p = tc->getProcessPtr();
1115 
1116  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1117  if (!sfdp)
1118  return -EBADF;
1119  int sim_fd = sfdp->getSimFD();
1120 
1121  int status = listen(sim_fd, backlog);
1122 
1123  return (status == -1) ? -errno : status;
1124 }
1125 
1126 SyscallReturn
1128  int tgt_fd, VPtr<> buf_ptr, int addrlen)
1129 {
1130  auto p = tc->getProcessPtr();
1131 
1132  BufferArg addr(buf_ptr, addrlen);
1133  addr.copyIn(SETranslatingPortProxy(tc));
1134 
1135  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1136  if (!sfdp)
1137  return -EBADF;
1138  int sim_fd = sfdp->getSimFD();
1139 
1140  int status = connect(sim_fd,
1141  (struct sockaddr *)addr.bufferPtr(),
1142  (socklen_t)addrlen);
1143 
1144  return (status == -1) ? -errno : status;
1145 }
1146 
1147 
1148 SyscallReturn
1150  int tgt_fd, VPtr<> msgPtr, int flags)
1151 {
1152  auto p = tc->getProcessPtr();
1153 
1154  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1155  if (!sfdp)
1156  return -EBADF;
1157  int sim_fd = sfdp->getSimFD();
1158 
1177  SETranslatingPortProxy proxy(tc);
1178 
1184  BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1185  msgBuf.copyIn(proxy);
1186  struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
1187 
1193  Addr msg_name_phold = 0;
1194  Addr msg_iov_phold = 0;
1195  Addr iovec_base_phold[msgHdr->msg_iovlen];
1196  Addr msg_control_phold = 0;
1197 
1201  BufferArg *nameBuf = NULL;
1202  if (msgHdr->msg_name) {
1203  /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
1204  /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1205  /*3*/nameBuf->copyIn(proxy);
1206  /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
1207  }
1208 
1214  BufferArg *iovBuf = NULL;
1215  BufferArg *iovecBuf[msgHdr->msg_iovlen];
1216  for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1217  iovec_base_phold[i] = 0;
1218  iovecBuf[i] = NULL;
1219  }
1220 
1221  if (msgHdr->msg_iov) {
1222  /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
1223  /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1224  sizeof(struct iovec));
1225  /*3*/iovBuf->copyIn(proxy);
1226  for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1227  if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1228  /*1*/iovec_base_phold[i] =
1229  (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
1230  /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
1231  ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
1232  /*3*/iovecBuf[i]->copyIn(proxy);
1233  /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1234  iovecBuf[i]->bufferPtr();
1235  }
1236  }
1237  /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
1238  }
1239 
1243  BufferArg *controlBuf = NULL;
1244  if (msgHdr->msg_control) {
1245  /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
1246  /*2*/controlBuf = new BufferArg(msg_control_phold,
1247  CMSG_ALIGN(msgHdr->msg_controllen));
1248  /*3*/controlBuf->copyIn(proxy);
1249  /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
1250  }
1251 
1252  ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1253 
1254  if (recvd_size < 0)
1255  return -errno;
1256 
1257  if (msgHdr->msg_name) {
1258  nameBuf->copyOut(proxy);
1259  delete(nameBuf);
1260  msgHdr->msg_name = (void *)msg_name_phold;
1261  }
1262 
1263  if (msgHdr->msg_iov) {
1264  for (int i = 0; i< msgHdr->msg_iovlen; i++) {
1265  if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1266  iovecBuf[i]->copyOut(proxy);
1267  delete iovecBuf[i];
1268  ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1269  (void *)iovec_base_phold[i];
1270  }
1271  }
1272  iovBuf->copyOut(proxy);
1273  delete iovBuf;
1274  msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
1275  }
1276 
1277  if (msgHdr->msg_control) {
1278  controlBuf->copyOut(proxy);
1279  delete(controlBuf);
1280  msgHdr->msg_control = (void *)msg_control_phold;
1281  }
1282 
1283  msgBuf.copyOut(proxy);
1284 
1285  return recvd_size;
1286 }
1287 
1288 SyscallReturn
1290  int tgt_fd, VPtr<> msgPtr, int flags)
1291 {
1292  auto p = tc->getProcessPtr();
1293 
1294  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1295  if (!sfdp)
1296  return -EBADF;
1297  int sim_fd = sfdp->getSimFD();
1298 
1299  SETranslatingPortProxy proxy(tc);
1300 
1304  BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1305  msgBuf.copyIn(proxy);
1306  struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
1307 
1312  struct iovec *iovPtr = msgHdr.msg_iov;
1313  BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
1314  iovBuf.copyIn(proxy);
1315  struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
1316  msgHdr.msg_iov = iov;
1317 
1323  BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
1324  * sizeof(BufferArg *));
1325 
1331  for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1332  Addr basePtr = (Addr) iov[iovIndex].iov_base;
1333  bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
1334  bufferArray[iovIndex]->copyIn(proxy);
1335  iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
1336  }
1337 
1338  ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1339  int local_errno = errno;
1340 
1344  for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1345  BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
1346  delete(baseBuf);
1347  }
1348 
1352  free(bufferArray);
1353 
1354  return (sent_size < 0) ? -local_errno : sent_size;
1355 }
1356 
1357 SyscallReturn
1359  int tgt_fd, int level, int optname, VPtr<> valPtr,
1360  VPtr<> lenPtr)
1361 {
1362  // union of all possible return value types from getsockopt
1363  union val
1364  {
1365  int i_val;
1366  long l_val;
1367  struct linger linger_val;
1368  struct timeval timeval_val;
1369  } val;
1370 
1371  auto p = tc->getProcessPtr();
1372 
1373  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1374  if (!sfdp)
1375  return -EBADF;
1376  int sim_fd = sfdp->getSimFD();
1377 
1378  socklen_t len = sizeof(val);
1379  int status = getsockopt(sim_fd, level, optname, &val, &len);
1380 
1381  if (status == -1)
1382  return -errno;
1383 
1384  SETranslatingPortProxy proxy(tc);
1385 
1386  // copy val to valPtr and pass it on
1387  BufferArg valBuf(valPtr, sizeof(val));
1388  memcpy(valBuf.bufferPtr(), &val, sizeof(val));
1389  valBuf.copyOut(proxy);
1390 
1391  // copy len to lenPtr and pass it on
1392  BufferArg lenBuf(lenPtr, sizeof(len));
1393  memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
1394  lenBuf.copyOut(proxy);
1395 
1396  return status;
1397 }
1398 
1399 SyscallReturn
1401  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
1402 {
1403  auto p = tc->getProcessPtr();
1404 
1405  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1406  if (!sfdp)
1407  return -EBADF;
1408  int sim_fd = sfdp->getSimFD();
1409 
1410  // lenPtr is an in-out paramenter:
1411  // sending the address length in, conveying the final length out
1412 
1413  SETranslatingPortProxy proxy(tc);
1414 
1415  // Read in the value of len from the passed pointer.
1416  BufferArg lenBuf(lenPtr, sizeof(socklen_t));
1417  lenBuf.copyIn(proxy);
1418  socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
1419 
1420  struct sockaddr sa;
1421  int status = getsockname(sim_fd, &sa, &len);
1422 
1423  if (status == -1)
1424  return -errno;
1425 
1426  // Copy address to addrPtr and pass it on.
1427  BufferArg addrBuf(addrPtr, sizeof(sa));
1428  memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
1429  addrBuf.copyOut(proxy);
1430 
1431  // Copy len to lenPtr and pass it on.
1432  *(socklen_t *)lenBuf.bufferPtr() = len;
1433  lenBuf.copyOut(proxy);
1434 
1435  return status;
1436 }
1437 
1438 SyscallReturn
1440  int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
1441 {
1442  auto p = tc->getProcessPtr();
1443 
1444  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1445  if (!sfdp)
1446  return -EBADF;
1447  int sim_fd = sfdp->getSimFD();
1448 
1449  SETranslatingPortProxy proxy(tc);
1450 
1451  BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
1452  bufAddrlen.copyIn(proxy);
1453  BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
1454 
1455  int retval = getpeername(sim_fd,
1456  (struct sockaddr *)bufSock.bufferPtr(),
1457  (unsigned *)bufAddrlen.bufferPtr());
1458 
1459  if (retval != -1) {
1460  bufSock.copyOut(proxy);
1461  bufAddrlen.copyOut(proxy);
1462  }
1463 
1464  return (retval == -1) ? -errno : retval;
1465 }
1466 
1467 SyscallReturn
1469  int tgt_fd, int level, int optname, VPtr<> valPtr,
1470  socklen_t len)
1471 {
1472  auto p = tc->getProcessPtr();
1473 
1474  BufferArg valBuf(valPtr, len);
1475  valBuf.copyIn(SETranslatingPortProxy(tc));
1476 
1477  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1478  if (!sfdp)
1479  return -EBADF;
1480  int sim_fd = sfdp->getSimFD();
1481 
1482  int status = setsockopt(sim_fd, level, optname,
1483  (struct sockaddr *)valBuf.bufferPtr(), len);
1484 
1485  return (status == -1) ? -errno : status;
1486 }
1487 
1488 SyscallReturn
1490  VPtr<uint32_t> cpu, VPtr<uint32_t> node, VPtr<uint32_t> tcache)
1491 {
1492  // unsigned is the same size (4) on all Linux supported ISAs.
1493  if (cpu)
1494  *cpu = htog(tc->contextId(), tc->getSystemPtr()->getGuestByteOrder());
1495 
1496  // Set a fixed NUMA node 0.
1497  if (node)
1498  *node = 0;
1499 
1500  return 0;
1501 }
1502 
1503 } // namespace gem5
Declaration and inline definition of ChunkGenerator object.
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
static bool readyToExit(Tick delay)
Initiate the exit from the simulation.
Definition: dist_iface.cc:891
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:110
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.cc:59
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
Definition: port_proxy.cc:115
uint64_t egid()
Definition: process.hh:86
uint64_t pid()
Definition: process.hh:87
uint64_t uid()
Definition: process.hh:83
uint64_t pgid()
Definition: process.hh:89
uint64_t ppid()
Definition: process.hh:88
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:424
uint64_t gid()
Definition: process.hh:85
uint64_t tgid()
Definition: process.hh:91
uint64_t euid()
Definition: process.hh:84
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
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:70
std::string name() const
Definition: syscall_desc.hh:80
int num() const
Definition: syscall_desc.hh:81
This class represents the return value from an emulated system call, including any errno setting.
int size() const
Definition: system.hh:213
std::list< BasicSignal > signalList
Definition: system.hh:610
FutexMap futexMap
Definition: system.hh:601
ByteOrder getGuestByteOrder() const
Get the guest byte order.
Definition: system.hh:391
static std::vector< System * > systemList
Definition: system.hh:596
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 System * getSystemPtr()=0
virtual void halt()=0
Set the status to Halted.
@ Halted
Permanently shut down.
@ Halting
Trying to exit and waiting for an event to completely exit.
@ Suspended
Temporarily inactive.
virtual Status status() const =0
virtual ContextID contextId() const =0
virtual Process * getProcessPtr()=0
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
uint16_t len
Definition: helpers.cc:62
uint8_t flags
Definition: helpers.cc:66
#define warn(...)
Definition: logging.hh:246
Bitfield< 3 > sa
Definition: misc_types.hh:398
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 5, 0 > status
Definition: misc_types.hh:429
Bitfield< 25, 21 > bo
Definition: types.hh:82
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 15 > system
Definition: misc.hh:1004
Bitfield< 63 > val
Definition: misc.hh:776
Bitfield< 20 > level
Definition: intmessage.hh:51
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:59
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:229
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
static void exitFutexWake(ThreadContext *tc, VPtr<> addr, uint64_t tgid)
Definition: syscall_emul.cc:94
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
const char * hostname
SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc, std::string old_name, std::string new_name)
SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode, dev_t dev)
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, uint32_t owner, uint32_t group)
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
Definition: syscall_emul.cc:79
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:65
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:72
SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
static SyscallReturn exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Declarations of a non-full system Page Table.
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
This file defines objects used to emulate syscalls from the target application on the host machine.
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:40 for gem5 by doxygen 1.9.1