2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
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.
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.
28 * Authors: Steve Reinhardt
39 #include "arch/utility.hh"
40 #include "base/chunk_generator.hh"
41 #include "base/trace.hh"
42 #include "config/the_isa.hh"
43 #include "cpu/base.hh"
44 #include "cpu/thread_context.hh"
45 #include "debug/SyscallVerbose.hh"
46 #include "mem/page_table.hh"
47 #include "sim/process.hh"
48 #include "sim/sim_exit.hh"
49 #include "sim/syscall_emul.hh"
50 #include "sim/system.hh"
53 using namespace TheISA
;
56 SyscallDesc::doSyscall(int callnum
, LiveProcess
*process
, ThreadContext
*tc
)
58 if (DTRACE(SyscallVerbose
)) {
60 IntReg arg
[4] M5_VAR_USED
;
62 // we can't just put the calls to getSyscallArg() in the
63 // DPRINTF arg list, because C++ doesn't guarantee their order
64 for (int i
= 0; i
< 4; ++i
)
65 arg
[i
] = process
->getSyscallArg(tc
, index
);
67 DPRINTFNR("%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n",
68 curTick(), tc
->getCpuPtr()->name(), name
,
69 arg
[0], arg
[1], arg
[2], arg
[3]);
72 SyscallReturn retval
= (*funcPtr
)(this, callnum
, process
, tc
);
74 if (retval
.needsRetry()) {
75 DPRINTFS(SyscallVerbose
, tc
->getCpuPtr(), "syscall %s needs retry\n",
78 DPRINTFS(SyscallVerbose
, tc
->getCpuPtr(), "syscall %s returns %d\n",
79 name
, retval
.encodedValue());
82 if (!(flags
& SyscallDesc::SuppressReturnValue
) && !retval
.needsRetry())
83 process
->setSyscallReturn(tc
, retval
);
88 unimplementedFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
91 fatal("syscall %s (#%d) unimplemented.", desc
->name
, callnum
);
98 ignoreFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
102 const char *extra_text
= "";
104 if (desc
->warnOnce()) {
109 extra_text
= "\n (further warnings will be suppressed)";
112 warn("ignoring syscall %s(%d, ...)%s", desc
->name
,
113 process
->getSyscallArg(tc
, index
), extra_text
);
120 exitFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
123 if (process
->system
->numRunningContexts() == 1) {
124 // Last running context... exit simulator
126 exitSimLoop("target called exit()",
127 process
->getSyscallArg(tc
, index
) & 0xff);
129 // other running threads... just halt this one
138 exitGroupFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
141 // halt all threads belonging to this process
142 for (auto i
: process
->contextIds
) {
143 process
->system
->getThreadContext(i
)->halt();
146 if (!process
->system
->numRunningContexts()) {
147 // all threads belonged to this process... exit simulator
149 exitSimLoop("target called exit()",
150 process
->getSyscallArg(tc
, index
) & 0xff);
158 getpagesizeFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
160 return (int)PageBytes
;
165 brkFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
167 // change brk addr to first arg
169 Addr new_brk
= p
->getSyscallArg(tc
, index
);
171 // in Linux at least, brk(0) returns the current break value
172 // (note that the syscall and the glibc function have different behavior)
176 if (new_brk
> p
->brk_point
) {
177 // might need to allocate some new pages
178 for (ChunkGenerator
gen(p
->brk_point
, new_brk
- p
->brk_point
,
179 PageBytes
); !gen
.done(); gen
.next()) {
180 if (!p
->pTable
->translate(gen
.addr()))
181 p
->allocateMem(roundDown(gen
.addr(), PageBytes
), PageBytes
);
183 // if the address is already there, zero it out
186 SETranslatingPortProxy
&tp
= tc
->getMemProxy();
188 // split non-page aligned accesses
189 Addr next_page
= roundUp(gen
.addr(), PageBytes
);
190 uint32_t size_needed
= next_page
- gen
.addr();
191 tp
.memsetBlob(gen
.addr(), zero
, size_needed
);
192 if (gen
.addr() + PageBytes
> next_page
&&
193 next_page
< new_brk
&&
194 p
->pTable
->translate(next_page
))
196 size_needed
= PageBytes
- size_needed
;
197 tp
.memsetBlob(next_page
, zero
, size_needed
);
203 p
->brk_point
= new_brk
;
204 DPRINTF(SyscallVerbose
, "Break Point changed to: %#X\n", p
->brk_point
);
210 closeFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
213 int tgt_fd
= p
->getSyscallArg(tc
, index
);
215 int sim_fd
= p
->getSimFD(tgt_fd
);
221 status
= close(sim_fd
);
223 p
->resetFDEntry(tgt_fd
);
229 readFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
232 int tgt_fd
= p
->getSyscallArg(tc
, index
);
233 Addr bufPtr
= p
->getSyscallArg(tc
, index
);
234 int nbytes
= p
->getSyscallArg(tc
, index
);
235 BufferArg
bufArg(bufPtr
, nbytes
);
237 int sim_fd
= p
->getSimFD(tgt_fd
);
241 int bytes_read
= read(sim_fd
, bufArg
.bufferPtr(), nbytes
);
243 if (bytes_read
!= -1)
244 bufArg
.copyOut(tc
->getMemProxy());
250 writeFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
253 int tgt_fd
= p
->getSyscallArg(tc
, index
);
254 Addr bufPtr
= p
->getSyscallArg(tc
, index
);
255 int nbytes
= p
->getSyscallArg(tc
, index
);
256 BufferArg
bufArg(bufPtr
, nbytes
);
258 int sim_fd
= p
->getSimFD(tgt_fd
);
262 bufArg
.copyIn(tc
->getMemProxy());
264 int bytes_written
= write(sim_fd
, bufArg
.bufferPtr(), nbytes
);
268 return bytes_written
;
273 lseekFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
276 int tgt_fd
= p
->getSyscallArg(tc
, index
);
277 uint64_t offs
= p
->getSyscallArg(tc
, index
);
278 int whence
= p
->getSyscallArg(tc
, index
);
280 int sim_fd
= p
->getSimFD(tgt_fd
);
284 off_t result
= lseek(sim_fd
, offs
, whence
);
286 return (result
== (off_t
)-1) ? -errno
: result
;
291 _llseekFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
294 int tgt_fd
= p
->getSyscallArg(tc
, index
);
295 uint64_t offset_high
= p
->getSyscallArg(tc
, index
);
296 uint32_t offset_low
= p
->getSyscallArg(tc
, index
);
297 Addr result_ptr
= p
->getSyscallArg(tc
, index
);
298 int whence
= p
->getSyscallArg(tc
, index
);
300 int sim_fd
= p
->getSimFD(tgt_fd
);
304 uint64_t offset
= (offset_high
<< 32) | offset_low
;
306 uint64_t result
= lseek(sim_fd
, offset
, whence
);
307 result
= TheISA::htog(result
);
309 if (result
== (off_t
)-1) {
313 // The seek succeeded.
314 // Copy "result" to "result_ptr"
315 // XXX We'll assume that the size of loff_t is 64 bits on the
317 BufferArg
result_buf(result_ptr
, sizeof(result
));
318 memcpy(result_buf
.bufferPtr(), &result
, sizeof(result
));
319 result_buf
.copyOut(tc
->getMemProxy());
326 munmapFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
328 // given that we don't really implement mmap, munmap is really easy
333 const char *hostname
= "m5.eecs.umich.edu";
336 gethostnameFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
339 Addr bufPtr
= p
->getSyscallArg(tc
, index
);
340 int name_len
= p
->getSyscallArg(tc
, index
);
341 BufferArg
name(bufPtr
, name_len
);
343 strncpy((char *)name
.bufferPtr(), hostname
, name_len
);
345 name
.copyOut(tc
->getMemProxy());
351 getcwdFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
355 Addr bufPtr
= p
->getSyscallArg(tc
, index
);
356 unsigned long size
= p
->getSyscallArg(tc
, index
);
357 BufferArg
buf(bufPtr
, size
);
359 // Is current working directory defined?
360 string cwd
= p
->getcwd();
362 if (cwd
.length() >= size
) {
366 strncpy((char *)buf
.bufferPtr(), cwd
.c_str(), size
);
367 result
= cwd
.length();
369 if (getcwd((char *)buf
.bufferPtr(), size
) != NULL
) {
370 result
= strlen((char *)buf
.bufferPtr());
376 buf
.copyOut(tc
->getMemProxy());
378 return (result
== -1) ? -errno
: result
;
381 /// Target open() handler.
383 readlinkFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
386 return readlinkFunc(desc
, callnum
, process
, tc
, 0);
390 readlinkFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
,
395 if (!tc
->getMemProxy().tryReadString(path
, p
->getSyscallArg(tc
, index
)))
398 // Adjust path for current working directory
399 path
= p
->fullPath(path
);
401 Addr bufPtr
= p
->getSyscallArg(tc
, index
);
402 size_t bufsiz
= p
->getSyscallArg(tc
, index
);
404 BufferArg
buf(bufPtr
, bufsiz
);
407 if (path
!= "/proc/self/exe") {
408 result
= readlink(path
.c_str(), (char *)buf
.bufferPtr(), bufsiz
);
410 // Emulate readlink() called on '/proc/self/exe' should return the
411 // absolute path of the binary running in the simulated system (the
412 // LiveProcess' executable). It is possible that using this path in
413 // the simulated system will result in unexpected behavior if:
414 // 1) One binary runs another (e.g., -c time -o "my_binary"), and
415 // called binary calls readlink().
416 // 2) The host's full path to the running benchmark changes from one
417 // simulation to another. This can result in different simulated
418 // performance since the simulated system will process the binary
419 // path differently, even if the binary itself does not change.
421 // Get the absolute canonical path to the running application
422 char real_path
[PATH_MAX
];
423 char *check_real_path
= realpath(p
->progName(), real_path
);
424 if (!check_real_path
) {
425 fatal("readlink('/proc/self/exe') unable to resolve path to "
426 "executable: %s", p
->progName());
428 strncpy((char*)buf
.bufferPtr(), real_path
, bufsiz
);
429 size_t real_path_len
= strlen(real_path
);
430 if (real_path_len
> bufsiz
) {
431 // readlink will truncate the contents of the
432 // path to ensure it is no more than bufsiz
435 result
= real_path_len
;
438 // Issue a warning about potential unexpected results
439 warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
440 "results in various settings.\n Returning '%s'\n",
441 (char*)buf
.bufferPtr());
444 buf
.copyOut(tc
->getMemProxy());
446 return (result
== -1) ? -errno
: result
;
450 unlinkFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
452 return unlinkHelper(desc
, num
, p
, tc
, 0);
456 unlinkHelper(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
,
461 if (!tc
->getMemProxy().tryReadString(path
, p
->getSyscallArg(tc
, index
)))
464 // Adjust path for current working directory
465 path
= p
->fullPath(path
);
467 int result
= unlink(path
.c_str());
468 return (result
== -1) ? -errno
: result
;
473 mkdirFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
478 if (!tc
->getMemProxy().tryReadString(path
, p
->getSyscallArg(tc
, index
)))
481 // Adjust path for current working directory
482 path
= p
->fullPath(path
);
484 mode_t mode
= p
->getSyscallArg(tc
, index
);
486 int result
= mkdir(path
.c_str(), mode
);
487 return (result
== -1) ? -errno
: result
;
491 renameFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
496 if (!tc
->getMemProxy().tryReadString(old_name
, p
->getSyscallArg(tc
, index
)))
501 if (!tc
->getMemProxy().tryReadString(new_name
, p
->getSyscallArg(tc
, index
)))
504 // Adjust path for current working directory
505 old_name
= p
->fullPath(old_name
);
506 new_name
= p
->fullPath(new_name
);
508 int64_t result
= rename(old_name
.c_str(), new_name
.c_str());
509 return (result
== -1) ? -errno
: result
;
513 truncateFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
518 if (!tc
->getMemProxy().tryReadString(path
, p
->getSyscallArg(tc
, index
)))
521 off_t length
= p
->getSyscallArg(tc
, index
);
523 // Adjust path for current working directory
524 path
= p
->fullPath(path
);
526 int result
= truncate(path
.c_str(), length
);
527 return (result
== -1) ? -errno
: result
;
531 ftruncateFunc(SyscallDesc
*desc
, int num
,
532 LiveProcess
*process
, ThreadContext
*tc
)
535 int tgt_fd
= process
->getSyscallArg(tc
, index
);
536 off_t length
= process
->getSyscallArg(tc
, index
);
538 int sim_fd
= process
->getSimFD(tgt_fd
);
542 int result
= ftruncate(sim_fd
, length
);
543 return (result
== -1) ? -errno
: result
;
547 truncate64Func(SyscallDesc
*desc
, int num
,
548 LiveProcess
*process
, ThreadContext
*tc
)
553 if (!tc
->getMemProxy().tryReadString(path
, process
->getSyscallArg(tc
, index
)))
556 int64_t length
= process
->getSyscallArg(tc
, index
, 64);
558 // Adjust path for current working directory
559 path
= process
->fullPath(path
);
562 int result
= truncate(path
.c_str(), length
);
564 int result
= truncate64(path
.c_str(), length
);
566 return (result
== -1) ? -errno
: result
;
570 ftruncate64Func(SyscallDesc
*desc
, int num
,
571 LiveProcess
*process
, ThreadContext
*tc
)
574 int tgt_fd
= process
->getSyscallArg(tc
, index
);
575 int64_t length
= process
->getSyscallArg(tc
, index
, 64);
577 int sim_fd
= process
->getSimFD(tgt_fd
);
582 int result
= ftruncate(sim_fd
, length
);
584 int result
= ftruncate64(sim_fd
, length
);
586 return (result
== -1) ? -errno
: result
;
590 umaskFunc(SyscallDesc
*desc
, int num
, LiveProcess
*process
, ThreadContext
*tc
)
592 // Letting the simulated program change the simulator's umask seems like
593 // a bad idea. Compromise by just returning the current umask but not
594 // changing anything.
595 mode_t oldMask
= umask(0);
601 chownFunc(SyscallDesc
*desc
, int num
, LiveProcess
*p
, ThreadContext
*tc
)
606 if (!tc
->getMemProxy().tryReadString(path
, p
->getSyscallArg(tc
, index
)))
610 uint32_t owner
= p
->getSyscallArg(tc
, index
);
611 uid_t hostOwner
= owner
;
612 uint32_t group
= p
->getSyscallArg(tc
, index
);
613 gid_t hostGroup
= group
;
615 // Adjust path for current working directory
616 path
= p
->fullPath(path
);
618 int result
= chown(path
.c_str(), hostOwner
, hostGroup
);
619 return (result
== -1) ? -errno
: result
;
623 fchownFunc(SyscallDesc
*desc
, int num
, LiveProcess
*process
, ThreadContext
*tc
)
626 int tgt_fd
= process
->getSyscallArg(tc
, index
);
628 int sim_fd
= process
->getSimFD(tgt_fd
);
633 uint32_t owner
= process
->getSyscallArg(tc
, index
);
634 uid_t hostOwner
= owner
;
635 uint32_t group
= process
->getSyscallArg(tc
, index
);
636 gid_t hostGroup
= group
;
638 int result
= fchown(sim_fd
, hostOwner
, hostGroup
);
639 return (result
== -1) ? -errno
: result
;
644 dupFunc(SyscallDesc
*desc
, int num
, LiveProcess
*process
, ThreadContext
*tc
)
647 int tgt_fd
= process
->getSyscallArg(tc
, index
);
649 int sim_fd
= process
->getSimFD(tgt_fd
);
653 FDEntry
*fde
= process
->getFDEntry(tgt_fd
);
655 int result
= dup(sim_fd
);
656 return (result
== -1) ? -errno
:
657 process
->allocFD(result
, fde
->filename
, fde
->flags
, fde
->mode
, false);
662 fcntlFunc(SyscallDesc
*desc
, int num
, LiveProcess
*process
,
666 int tgt_fd
= process
->getSyscallArg(tc
, index
);
668 int sim_fd
= process
->getSimFD(tgt_fd
);
672 int cmd
= process
->getSyscallArg(tc
, index
);
675 // if we really wanted to support this, we'd need to do it
676 // in the target fd space.
677 warn("fcntl(%d, F_DUPFD) not supported, error returned\n", tgt_fd
);
680 case 1: // F_GETFD (get close-on-exec flag)
681 case 2: // F_SETFD (set close-on-exec flag)
684 case 3: // F_GETFL (get file flags)
685 case 4: // F_SETFL (set file flags)
686 // not sure if this is totally valid, but we'll pass it through
687 // to the underlying OS
688 warn("fcntl(%d, %d) passed through to host\n", tgt_fd
, cmd
);
689 return fcntl(sim_fd
, cmd
);
692 case 7: // F_GETLK (get lock)
693 case 8: // F_SETLK (set lock)
694 case 9: // F_SETLKW (set lock and wait)
695 // don't mess with file locking... just act like it's OK
696 warn("File lock call (fcntl(%d, %d)) ignored.\n", tgt_fd
, cmd
);
700 warn("Unknown fcntl command %d\n", cmd
);
706 fcntl64Func(SyscallDesc
*desc
, int num
, LiveProcess
*process
,
710 int tgt_fd
= process
->getSyscallArg(tc
, index
);
712 int sim_fd
= process
->getSimFD(tgt_fd
);
716 int cmd
= process
->getSyscallArg(tc
, index
);
719 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd
);
722 case 34: // F_SETLK64
723 case 35: // F_SETLKW64
724 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
729 // not sure if this is totally valid, but we'll pass it through
730 // to the underlying OS
731 warn("fcntl64(%d, %d) passed through to host\n", tgt_fd
, cmd
);
732 return fcntl(sim_fd
, cmd
);
738 pipePseudoFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
741 int fds
[2], sim_fds
[2];
742 int pipe_retval
= pipe(fds
);
744 if (pipe_retval
< 0) {
749 sim_fds
[0] = process
->allocFD(fds
[0], "PIPE-READ", O_WRONLY
, -1, true);
750 sim_fds
[1] = process
->allocFD(fds
[1], "PIPE-WRITE", O_RDONLY
, -1, true);
752 process
->setReadPipeSource(sim_fds
[0], sim_fds
[1]);
753 // Alpha Linux convention for pipe() is that fd[0] is returned as
754 // the return value of the function, and fd[1] is returned in r20.
755 tc
->setIntReg(SyscallPseudoReturnReg
, sim_fds
[1]);
761 getpidPseudoFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
764 // Make up a PID. There's no interprocess communication in
765 // fake_syscall mode, so there's no way for a process to know it's
766 // not getting a unique value.
768 tc
->setIntReg(SyscallPseudoReturnReg
, process
->ppid());
769 return process
->pid();
774 getuidPseudoFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
777 // Make up a UID and EUID... it shouldn't matter, and we want the
778 // simulation to be deterministic.
781 tc
->setIntReg(SyscallPseudoReturnReg
, process
->euid()); //EUID
782 return process
->uid(); // UID
787 getgidPseudoFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
790 // Get current group ID. EGID goes in r20.
791 tc
->setIntReg(SyscallPseudoReturnReg
, process
->egid()); //EGID
792 return process
->gid();
797 setuidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
800 // can't fathom why a benchmark would call this.
802 warn("Ignoring call to setuid(%d)\n", process
->getSyscallArg(tc
, index
));
807 getpidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
810 // Make up a PID. There's no interprocess communication in
811 // fake_syscall mode, so there's no way for a process to know it's
812 // not getting a unique value.
814 tc
->setIntReg(SyscallPseudoReturnReg
, process
->ppid()); //PID
815 return process
->pid();
819 getppidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
822 return process
->ppid();
826 getuidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
829 return process
->uid(); // UID
833 geteuidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
836 return process
->euid(); // UID
840 getgidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
843 return process
->gid();
847 getegidFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
850 return process
->egid();
855 cloneFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*process
,
859 IntReg flags
= process
->getSyscallArg(tc
, index
);
860 IntReg newStack
= process
->getSyscallArg(tc
, index
);
862 DPRINTF(SyscallVerbose
, "In sys_clone:\n");
863 DPRINTF(SyscallVerbose
, " Flags=%llx\n", flags
);
864 DPRINTF(SyscallVerbose
, " Child stack=%llx\n", newStack
);
867 if (flags
!= 0x10f00) {
868 warn("This sys_clone implementation assumes flags "
869 "CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD "
870 "(0x10f00), and may not work correctly with given flags "
874 ThreadContext
* ctc
; // child thread context
875 if ( ( ctc
= process
->findFreeContext() ) != NULL
) {
876 DPRINTF(SyscallVerbose
, " Found unallocated thread context\n");
878 ctc
->clearArchRegs();
880 // Arch-specific cloning code
881 #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA
882 // Cloning the misc. regs for these archs is enough
883 TheISA::copyMiscRegs(tc
, ctc
);
884 #elif THE_ISA == SPARC_ISA
885 TheISA::copyRegs(tc
, ctc
);
887 // TODO: Explain what this code actually does :-)
888 ctc
->setIntReg(NumIntArchRegs
+ 6, 0);
889 ctc
->setIntReg(NumIntArchRegs
+ 4, 0);
890 ctc
->setIntReg(NumIntArchRegs
+ 3, NWindows
- 2);
891 ctc
->setIntReg(NumIntArchRegs
+ 5, NWindows
);
892 ctc
->setMiscReg(MISCREG_CWP
, 0);
893 ctc
->setIntReg(NumIntArchRegs
+ 7, 0);
894 ctc
->setMiscRegNoEffect(MISCREG_TL
, 0);
895 ctc
->setMiscReg(MISCREG_ASI
, ASI_PRIMARY
);
897 for (int y
= 8; y
< 32; y
++)
898 ctc
->setIntReg(y
, tc
->readIntReg(y
));
899 #elif THE_ISA == ARM_ISA
900 TheISA::copyRegs(tc
, ctc
);
902 fatal("sys_clone is not implemented for this ISA\n");
905 // Set up stack register
906 ctc
->setIntReg(TheISA::StackPointerReg
, newStack
);
908 // Set up syscall return values in parent and child
909 ctc
->setIntReg(ReturnValueReg
, 0); // return value, child
911 // Alpha needs SyscallSuccessReg=0 in child
912 #if THE_ISA == ALPHA_ISA
913 ctc
->setIntReg(TheISA::SyscallSuccessReg
, 0);
916 // In SPARC/Linux, clone returns 0 on pseudo-return register if
917 // parent, non-zero if child
918 #if THE_ISA == SPARC_ISA
919 tc
->setIntReg(TheISA::SyscallPseudoReturnReg
, 0);
920 ctc
->setIntReg(TheISA::SyscallPseudoReturnReg
, 1);
923 ctc
->pcState(tc
->nextInstAddr());
927 // Should return nonzero child TID in parent's syscall return register,
928 // but for our pthread library any non-zero value will work
931 fatal("Called sys_clone, but no unallocated thread contexts found!\n");
937 accessFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*p
, ThreadContext
*tc
,
941 if (!tc
->getMemProxy().tryReadString(path
, p
->getSyscallArg(tc
, index
)))
944 // Adjust path for current working directory
945 path
= p
->fullPath(path
);
947 mode_t mode
= p
->getSyscallArg(tc
, index
);
949 int result
= access(path
.c_str(), mode
);
950 return (result
== -1) ? -errno
: result
;
954 accessFunc(SyscallDesc
*desc
, int callnum
, LiveProcess
*p
, ThreadContext
*tc
)
956 return accessFunc(desc
, callnum
, p
, tc
, 0);