2 * Copyright (c) 2003 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.
31 #include <sys/types.h>
33 #include <string.h> // for memset()
35 #include "sim/host.hh"
36 #include "cpu/base_cpu.hh"
37 #include "mem/functional_mem/functional_memory.hh"
38 #include "sim/prog.hh"
39 #include "cpu/exec_context.hh"
40 #include "sim/fake_syscall.hh"
41 #include "sim/sim_events.hh"
43 #include "targetarch/osf_syscalls.h"
44 #include "sim/universe.hh" // for curTick & ticksPerSecond
46 #include "base/trace.hh"
51 // System call descriptor
57 typedef int (*FuncPtr
)(SyscallDesc
*, int num
,
58 Process
*, ExecContext
*);
64 SyscallDesc(const char *_name
, FuncPtr _funcPtr
, int _flags
= 0)
65 : name(_name
), funcPtr(_funcPtr
), flags(_flags
)
68 int doFunc(int num
, Process
*proc
, ExecContext
*xc
) {
69 return (*funcPtr
)(this, num
, proc
, xc
);
78 BaseBufferArg(Addr _addr
, int _size
) : addr(_addr
), size(_size
) {
79 bufPtr
= new uint8_t[size
];
80 // clear out buffer: in case we only partially populate this,
81 // and then do a copyOut(), we want to make sure we don't
82 // introduce any random junk into the simulated address space
83 memset(bufPtr
, 0, size
);
86 virtual ~BaseBufferArg() { delete [] bufPtr
; }
89 // copy data into simulator space (read from target memory)
91 virtual bool copyIn(FunctionalMemory
*mem
) {
92 mem
->access(Read
, addr
, bufPtr
, size
);
93 return true; // no EFAULT detection for now
97 // copy data out of simulator space (write to target memory)
99 virtual bool copyOut(FunctionalMemory
*mem
) {
100 mem
->access(Write
, addr
, bufPtr
, size
);
101 return true; // no EFAULT detection for now
111 class BufferArg
: public BaseBufferArg
114 BufferArg(Addr _addr
, int _size
) : BaseBufferArg(_addr
, _size
) { }
115 void *bufferPtr() { return bufPtr
; }
119 class TypedBufferArg
: public BaseBufferArg
122 // user can optionally specify a specific number of bytes to
123 // allocate to deal with those structs that have variable-size
125 TypedBufferArg(Addr _addr
, int _size
= sizeof(T
))
126 : BaseBufferArg(_addr
, _size
)
130 operator T
*() { return (T
*)bufPtr
; }
132 // dereference operators
133 T
& operator*() { return *((T
*)bufPtr
); }
134 T
* operator->() { return (T
*)bufPtr
; }
135 T
& operator[](int i
) { return ((T
*)bufPtr
)[i
]; }
140 getArg(ExecContext
*xc
, int i
)
142 return xc
->regs
.intRegFile
[ArgumentReg0
+ i
];
147 // used to shift args for indirect syscall
150 setArg(ExecContext
*xc
, int i
, IntReg val
)
152 xc
->regs
.intRegFile
[ArgumentReg0
+ i
] = val
;
157 set_return_value(ExecContext
*xc
, IntReg return_value
)
159 // check for error condition. Alpha syscall convention is to
160 // indicate success/failure in reg a3 (r19) and put the
161 // return value itself in the standard return value reg (v0).
162 const int RegA3
= 19; // only place this is used
163 if (return_value
>= 0) {
165 xc
->regs
.intRegFile
[RegA3
] = 0;
166 xc
->regs
.intRegFile
[ReturnValueReg
] = return_value
;
168 // got an error, return details
169 xc
->regs
.intRegFile
[RegA3
] = (IntReg
) -1;
170 xc
->regs
.intRegFile
[ReturnValueReg
] = -return_value
;
176 getpagesizeFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
184 obreakFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
187 // change brk addr to first arg
188 process
->brk_point
= getArg(xc
, 0);
189 return process
->brk_point
;
194 ioctlFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
197 int fd
= process
->sim_fd(getArg(xc
, 0));
198 unsigned req
= getArg(xc
, 1);
201 case OSF::TIOCGETP
: {
202 // get tty parameters: the main use of this call is by
203 // isatty(), which really just wants to see whether it
204 // succeeds or returns ENOTTY to determine whether this is
205 // a terminal or not. This call is in turn used by the
206 // stdio library to determine whether to do line buffering
207 // or block buffering on a specific file descriptor.
208 TypedBufferArg
<OSF::sgttyb
> buf(getArg(xc
, 2));
211 // bad file descriptor
213 } else if (0 <= fd
< 3) {
214 // stdin/stdout/stderr: make it look like a terminal
215 // so we get line buffering & not block buffering
216 buf
->sg_ispeed
= 0xf;
217 buf
->sg_ospeed
= 0xf;
218 buf
->sg_erase
= 0x7f;
220 buf
->sg_flags
= 0x18;
221 buf
.copyOut(xc
->mem
);
224 // any other file descriptor: assume it's a file or
225 // pipe and not a terminal
231 case OSF::TIOCISATTY
:
233 // bad file descriptor
235 } else if (0 <= fd
< 3) {
236 // stdin/stdout/stderr: make it look like a terminal
237 // so we get line buffering & not block buffering
240 // any other file descriptor: assume it's a file or
241 // pipe and not a terminal
247 cerr
<< "Unsupported ioctl call: ioctl("
248 << fd
<< ", " << req
<< ", ...)" << endl
;
256 openFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
261 if (xc
->mem
->readString(path
, getArg(xc
, 0)) != No_Fault
)
264 if (path
== "/dev/sysdev0") {
265 // This is a memory-mapped high-resolution timer device on Alpha.
266 // We don't support it, so just punt.
267 DCOUT(SyscallWarnings
) << "Ignoring open(" << path
<< ", ...)" << endl
;
271 int osfFlags
= getArg(xc
, 1);
272 int mode
= getArg(xc
, 2);
275 // translate open flags
276 for (int i
= 0; i
< OSF::NUM_OPEN_FLAGS
; i
++) {
277 if (osfFlags
& OSF::openFlagTable
[i
].osfFlag
) {
278 osfFlags
&= ~OSF::openFlagTable
[i
].osfFlag
;
279 hostFlags
|= OSF::openFlagTable
[i
].hostFlag
;
283 // any target flags left?
285 cerr
<< "Syscall: open: cannot decode flags: " << osfFlags
<< endl
;
288 hostFlags
|= O_BINARY
;
292 int fd
= open(path
.c_str(), hostFlags
, mode
);
294 return (fd
== -1) ? -errno
: process
->open_fd(fd
);
299 closeFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
302 int fd
= process
->sim_fd(getArg(xc
, 0));
308 readFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
311 int fd
= process
->sim_fd(getArg(xc
, 0));
312 int nbytes
= getArg(xc
, 2);
313 BufferArg
bufArg(getArg(xc
, 1), nbytes
);
315 int bytes_read
= read(fd
, bufArg
.bufferPtr(), nbytes
);
317 if (bytes_read
!= -1)
318 bufArg
.copyOut(xc
->mem
);
324 writeFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
327 int fd
= process
->sim_fd(getArg(xc
, 0));
328 int nbytes
= getArg(xc
, 2);
329 BufferArg
bufArg(getArg(xc
, 1), nbytes
);
331 bufArg
.copyIn(xc
->mem
);
333 int bytes_written
= write(fd
, bufArg
.bufferPtr(), nbytes
);
337 return bytes_written
;
342 lseekFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
345 int fd
= process
->sim_fd(getArg(xc
, 0));
346 uint64_t offs
= getArg(xc
, 1);
347 int whence
= getArg(xc
, 2);
349 off_t result
= lseek(fd
, offs
, whence
);
351 return (result
== (off_t
)-1) ? -errno
: result
;
356 copyOutStatBuf(FunctionalMemory
*mem
, Addr addr
, struct stat
*host
)
358 TypedBufferArg
<OSF::F64_stat
> tgt(addr
);
360 tgt
->st_dev
= host
->st_dev
;
361 tgt
->st_ino
= host
->st_ino
;
362 tgt
->st_mode
= host
->st_mode
;
363 tgt
->st_nlink
= host
->st_nlink
;
364 tgt
->st_uid
= host
->st_uid
;
365 tgt
->st_gid
= host
->st_gid
;
366 tgt
->st_rdev
= host
->st_rdev
;
367 tgt
->st_size
= host
->st_size
;
368 tgt
->st_atimeX
= host
->st_atime
;
369 tgt
->st_mtimeX
= host
->st_mtime
;
370 tgt
->st_ctimeX
= host
->st_ctime
;
371 tgt
->st_blksize
= host
->st_blksize
;
372 tgt
->st_blocks
= host
->st_blocks
;
378 statFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
383 if (xc
->mem
->readString(path
, getArg(xc
, 0)) != No_Fault
)
387 int result
= stat(path
.c_str(), &hostBuf
);
392 copyOutStatBuf(xc
->mem
, getArg(xc
, 1), &hostBuf
);
399 lstatFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
404 if (xc
->mem
->readString(path
, getArg(xc
, 0)) != No_Fault
)
408 int result
= lstat(path
.c_str(), &hostBuf
);
413 copyOutStatBuf(xc
->mem
, getArg(xc
, 1), &hostBuf
);
419 fstatFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
422 int fd
= process
->sim_fd(getArg(xc
, 0));
428 int result
= fstat(fd
, &hostBuf
);
433 copyOutStatBuf(xc
->mem
, getArg(xc
, 1), &hostBuf
);
440 // We don't handle mmap(). If the target is really mmaping /dev/zero,
441 // we can get away with doing nothing (since the simulator doesn't
442 // really check addresses anyway). Always print a warning, since this
443 // could be seriously broken if we're not mapping /dev/zero.
445 // Someday we should explicitly check for /dev/zero in open, flag the
446 // file descriptor, and fail an mmap to anything else.
449 mmapFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
452 Addr start
= getArg(xc
, 0);
453 uint64_t length
= getArg(xc
, 1);
454 int prot
= getArg(xc
, 2);
455 int flags
= getArg(xc
, 3);
456 int fd
= process
->sim_fd(getArg(xc
, 4));
457 int offset
= getArg(xc
, 5);
459 cerr
<< "Warning: ignoring syscall mmap("
460 << start
<< ", " << length
<< ", "
461 << prot
<< ", " << flags
<< ", "
462 << fd
<< " " << getArg(xc
, 4) << ", "
463 << offset
<< ")" << endl
;
469 const char *hostname
= "m5.eecs.umich.edu";
472 unameFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
475 TypedBufferArg
<OSF::utsname
> name(getArg(xc
, 0));
477 strcpy(name
->sysname
, "OSF1");
478 strcpy(name
->nodename
, hostname
);
479 strcpy(name
->release
, "V5.1");
480 strcpy(name
->version
, "732");
481 strcpy(name
->machine
, "alpha");
483 name
.copyOut(xc
->mem
);
489 gethostnameFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
492 int name_len
= getArg(xc
, 1);
493 BufferArg
name(getArg(xc
, 0), name_len
);
495 strncpy((char *)name
.bufferPtr(), hostname
, name_len
);
497 name
.copyOut(xc
->mem
);
504 getsysinfoFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
507 unsigned op
= getArg(xc
, 0);
508 unsigned nbytes
= getArg(xc
, 2);
512 case OSF::GSI_MAX_CPU
: {
513 TypedBufferArg
<uint32_t> max_cpu(getArg(xc
, 1));
514 *max_cpu
= process
->numCpus();
515 max_cpu
.copyOut(xc
->mem
);
519 case OSF::GSI_CPUS_IN_BOX
: {
520 TypedBufferArg
<uint32_t> cpus_in_box(getArg(xc
, 1));
521 *cpus_in_box
= process
->numCpus();
522 cpus_in_box
.copyOut(xc
->mem
);
526 case OSF::GSI_PHYSMEM
: {
527 TypedBufferArg
<uint64_t> physmem(getArg(xc
, 1));
528 *physmem
= 1024 * 1024; // physical memory in KB
529 physmem
.copyOut(xc
->mem
);
533 case OSF::GSI_CPU_INFO
: {
534 TypedBufferArg
<OSF::cpu_info
> infop(getArg(xc
, 1));
536 infop
->current_cpu
= 0;
537 infop
->cpus_in_box
= process
->numCpus();
538 infop
->cpu_type
= 57;
539 infop
->ncpus
= process
->numCpus();
540 int cpumask
= (1 << process
->numCpus()) - 1;
541 infop
->cpus_present
= infop
->cpus_running
= cpumask
;
542 infop
->cpu_binding
= 0;
543 infop
->cpu_ex_binding
= 0;
546 infop
.copyOut(xc
->mem
);
550 case OSF::GSI_PROC_TYPE
: {
551 TypedBufferArg
<uint64_t> proc_type(getArg(xc
, 1));
553 proc_type
.copyOut(xc
->mem
);
557 case OSF::GSI_PLATFORM_NAME
: {
558 BufferArg
bufArg(getArg(xc
, 1), nbytes
);
559 strncpy((char *)bufArg
.bufferPtr(),
560 "COMPAQ Professional Workstation XP1000",
562 bufArg
.copyOut(xc
->mem
);
566 case OSF::GSI_CLK_TCK
: {
567 TypedBufferArg
<uint64_t> clk_hz(getArg(xc
, 1));
569 clk_hz
.copyOut(xc
->mem
);
574 cerr
<< "getsysinfo: unknown op " << op
<< endl
;
583 getpidFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
586 // Make up a PID. There's no interprocess communication in
587 // fake_syscall mode, so there's no way for a process to know it's
588 // not getting a unique value.
593 getuidFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
601 getrlimitFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
604 unsigned resource
= getArg(xc
, 0);
605 TypedBufferArg
<OSF::rlimit
> rlp(getArg(xc
, 1));
608 case OSF::RLIMIT_STACK
:
609 // max stack size in bytes: make up a number (2MB for now)
610 rlp
->rlim_cur
= rlp
->rlim_max
= 8 * 1024 * 1024;
614 cerr
<< "getrlimitFunc: unimplemented resource " << resource
<< endl
;
619 rlp
.copyOut(xc
->mem
);
623 // 1M usecs in 1 sec, for readability
624 static const int one_million
= 1000000;
626 // seconds since the epoch (1/1/1970)... about a billion, by my reckoning
627 static const unsigned seconds_since_epoch
= 1000000000;
630 // helper function: populate struct timeval with approximation of
631 // current elapsed time
634 getElapsedTime(OSF::timeval
*tp
)
636 int cycles_per_usec
= ticksPerSecond
/ one_million
;
638 int elapsed_usecs
= curTick
/ cycles_per_usec
;
639 tp
->tv_sec
= elapsed_usecs
/ one_million
;
640 tp
->tv_usec
= elapsed_usecs
% one_million
;
645 gettimeofdayFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
648 TypedBufferArg
<OSF::timeval
> tp(getArg(xc
, 0));
651 tp
->tv_sec
+= seconds_since_epoch
;
660 getrusageFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
663 int who
= getArg(xc
, 0); // THREAD, SELF, or CHILDREN
664 TypedBufferArg
<OSF::rusage
> rup(getArg(xc
, 1));
666 if (who
!= OSF::RUSAGE_SELF
) {
667 // don't really handle THREAD or CHILDREN, but just warn and
669 DCOUT(SyscallWarnings
)
670 << "Warning: getrusage() only supports RUSAGE_SELF."
671 << " Parameter " << who
<< " ignored." << endl
;
674 getElapsedTime(&rup
->ru_utime
);
675 rup
->ru_stime
.tv_sec
= 0;
676 rup
->ru_stime
.tv_usec
= 0;
688 rup
->ru_nsignals
= 0;
692 rup
.copyOut(xc
->mem
);
699 sigreturnFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
702 RegFile
*regs
= &xc
->regs
;
703 TypedBufferArg
<OSF::sigcontext
> sc(getArg(xc
, 0));
707 // restore state from sigcontext structure
708 regs
->pc
= sc
->sc_pc
;
709 regs
->npc
= regs
->pc
+ sizeof(MachInst
);
711 for (int i
= 0; i
< 31; ++i
) {
712 regs
->intRegFile
[i
] = sc
->sc_regs
[i
];
713 regs
->floatRegFile
.q
[i
] = sc
->sc_fpregs
[i
];
716 regs
->miscRegs
.fpcr
= sc
->sc_fpcr
;
722 tableFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
725 int id
= getArg(xc
, 0); // table ID
726 int index
= getArg(xc
, 1); // index into table
727 // arg 2 is buffer pointer; type depends on table ID
728 int nel
= getArg(xc
, 3); // number of elements
729 int lel
= getArg(xc
, 4); // expected element size
732 case OSF::TBL_SYSINFO
: {
733 if (index
!= 0 || nel
!= 1 || lel
!= sizeof(OSF::tbl_sysinfo
))
735 TypedBufferArg
<OSF::tbl_sysinfo
> elp(getArg(xc
, 2));
737 const int clk_hz
= one_million
;
738 elp
->si_user
= curTick
/ (ticksPerSecond
/ clk_hz
);
744 elp
->si_phz
= clk_hz
;
745 elp
->si_boottime
= seconds_since_epoch
; // seconds since epoch?
746 elp
->si_max_procs
= process
->numCpus();
747 elp
.copyOut(xc
->mem
);
752 cerr
<< "table(): id " << id
<< " unknown." << endl
;
758 // forward declaration... defined below table
761 indirectSyscallFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
765 // Handler for unimplemented syscalls that we haven't thought about.
768 unimplementedFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
771 cerr
<< "Error: syscall " << desc
->name
772 << " (#" << callnum
<< ") unimplemented.";
773 cerr
<< " Args: " << getArg(xc
, 0) << ", " << getArg(xc
, 1)
781 // Handler for unimplemented syscalls that we never intend to
782 // implement (signal handling, etc.) and should not affect the correct
783 // behavior of the program. Print a warning only if the appropriate
784 // trace flag is enabled. Return success to the target program.
787 ignoreFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
790 DCOUT(SyscallWarnings
) << "Warning: ignoring syscall " << desc
->name
791 << "(" << getArg(xc
, 0)
792 << ", " << getArg(xc
, 1)
800 exitFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
803 new SimExitEvent("syscall caused exit", getArg(xc
, 0) & 0xff);
809 SyscallDesc syscallDescs
[] = {
810 /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc
),
811 /* 1 */ SyscallDesc("exit", exitFunc
),
812 /* 2 */ SyscallDesc("fork", unimplementedFunc
),
813 /* 3 */ SyscallDesc("read", readFunc
),
814 /* 4 */ SyscallDesc("write", writeFunc
),
815 /* 5 */ SyscallDesc("old_open", unimplementedFunc
),
816 /* 6 */ SyscallDesc("close", closeFunc
),
817 /* 7 */ SyscallDesc("wait4", unimplementedFunc
),
818 /* 8 */ SyscallDesc("old_creat", unimplementedFunc
),
819 /* 9 */ SyscallDesc("link", unimplementedFunc
),
820 /* 10 */ SyscallDesc("unlink", unimplementedFunc
),
821 /* 11 */ SyscallDesc("execv", unimplementedFunc
),
822 /* 12 */ SyscallDesc("chdir", unimplementedFunc
),
823 /* 13 */ SyscallDesc("fchdir", unimplementedFunc
),
824 /* 14 */ SyscallDesc("mknod", unimplementedFunc
),
825 /* 15 */ SyscallDesc("chmod", unimplementedFunc
),
826 /* 16 */ SyscallDesc("chown", unimplementedFunc
),
827 /* 17 */ SyscallDesc("obreak", obreakFunc
),
828 /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc
),
829 /* 19 */ SyscallDesc("lseek", lseekFunc
),
830 /* 20 */ SyscallDesc("getpid", getpidFunc
),
831 /* 21 */ SyscallDesc("mount", unimplementedFunc
),
832 /* 22 */ SyscallDesc("unmount", unimplementedFunc
),
833 /* 23 */ SyscallDesc("setuid", unimplementedFunc
),
834 /* 24 */ SyscallDesc("getuid", getuidFunc
),
835 /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc
),
836 /* 26 */ SyscallDesc("ptrace", unimplementedFunc
),
837 /* 27 */ SyscallDesc("recvmsg", unimplementedFunc
),
838 /* 28 */ SyscallDesc("sendmsg", unimplementedFunc
),
839 /* 29 */ SyscallDesc("recvfrom", unimplementedFunc
),
840 /* 30 */ SyscallDesc("accept", unimplementedFunc
),
841 /* 31 */ SyscallDesc("getpeername", unimplementedFunc
),
842 /* 32 */ SyscallDesc("getsockname", unimplementedFunc
),
843 /* 33 */ SyscallDesc("access", unimplementedFunc
),
844 /* 34 */ SyscallDesc("chflags", unimplementedFunc
),
845 /* 35 */ SyscallDesc("fchflags", unimplementedFunc
),
846 /* 36 */ SyscallDesc("sync", unimplementedFunc
),
847 /* 37 */ SyscallDesc("kill", unimplementedFunc
),
848 /* 38 */ SyscallDesc("old_stat", unimplementedFunc
),
849 /* 39 */ SyscallDesc("setpgid", unimplementedFunc
),
850 /* 40 */ SyscallDesc("old_lstat", unimplementedFunc
),
851 /* 41 */ SyscallDesc("dup", unimplementedFunc
),
852 /* 42 */ SyscallDesc("pipe", unimplementedFunc
),
853 /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc
),
854 /* 44 */ SyscallDesc("profil", unimplementedFunc
),
855 /* 45 */ SyscallDesc("open", openFunc
),
856 /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc
),
857 /* 47 */ SyscallDesc("getgid", unimplementedFunc
),
858 /* 48 */ SyscallDesc("sigprocmask", ignoreFunc
),
859 /* 49 */ SyscallDesc("getlogin", unimplementedFunc
),
860 /* 50 */ SyscallDesc("setlogin", unimplementedFunc
),
861 /* 51 */ SyscallDesc("acct", unimplementedFunc
),
862 /* 52 */ SyscallDesc("sigpending", unimplementedFunc
),
863 /* 53 */ SyscallDesc("classcntl", unimplementedFunc
),
864 /* 54 */ SyscallDesc("ioctl", ioctlFunc
),
865 /* 55 */ SyscallDesc("reboot", unimplementedFunc
),
866 /* 56 */ SyscallDesc("revoke", unimplementedFunc
),
867 /* 57 */ SyscallDesc("symlink", unimplementedFunc
),
868 /* 58 */ SyscallDesc("readlink", unimplementedFunc
),
869 /* 59 */ SyscallDesc("execve", unimplementedFunc
),
870 /* 60 */ SyscallDesc("umask", unimplementedFunc
),
871 /* 61 */ SyscallDesc("chroot", unimplementedFunc
),
872 /* 62 */ SyscallDesc("old_fstat", unimplementedFunc
),
873 /* 63 */ SyscallDesc("getpgrp", unimplementedFunc
),
874 /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc
),
875 /* 65 */ SyscallDesc("mremap", unimplementedFunc
),
876 /* 66 */ SyscallDesc("vfork", unimplementedFunc
),
877 /* 67 */ SyscallDesc("pre_F64_stat", unimplementedFunc
),
878 /* 68 */ SyscallDesc("pre_F64_lstat", unimplementedFunc
),
879 /* 69 */ SyscallDesc("sbrk", unimplementedFunc
),
880 /* 70 */ SyscallDesc("sstk", unimplementedFunc
),
881 /* 71 */ SyscallDesc("mmap", mmapFunc
),
882 /* 72 */ SyscallDesc("ovadvise", unimplementedFunc
),
883 /* 73 */ SyscallDesc("munmap", unimplementedFunc
),
884 /* 74 */ SyscallDesc("mprotect", ignoreFunc
),
885 /* 75 */ SyscallDesc("madvise", unimplementedFunc
),
886 /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc
),
887 /* 77 */ SyscallDesc("kmodcall", unimplementedFunc
),
888 /* 78 */ SyscallDesc("mincore", unimplementedFunc
),
889 /* 79 */ SyscallDesc("getgroups", unimplementedFunc
),
890 /* 80 */ SyscallDesc("setgroups", unimplementedFunc
),
891 /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc
),
892 /* 82 */ SyscallDesc("setpgrp", unimplementedFunc
),
893 /* 83 */ SyscallDesc("setitimer", unimplementedFunc
),
894 /* 84 */ SyscallDesc("old_wait", unimplementedFunc
),
895 /* 85 */ SyscallDesc("table", tableFunc
),
896 /* 86 */ SyscallDesc("getitimer", unimplementedFunc
),
897 /* 87 */ SyscallDesc("gethostname", gethostnameFunc
),
898 /* 88 */ SyscallDesc("sethostname", unimplementedFunc
),
899 /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc
),
900 /* 90 */ SyscallDesc("dup2", unimplementedFunc
),
901 /* 91 */ SyscallDesc("pre_F64_fstat", unimplementedFunc
),
902 /* 92 */ SyscallDesc("fcntl", unimplementedFunc
),
903 /* 93 */ SyscallDesc("select", unimplementedFunc
),
904 /* 94 */ SyscallDesc("poll", unimplementedFunc
),
905 /* 95 */ SyscallDesc("fsync", unimplementedFunc
),
906 /* 96 */ SyscallDesc("setpriority", unimplementedFunc
),
907 /* 97 */ SyscallDesc("socket", unimplementedFunc
),
908 /* 98 */ SyscallDesc("connect", unimplementedFunc
),
909 /* 99 */ SyscallDesc("old_accept", unimplementedFunc
),
910 /* 100 */ SyscallDesc("getpriority", unimplementedFunc
),
911 /* 101 */ SyscallDesc("old_send", unimplementedFunc
),
912 /* 102 */ SyscallDesc("old_recv", unimplementedFunc
),
913 /* 103 */ SyscallDesc("sigreturn", sigreturnFunc
),
914 /* 104 */ SyscallDesc("bind", unimplementedFunc
),
915 /* 105 */ SyscallDesc("setsockopt", unimplementedFunc
),
916 /* 106 */ SyscallDesc("listen", unimplementedFunc
),
917 /* 107 */ SyscallDesc("plock", unimplementedFunc
),
918 /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc
),
919 /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc
),
920 /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc
),
921 /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc
),
922 /* 112 */ SyscallDesc("sigstack", ignoreFunc
),
923 /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc
),
924 /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc
),
925 /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc
),
926 /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc
),
927 /* 117 */ SyscallDesc("getrusage", getrusageFunc
),
928 /* 118 */ SyscallDesc("getsockopt", unimplementedFunc
),
929 /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc
),
930 /* 120 */ SyscallDesc("readv", unimplementedFunc
),
931 /* 121 */ SyscallDesc("writev", unimplementedFunc
),
932 /* 122 */ SyscallDesc("settimeofday", unimplementedFunc
),
933 /* 123 */ SyscallDesc("fchown", unimplementedFunc
),
934 /* 124 */ SyscallDesc("fchmod", unimplementedFunc
),
935 /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc
),
936 /* 126 */ SyscallDesc("setreuid", unimplementedFunc
),
937 /* 127 */ SyscallDesc("setregid", unimplementedFunc
),
938 /* 128 */ SyscallDesc("rename", unimplementedFunc
),
939 /* 129 */ SyscallDesc("truncate", unimplementedFunc
),
940 /* 130 */ SyscallDesc("ftruncate", unimplementedFunc
),
941 /* 131 */ SyscallDesc("flock", unimplementedFunc
),
942 /* 132 */ SyscallDesc("setgid", unimplementedFunc
),
943 /* 133 */ SyscallDesc("sendto", unimplementedFunc
),
944 /* 134 */ SyscallDesc("shutdown", unimplementedFunc
),
945 /* 135 */ SyscallDesc("socketpair", unimplementedFunc
),
946 /* 136 */ SyscallDesc("mkdir", unimplementedFunc
),
947 /* 137 */ SyscallDesc("rmdir", unimplementedFunc
),
948 /* 138 */ SyscallDesc("utimes", unimplementedFunc
),
949 /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc
),
950 /* 140 */ SyscallDesc("adjtime", unimplementedFunc
),
951 /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc
),
952 /* 142 */ SyscallDesc("gethostid", unimplementedFunc
),
953 /* 143 */ SyscallDesc("sethostid", unimplementedFunc
),
954 /* 144 */ SyscallDesc("getrlimit", getrlimitFunc
),
955 /* 145 */ SyscallDesc("setrlimit", unimplementedFunc
),
956 /* 146 */ SyscallDesc("old_killpg", unimplementedFunc
),
957 /* 147 */ SyscallDesc("setsid", unimplementedFunc
),
958 /* 148 */ SyscallDesc("quotactl", unimplementedFunc
),
959 /* 149 */ SyscallDesc("oldquota", unimplementedFunc
),
960 /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc
),
961 /* 151 */ SyscallDesc("pread", unimplementedFunc
),
962 /* 152 */ SyscallDesc("pwrite", unimplementedFunc
),
963 /* 153 */ SyscallDesc("pid_block", unimplementedFunc
),
964 /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc
),
965 /* 155 */ SyscallDesc("signal_urti", unimplementedFunc
),
966 /* 156 */ SyscallDesc("sigaction", ignoreFunc
),
967 /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc
),
968 /* 158 */ SyscallDesc("nfssvc", unimplementedFunc
),
969 /* 159 */ SyscallDesc("getdirentries", unimplementedFunc
),
970 /* 160 */ SyscallDesc("pre_F64_statfs", unimplementedFunc
),
971 /* 161 */ SyscallDesc("pre_F64_fstatfs", unimplementedFunc
),
972 /* 162 */ SyscallDesc("unknown #162", unimplementedFunc
),
973 /* 163 */ SyscallDesc("async_daemon", unimplementedFunc
),
974 /* 164 */ SyscallDesc("getfh", unimplementedFunc
),
975 /* 165 */ SyscallDesc("getdomainname", unimplementedFunc
),
976 /* 166 */ SyscallDesc("setdomainname", unimplementedFunc
),
977 /* 167 */ SyscallDesc("unknown #167", unimplementedFunc
),
978 /* 168 */ SyscallDesc("unknown #168", unimplementedFunc
),
979 /* 169 */ SyscallDesc("exportfs", unimplementedFunc
),
980 /* 170 */ SyscallDesc("unknown #170", unimplementedFunc
),
981 /* 171 */ SyscallDesc("unknown #171", unimplementedFunc
),
982 /* 172 */ SyscallDesc("unknown #172", unimplementedFunc
),
983 /* 173 */ SyscallDesc("unknown #173", unimplementedFunc
),
984 /* 174 */ SyscallDesc("unknown #174", unimplementedFunc
),
985 /* 175 */ SyscallDesc("unknown #175", unimplementedFunc
),
986 /* 176 */ SyscallDesc("unknown #176", unimplementedFunc
),
987 /* 177 */ SyscallDesc("unknown #177", unimplementedFunc
),
988 /* 178 */ SyscallDesc("unknown #178", unimplementedFunc
),
989 /* 179 */ SyscallDesc("unknown #179", unimplementedFunc
),
990 /* 180 */ SyscallDesc("unknown #180", unimplementedFunc
),
991 /* 181 */ SyscallDesc("alt_plock", unimplementedFunc
),
992 /* 182 */ SyscallDesc("unknown #182", unimplementedFunc
),
993 /* 183 */ SyscallDesc("unknown #183", unimplementedFunc
),
994 /* 184 */ SyscallDesc("getmnt", unimplementedFunc
),
995 /* 185 */ SyscallDesc("unknown #185", unimplementedFunc
),
996 /* 186 */ SyscallDesc("unknown #186", unimplementedFunc
),
997 /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc
),
998 /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc
),
999 /* 189 */ SyscallDesc("unknown #189", unimplementedFunc
),
1000 /* 190 */ SyscallDesc("unknown #190", unimplementedFunc
),
1001 /* 191 */ SyscallDesc("unknown #191", unimplementedFunc
),
1002 /* 192 */ SyscallDesc("unknown #192", unimplementedFunc
),
1003 /* 193 */ SyscallDesc("unknown #193", unimplementedFunc
),
1004 /* 194 */ SyscallDesc("unknown #194", unimplementedFunc
),
1005 /* 195 */ SyscallDesc("unknown #195", unimplementedFunc
),
1006 /* 196 */ SyscallDesc("unknown #196", unimplementedFunc
),
1007 /* 197 */ SyscallDesc("unknown #197", unimplementedFunc
),
1008 /* 198 */ SyscallDesc("unknown #198", unimplementedFunc
),
1009 /* 199 */ SyscallDesc("swapon", unimplementedFunc
),
1010 /* 200 */ SyscallDesc("msgctl", unimplementedFunc
),
1011 /* 201 */ SyscallDesc("msgget", unimplementedFunc
),
1012 /* 202 */ SyscallDesc("msgrcv", unimplementedFunc
),
1013 /* 203 */ SyscallDesc("msgsnd", unimplementedFunc
),
1014 /* 204 */ SyscallDesc("semctl", unimplementedFunc
),
1015 /* 205 */ SyscallDesc("semget", unimplementedFunc
),
1016 /* 206 */ SyscallDesc("semop", unimplementedFunc
),
1017 /* 207 */ SyscallDesc("uname", unameFunc
),
1018 /* 208 */ SyscallDesc("lchown", unimplementedFunc
),
1019 /* 209 */ SyscallDesc("shmat", unimplementedFunc
),
1020 /* 210 */ SyscallDesc("shmctl", unimplementedFunc
),
1021 /* 211 */ SyscallDesc("shmdt", unimplementedFunc
),
1022 /* 212 */ SyscallDesc("shmget", unimplementedFunc
),
1023 /* 213 */ SyscallDesc("mvalid", unimplementedFunc
),
1024 /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc
),
1025 /* 215 */ SyscallDesc("msleep", unimplementedFunc
),
1026 /* 216 */ SyscallDesc("mwakeup", unimplementedFunc
),
1027 /* 217 */ SyscallDesc("msync", unimplementedFunc
),
1028 /* 218 */ SyscallDesc("signal", unimplementedFunc
),
1029 /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc
),
1030 /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc
),
1031 /* 221 */ SyscallDesc("unknown #221", unimplementedFunc
),
1032 /* 222 */ SyscallDesc("security", unimplementedFunc
),
1033 /* 223 */ SyscallDesc("kloadcall", unimplementedFunc
),
1034 /* 224 */ SyscallDesc("stat", statFunc
),
1035 /* 225 */ SyscallDesc("lstat", lstatFunc
),
1036 /* 226 */ SyscallDesc("fstat", fstatFunc
),
1037 /* 227 */ SyscallDesc("statfs", unimplementedFunc
),
1038 /* 228 */ SyscallDesc("fstatfs", unimplementedFunc
),
1039 /* 229 */ SyscallDesc("getfsstat", unimplementedFunc
),
1040 /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc
),
1041 /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc
),
1042 /* 232 */ SyscallDesc("unknown #232", unimplementedFunc
),
1043 /* 233 */ SyscallDesc("getpgid", unimplementedFunc
),
1044 /* 234 */ SyscallDesc("getsid", unimplementedFunc
),
1045 /* 235 */ SyscallDesc("sigaltstack", ignoreFunc
),
1046 /* 236 */ SyscallDesc("waitid", unimplementedFunc
),
1047 /* 237 */ SyscallDesc("priocntlset", unimplementedFunc
),
1048 /* 238 */ SyscallDesc("sigsendset", unimplementedFunc
),
1049 /* 239 */ SyscallDesc("set_speculative", unimplementedFunc
),
1050 /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc
),
1051 /* 241 */ SyscallDesc("sysinfo", unimplementedFunc
),
1052 /* 242 */ SyscallDesc("uadmin", unimplementedFunc
),
1053 /* 243 */ SyscallDesc("fuser", unimplementedFunc
),
1054 /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc
),
1055 /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc
),
1056 /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc
),
1057 /* 247 */ SyscallDesc("pathconf", unimplementedFunc
),
1058 /* 248 */ SyscallDesc("fpathconf", unimplementedFunc
),
1059 /* 249 */ SyscallDesc("sync2", unimplementedFunc
),
1060 /* 250 */ SyscallDesc("uswitch", unimplementedFunc
),
1061 /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc
),
1062 /* 252 */ SyscallDesc("audcntl", unimplementedFunc
),
1063 /* 253 */ SyscallDesc("audgen", unimplementedFunc
),
1064 /* 254 */ SyscallDesc("sysfs", unimplementedFunc
),
1065 /* 255 */ SyscallDesc("subsys_info", unimplementedFunc
),
1066 /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc
),
1067 /* 257 */ SyscallDesc("setsysinfo", unimplementedFunc
),
1068 /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc
),
1069 /* 259 */ SyscallDesc("swapctl", unimplementedFunc
),
1070 /* 260 */ SyscallDesc("memcntl", unimplementedFunc
),
1071 /* 261 */ SyscallDesc("fdatasync", unimplementedFunc
),
1072 /* 262 */ SyscallDesc("oflock", unimplementedFunc
),
1073 /* 263 */ SyscallDesc("F64_readv", unimplementedFunc
),
1074 /* 264 */ SyscallDesc("F64_writev", unimplementedFunc
),
1075 /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc
),
1076 /* 266 */ SyscallDesc("sendfile", unimplementedFunc
),
1079 const int Num_Syscall_Descs
= sizeof(syscallDescs
) / sizeof(SyscallDesc
);
1081 const int Max_Syscall_Desc
= Num_Syscall_Descs
- 1;
1084 // Mach syscalls -- identified by negated syscall numbers
1087 // Create a stack region for a thread.
1089 stack_createFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1092 TypedBufferArg
<OSF::vm_stack
> argp(getArg(xc
, 0));
1094 argp
.copyIn(xc
->mem
);
1096 // if the user chose an address, just let them have it. Otherwise
1097 // pick one for them.
1098 if (argp
->address
== 0) {
1099 argp
->address
= process
->next_thread_stack_base
;
1100 int stack_size
= (argp
->rsize
+ argp
->ysize
+ argp
->gsize
);
1101 process
->next_thread_stack_base
-= stack_size
;
1102 argp
.copyOut(xc
->mem
);
1108 const int NXM_LIB_VERSION
= 301003;
1111 // This call sets up the interface between the user and kernel
1112 // schedulers by creating a shared-memory region. The shared memory
1113 // region has several structs, some global, some per-RAD, some per-VP.
1116 nxm_task_initFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1119 TypedBufferArg
<OSF::nxm_task_attr
> attrp(getArg(xc
, 0));
1120 TypedBufferArg
<Addr
> configptr_ptr(getArg(xc
, 1));
1122 attrp
.copyIn(xc
->mem
);
1124 if (attrp
->nxm_version
!= NXM_LIB_VERSION
) {
1125 cerr
<< "nxm_task_init: thread library version mismatch! "
1126 << "got " << attrp
->nxm_version
1127 << ", expected " << NXM_LIB_VERSION
<< endl
;
1131 if (attrp
->flags
!= OSF::NXM_TASK_INIT_VP
) {
1132 cerr
<< "nxm_task_init: bad flag value " << attrp
->flags
1133 << " (expected " << OSF::NXM_TASK_INIT_VP
<< ")" << endl
;
1137 const Addr base_addr
= 0x12000; // was 0x3f0000000LL;
1138 Addr cur_addr
= base_addr
; // next addresses to use
1139 // first comes the config_info struct
1140 Addr config_addr
= cur_addr
;
1141 cur_addr
+= sizeof(OSF::nxm_config_info
);
1142 // next comes the per-cpu state vector
1143 Addr slot_state_addr
= cur_addr
;
1144 int slot_state_size
= process
->numCpus() * sizeof(OSF::nxm_slot_state_t
);
1145 cur_addr
+= slot_state_size
;
1146 // now the per-RAD state struct (we only support one RAD)
1147 cur_addr
= 0x14000; // bump up addr for alignment
1148 Addr rad_state_addr
= cur_addr
;
1149 int rad_state_size
=
1150 (sizeof(OSF::nxm_shared
)
1151 + (process
->numCpus()-1) * sizeof(OSF::nxm_sched_state
));
1152 cur_addr
+= rad_state_size
;
1154 // now initialize a config_info struct and copy it out to user space
1155 TypedBufferArg
<OSF::nxm_config_info
> config(config_addr
);
1157 config
->nxm_nslots_per_rad
= process
->numCpus();
1158 config
->nxm_nrads
= 1; // only one RAD in our system!
1159 config
->nxm_slot_state
= slot_state_addr
;
1160 config
->nxm_rad
[0] = rad_state_addr
;
1162 config
.copyOut(xc
->mem
);
1164 // initialize the slot_state array and copy it out
1165 TypedBufferArg
<OSF::nxm_slot_state_t
> slot_state(slot_state_addr
,
1167 for (int i
= 0; i
< process
->numCpus(); ++i
) {
1168 // CPU 0 is bound to the calling process; all others are available
1169 slot_state
[i
] = (i
== 0) ? OSF::NXM_SLOT_BOUND
: OSF::NXM_SLOT_AVAIL
;
1172 slot_state
.copyOut(xc
->mem
);
1174 // same for the per-RAD "shared" struct. Note that we need to
1175 // allocate extra bytes for the per-VP array which is embedded at
1177 TypedBufferArg
<OSF::nxm_shared
> rad_state(rad_state_addr
,
1180 rad_state
->nxm_callback
= attrp
->nxm_callback
;
1181 rad_state
->nxm_version
= attrp
->nxm_version
;
1182 rad_state
->nxm_uniq_offset
= attrp
->nxm_uniq_offset
;
1183 for (int i
= 0; i
< process
->numCpus(); ++i
) {
1184 OSF::nxm_sched_state
*ssp
= &rad_state
->nxm_ss
[i
];
1185 ssp
->nxm_u
.sigmask
= 0;
1187 ssp
->nxm_u
.flags
= 0;
1188 ssp
->nxm_u
.cancel_state
= 0;
1189 ssp
->nxm_u
.nxm_ssig
= 0;
1191 ssp
->nxm_quantum
= attrp
->nxm_quantum
;
1192 ssp
->nxm_set_quantum
= attrp
->nxm_quantum
;
1193 ssp
->nxm_sysevent
= 0;
1196 uint64_t uniq
= xc
->regs
.miscRegs
.uniq
;
1197 ssp
->nxm_u
.pth_id
= uniq
+ attrp
->nxm_uniq_offset
;
1198 ssp
->nxm_u
.nxm_active
= uniq
| 1;
1201 ssp
->nxm_u
.pth_id
= 0;
1202 ssp
->nxm_u
.nxm_active
= 0;
1206 rad_state
.copyOut(xc
->mem
);
1209 // copy pointer to shared config area out to user
1211 *configptr_ptr
= config_addr
;
1212 configptr_ptr
.copyOut(xc
->mem
);
1219 init_exec_context(ExecContext
*ec
,
1220 OSF::nxm_thread_attr
*attrp
, uint64_t uniq_val
)
1222 memset(&ec
->regs
, 0, sizeof(ec
->regs
));
1224 ec
->regs
.intRegFile
[ArgumentReg0
] = attrp
->registers
.a0
;
1225 ec
->regs
.intRegFile
[27/*t12*/] = attrp
->registers
.pc
;
1226 ec
->regs
.intRegFile
[StackPointerReg
] = attrp
->registers
.sp
;
1227 ec
->regs
.miscRegs
.uniq
= uniq_val
;
1229 ec
->regs
.pc
= attrp
->registers
.pc
;
1230 ec
->regs
.npc
= attrp
->registers
.pc
+ sizeof(MachInst
);
1232 ec
->setStatus(ExecContext::Active
);
1236 nxm_thread_createFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1239 TypedBufferArg
<OSF::nxm_thread_attr
> attrp(getArg(xc
, 0));
1240 TypedBufferArg
<uint64_t> kidp(getArg(xc
, 1));
1241 int thread_index
= getArg(xc
, 2);
1243 // get attribute args
1244 attrp
.copyIn(xc
->mem
);
1246 if (attrp
->version
!= NXM_LIB_VERSION
) {
1247 cerr
<< "nxm_thread_create: thread library version mismatch! "
1248 << "got " << attrp
->version
1249 << ", expected " << NXM_LIB_VERSION
<< endl
;
1253 if (thread_index
< 0 | thread_index
> process
->numCpus()) {
1254 cerr
<< "nxm_thread_create: bad thread index " << thread_index
1259 // On a real machine, the per-RAD shared structure is in
1260 // shared memory, so both the user and kernel can get at it.
1261 // We don't have that luxury, so we just copy it in and then
1263 int rad_state_size
=
1264 (sizeof(OSF::nxm_shared
) +
1265 (process
->numCpus()-1) * sizeof(OSF::nxm_sched_state
));
1267 TypedBufferArg
<OSF::nxm_shared
> rad_state(0x14000,
1269 rad_state
.copyIn(xc
->mem
);
1271 uint64_t uniq_val
= attrp
->pthid
- rad_state
->nxm_uniq_offset
;
1273 if (attrp
->type
== OSF::NXM_TYPE_MANAGER
) {
1274 // DEC pthreads seems to always create one of these (in
1275 // addition to N application threads), but we don't use it,
1276 // so don't bother creating it.
1278 // This is supposed to be a port number. Make something up.
1280 kidp
.copyOut(xc
->mem
);
1283 } else if (attrp
->type
== OSF::NXM_TYPE_VP
) {
1284 // A real "virtual processor" kernel thread. Need to fork
1285 // this thread on another CPU.
1286 OSF::nxm_sched_state
*ssp
= &rad_state
->nxm_ss
[thread_index
];
1288 if (ssp
->nxm_u
.nxm_active
!= 0)
1289 return OSF::KERN_NOT_RECEIVER
;
1291 ssp
->nxm_u
.pth_id
= attrp
->pthid
;
1292 ssp
->nxm_u
.nxm_active
= uniq_val
| 1;
1294 rad_state
.copyOut(xc
->mem
);
1296 Addr slot_state_addr
= 0x12000 + sizeof(OSF::nxm_config_info
);
1297 int slot_state_size
= process
->numCpus() * sizeof(OSF::nxm_slot_state_t
);
1299 TypedBufferArg
<OSF::nxm_slot_state_t
> slot_state(slot_state_addr
,
1302 slot_state
.copyIn(xc
->mem
);
1304 if (slot_state
[thread_index
] != OSF::NXM_SLOT_AVAIL
) {
1305 cerr
<< "nxm_thread_createFunc: requested VP slot "
1306 << thread_index
<< " not available!" << endl
;
1310 slot_state
[thread_index
] = OSF::NXM_SLOT_BOUND
;
1312 slot_state
.copyOut(xc
->mem
);
1314 // Find a free simulator execution context.
1315 for (int i
= 0; i
< process
->numCpus(); ++i
) {
1316 ExecContext
*xc
= process
->execContexts
[i
];
1318 if (xc
->status() == ExecContext::Unallocated
) {
1319 // inactive context... grab it
1320 init_exec_context(xc
, attrp
, uniq_val
);
1322 // This is supposed to be a port number, but we'll try
1323 // and get away with just sticking the thread index
1325 *kidp
= thread_index
;
1326 kidp
.copyOut(xc
->mem
);
1332 // fell out of loop... no available inactive context
1333 cerr
<< "nxm_thread_create: no idle contexts available." << endl
;
1336 cerr
<< "nxm_thread_create: can't handle thread type "
1337 << attrp
->type
<< endl
;
1346 nxm_idleFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1353 nxm_thread_blockFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1356 uint64_t tid
= getArg(xc
, 0);
1357 uint64_t secs
= getArg(xc
, 1);
1358 uint64_t flags
= getArg(xc
, 2);
1359 uint64_t action
= getArg(xc
, 3);
1360 uint64_t usecs
= getArg(xc
, 4);
1362 cout
<< xc
->cpu
->name() << ": nxm_thread_block " << tid
<< " " << secs
1363 << " " << flags
<< " " << action
<< " " << usecs
<< endl
;
1370 nxm_blockFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1373 Addr uaddr
= getArg(xc
, 0);
1374 uint64_t val
= getArg(xc
, 1);
1375 uint64_t secs
= getArg(xc
, 2);
1376 uint64_t usecs
= getArg(xc
, 3);
1377 uint64_t flags
= getArg(xc
, 4);
1379 BaseCPU
*cpu
= xc
->cpu
;
1381 cout
<< cpu
->name() << ": nxm_block " << hex
<< uaddr
<< dec
<< " " << val
1382 << " " << secs
<< " " << usecs
1383 << " " << flags
<< endl
;
1390 nxm_unblockFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1393 Addr uaddr
= getArg(xc
, 0);
1395 cout
<< xc
->cpu
->name() << ": nxm_unblock "
1396 << hex
<< uaddr
<< dec
<< endl
;
1403 swtch_priFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1406 // Attempts to switch to another runnable thread (if there is
1407 // one). Returns false if there are no other threads to run
1408 // (i.e., the thread can reasonably spin-wait) or true if there
1409 // are other threads.
1411 // Since we assume at most one "kernel" thread per CPU, it's
1412 // always safe to return false here.
1417 // just activate one by default
1419 activate_waiting_context(Addr uaddr
, Process
*process
,
1420 bool activate_all
= false)
1422 int num_activated
= 0;
1424 list
<Process::WaitRec
>::iterator i
= process
->waitList
.begin();
1425 list
<Process::WaitRec
>::iterator end
= process
->waitList
.end();
1427 while (i
!= end
&& (num_activated
== 0 || activate_all
)) {
1428 if (i
->waitChan
== uaddr
) {
1429 // found waiting process: make it active
1430 ExecContext
*newCtx
= i
->waitingContext
;
1431 assert(newCtx
->status() == ExecContext::Suspended
);
1432 newCtx
->setStatus(ExecContext::Active
);
1434 // get rid of this record
1435 i
= process
->waitList
.erase(i
);
1443 return num_activated
;
1448 m5_lock_mutex(Addr uaddr
, Process
*process
, ExecContext
*xc
)
1450 TypedBufferArg
<uint64_t> lockp(uaddr
);
1452 lockp
.copyIn(xc
->mem
);
1455 // lock is free: grab it
1457 lockp
.copyOut(xc
->mem
);
1459 // lock is busy: disable until free
1460 process
->waitList
.push_back(Process::WaitRec(uaddr
, xc
));
1461 xc
->setStatus(ExecContext::Suspended
);
1466 m5_unlock_mutex(Addr uaddr
, Process
*process
, ExecContext
*xc
)
1468 TypedBufferArg
<uint64_t> lockp(uaddr
);
1470 lockp
.copyIn(xc
->mem
);
1471 assert(*lockp
!= 0);
1473 // Check for a process waiting on the lock.
1474 int num_waiting
= activate_waiting_context(uaddr
, process
);
1476 // clear lock field if no waiting context is taking over the lock
1477 if (num_waiting
== 0) {
1479 lockp
.copyOut(xc
->mem
);
1485 m5_mutex_lockFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1488 Addr uaddr
= getArg(xc
, 0);
1490 m5_lock_mutex(uaddr
, process
, xc
);
1492 // Return 0 since we will always return to the user with the lock
1493 // acquired. We will just keep the context inactive until that is
1500 m5_mutex_trylockFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1503 Addr uaddr
= getArg(xc
, 0);
1504 TypedBufferArg
<uint64_t> lockp(uaddr
);
1506 lockp
.copyIn(xc
->mem
);
1509 // lock is free: grab it
1511 lockp
.copyOut(xc
->mem
);
1520 m5_mutex_unlockFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1523 Addr uaddr
= getArg(xc
, 0);
1525 m5_unlock_mutex(uaddr
, process
, xc
);
1532 m5_cond_signalFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1535 Addr cond_addr
= getArg(xc
, 0);
1537 // Wqake up one process waiting on the condition variable.
1538 activate_waiting_context(cond_addr
, process
);
1545 m5_cond_broadcastFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1548 Addr cond_addr
= getArg(xc
, 0);
1550 // Wake up all processes waiting on the condition variable.
1551 activate_waiting_context(cond_addr
, process
, true);
1558 m5_cond_waitFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1561 Addr cond_addr
= getArg(xc
, 0);
1562 Addr lock_addr
= getArg(xc
, 1);
1563 TypedBufferArg
<uint64_t> condp(cond_addr
);
1564 TypedBufferArg
<uint64_t> lockp(lock_addr
);
1566 // user is supposed to acquire lock before entering
1567 lockp
.copyIn(xc
->mem
);
1568 assert(*lockp
!= 0);
1570 m5_unlock_mutex(lock_addr
, process
, xc
);
1572 process
->waitList
.push_back(Process::WaitRec(cond_addr
, xc
));
1573 xc
->setStatus(ExecContext::Suspended
);
1580 m5_thread_exitFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1583 assert(xc
->status() == ExecContext::Active
);
1584 xc
->setStatus(ExecContext::Unallocated
);
1590 SyscallDesc machSyscallDescs
[] = {
1591 /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1592 /* 1 */ SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc
),
1593 /* 2 */ SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc
),
1594 /* 3 */ SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc
),
1595 /* 4 */ SyscallDesc("m5_cond_signal", m5_cond_signalFunc
),
1596 /* 5 */ SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc
),
1597 /* 6 */ SyscallDesc("m5_cond_wait", m5_cond_waitFunc
),
1598 /* 7 */ SyscallDesc("m5_thread_exit", m5_thread_exitFunc
),
1599 /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1600 /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1601 /* 10 */ SyscallDesc("task_self", unimplementedFunc
),
1602 /* 11 */ SyscallDesc("thread_reply", unimplementedFunc
),
1603 /* 12 */ SyscallDesc("task_notify", unimplementedFunc
),
1604 /* 13 */ SyscallDesc("thread_self", unimplementedFunc
),
1605 /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1606 /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1607 /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1608 /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1609 /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1610 /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1611 /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc
),
1612 /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc
),
1613 /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc
),
1614 /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1615 /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc
),
1616 /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc
),
1617 /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1618 /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1619 /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1620 /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc
),
1621 /* 30 */ SyscallDesc("lw_wire", unimplementedFunc
),
1622 /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc
),
1623 /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc
),
1624 /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc
),
1625 /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1626 /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc
),
1627 /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc
),
1628 /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc
),
1629 /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc
),
1630 /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc
),
1631 /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc
),
1632 /* 41 */ SyscallDesc("init_process", unimplementedFunc
),
1633 /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc
),
1634 /* 43 */ SyscallDesc("map_fd", unimplementedFunc
),
1635 /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc
),
1636 /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc
),
1637 /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc
),
1638 /* 47 */ SyscallDesc("stack_create", stack_createFunc
),
1639 /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc
),
1640 /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc
),
1641 /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc
),
1642 /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc
),
1643 /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc
),
1644 /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1645 /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1646 /* 55 */ SyscallDesc("host_self", unimplementedFunc
),
1647 /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc
),
1648 /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1649 /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1650 /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc
),
1651 /* 60 */ SyscallDesc("swtch", unimplementedFunc
),
1652 /* 61 */ SyscallDesc("thread_switch", unimplementedFunc
),
1653 /* 62 */ SyscallDesc("semop_fast", unimplementedFunc
),
1654 /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc
),
1655 /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc
),
1656 /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc
),
1657 /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc
),
1658 /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc
),
1659 /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc
),
1660 /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc
),
1661 /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc
),
1662 /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc
),
1663 /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc
),
1664 /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc
),
1665 /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc
),
1666 /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc
),
1667 /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc
),
1668 /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc
),
1669 /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc
),
1670 /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc
),
1671 /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc
),
1672 /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc
),
1673 /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc
)
1676 const int Num_Mach_Syscall_Descs
=
1677 sizeof(machSyscallDescs
) / sizeof(SyscallDesc
);
1679 const int Max_Mach_Syscall_Desc
= Num_Mach_Syscall_Descs
- 1;
1681 // Since negated values are used to identify Mach syscalls, the
1682 // minimum (signed) valid syscall number is the negated max Mach
1684 const int Min_Syscall_Desc
= -Max_Mach_Syscall_Desc
;
1688 // helper function for invoking syscalls
1692 doSyscall(int callnum
, Process
*process
,
1695 if (callnum
< Min_Syscall_Desc
|| callnum
> Max_Syscall_Desc
) {
1696 cerr
<< "Syscall " << callnum
<< " out of range" << endl
;
1701 (callnum
< 0) ? &machSyscallDescs
[-callnum
] : &syscallDescs
[callnum
];
1703 DCOUT(SyscallVerbose
) << xc
->cpu
->name() << ": syscall " << desc
->name
1704 << " called @ " << curTick
<< endl
;
1706 return desc
->doFunc(callnum
, process
, xc
);
1710 // Indirect syscall invocation (call #0)
1713 indirectSyscallFunc(SyscallDesc
*desc
, int callnum
, Process
*process
,
1716 int new_callnum
= getArg(xc
, 0);
1718 for (int i
= 0; i
< 5; ++i
)
1719 setArg(xc
, i
, getArg(xc
, i
+1));
1721 return doSyscall(new_callnum
, process
, xc
);
1726 fake_syscall(Process
*process
, ExecContext
*xc
)
1728 int64_t callnum
= xc
->regs
.intRegFile
[ReturnValueReg
];
1730 int retval
= doSyscall(callnum
, process
, xc
);
1732 set_return_value(xc
, retval
);