summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Sanchez <sanchezd@stanford.edu>2009-04-21 08:17:36 -0700
committerDaniel Sanchez <sanchezd@stanford.edu>2009-04-21 08:17:36 -0700
commitb0e9654f8621729400ba627ed8c9bd0bf3833f7a (patch)
tree9d2131b1d6cfd177878b06595735627da7797527 /src
parentb0489d18ed74b542e311a2a7238cd5e19bd4b2ab (diff)
downloadgem5-b0e9654f8621729400ba627ed8c9bd0bf3833f7a.tar.xz
Commit m5threads package.
This patch adds limited multithreading support in syscall-emulation mode, by using the clone system call. The clone system call works for Alpha, SPARC and x86, and multithreaded applications run correctly in Alpha and SPARC.
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/linux/process.cc4
-rw-r--r--src/arch/sparc/linux/syscalls.cc24
-rw-r--r--src/arch/sparc/regfile.cc29
-rw-r--r--src/arch/x86/linux/syscalls.cc8
-rw-r--r--src/arch/x86/regfile.cc12
-rw-r--r--src/sim/syscall_emul.cc91
-rw-r--r--src/sim/syscall_emul.hh13
7 files changed, 156 insertions, 25 deletions
diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc
index aeff9fbed..9886c7ea7 100644
--- a/src/arch/alpha/linux/process.cc
+++ b/src/arch/alpha/linux/process.cc
@@ -434,7 +434,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
/* 310 */ SyscallDesc("syslog", unimplementedFunc),
/* 311 */ SyscallDesc("reboot", unimplementedFunc),
- /* 312 */ SyscallDesc("clone", unimplementedFunc),
+ /* 312 */ SyscallDesc("clone", cloneFunc),
/* 313 */ SyscallDesc("uselib", unimplementedFunc),
/* 314 */ SyscallDesc("mlock", unimplementedFunc),
/* 315 */ SyscallDesc("munlock", unimplementedFunc),
@@ -527,7 +527,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 402 */ SyscallDesc("io_cancel", unimplementedFunc),
/* 403 */ SyscallDesc("unknown #403", unimplementedFunc),
/* 404 */ SyscallDesc("unknown #404", unimplementedFunc),
- /* 405 */ SyscallDesc("exit_group", exitFunc), // exit all threads...
+ /* 405 */ SyscallDesc("exit_group", exitGroupFunc), // exit all threads...
/* 406 */ SyscallDesc("lookup_dcookie", unimplementedFunc),
/* 407 */ SyscallDesc("sys_epoll_create", unimplementedFunc),
/* 408 */ SyscallDesc("sys_epoll_ctl", unimplementedFunc),
diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc
index d9651c85c..f4781d886 100644
--- a/src/arch/sparc/linux/syscalls.cc
+++ b/src/arch/sparc/linux/syscalls.cc
@@ -162,7 +162,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
/* 71 */ SyscallDesc("mmap", mmapFunc<Sparc32Linux>),
/* 72 */ SyscallDesc("setreuid32", unimplementedFunc),
/* 73 */ SyscallDesc("munmap", munmapFunc),
- /* 74 */ SyscallDesc("mprotect", unimplementedFunc),
+ /* 74 */ SyscallDesc("mprotect", ignoreFunc),
/* 75 */ SyscallDesc("madvise", unimplementedFunc),
/* 76 */ SyscallDesc("vhangup", unimplementedFunc),
/* 77 */ SyscallDesc("truncate64", unimplementedFunc), //32 bit
@@ -191,20 +191,20 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
/* 100 */ SyscallDesc("getpriority", unimplementedFunc), //32 bit
/* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), //32 bit
/* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), //32 bit
- /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), //32 bit
+ /* 103 */ SyscallDesc("rt_sigprocmask", ignoreFunc), //32 bit
/* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), //32 bit
/* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
/* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), //32 bit
/* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
/* 108 */ SyscallDesc("setresuid32", unimplementedFunc),
/* 109 */ SyscallDesc("getresuid32", getresuidFunc),
- /* 110 */ SyscallDesc("setresgid32", unimplementedFunc),
+ /* 110 */ SyscallDesc("setresgid32", ignoreFunc),
/* 111 */ SyscallDesc("getresgid32", unimplementedFunc),
/* 112 */ SyscallDesc("setregid32", unimplementedFunc),
/* 113 */ SyscallDesc("revcmsg", unimplementedFunc),
/* 114 */ SyscallDesc("sendmsg", unimplementedFunc),
/* 115 */ SyscallDesc("getgroups32", unimplementedFunc), //32 bit
- /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), //32 bit
+ /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Sparc32Linux>), //32 bit
/* 117 */ SyscallDesc("getrusage", unimplementedFunc), //32 bit
/* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
/* 119 */ SyscallDesc("getcwd", getcwdFunc),
@@ -276,7 +276,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
/* 185 */ SyscallDesc("setpgid", unimplementedFunc), //32 bit
/* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), //32 bit
/* 187 */ SyscallDesc("tkill", unimplementedFunc), //32 bit
- /* 188 */ SyscallDesc("exit_group", exitFunc), //32 bit
+ /* 188 */ SyscallDesc("exit_group", exitGroupFunc), //32 bit
/* 189 */ SyscallDesc("uname", unameFunc),
/* 190 */ SyscallDesc("init_module", unimplementedFunc), //32 bit
/* 191 */ SyscallDesc("personality", unimplementedFunc),
@@ -305,7 +305,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
/* 214 */ SyscallDesc("sysinfo", unimplementedFunc), //32 bit
/* 215 */ SyscallDesc("ipc", unimplementedFunc), //32 bit
/* 216 */ SyscallDesc("sigreturn", unimplementedFunc), //32 bit
- /* 217 */ SyscallDesc("clone", unimplementedFunc),
+ /* 217 */ SyscallDesc("clone", cloneFunc),
/* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), //32 bit
/* 219 */ SyscallDesc("adjtimex", unimplementedFunc), //32 bit
/* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), //32 bit
@@ -468,7 +468,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>),
/* 72 */ SyscallDesc("setreuid32", unimplementedFunc),
/* 73 */ SyscallDesc("munmap", munmapFunc),
- /* 74 */ SyscallDesc("mprotect", unimplementedFunc),
+ /* 74 */ SyscallDesc("mprotect", ignoreFunc),
/* 75 */ SyscallDesc("madvise", unimplementedFunc),
/* 76 */ SyscallDesc("vhangup", unimplementedFunc),
/* 77 */ SyscallDesc("truncate64", unimplementedFunc),
@@ -497,20 +497,20 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 100 */ SyscallDesc("getpriority", unimplementedFunc),
/* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
/* 102 */ SyscallDesc("rt_sigaction", ignoreFunc),
- /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
+ /* 103 */ SyscallDesc("rt_sigprocmask", ignoreFunc),
/* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc),
/* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
/* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
/* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
/* 108 */ SyscallDesc("setresuid", unimplementedFunc),
/* 109 */ SyscallDesc("getresuid", getresuidFunc),
- /* 110 */ SyscallDesc("setresgid", unimplementedFunc),
+ /* 110 */ SyscallDesc("setresgid", ignoreFunc),
/* 111 */ SyscallDesc("getresgid", unimplementedFunc),
/* 112 */ SyscallDesc("setregid32", unimplementedFunc),
/* 113 */ SyscallDesc("recvmsg", unimplementedFunc),
/* 114 */ SyscallDesc("sendmsg", unimplementedFunc),
/* 115 */ SyscallDesc("getgroups32", unimplementedFunc),
- /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc),
+ /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<SparcLinux>),
/* 117 */ SyscallDesc("getrusage", unimplementedFunc),
/* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
/* 119 */ SyscallDesc("getcwd", unimplementedFunc),
@@ -582,7 +582,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 185 */ SyscallDesc("setpgid", unimplementedFunc),
/* 186 */ SyscallDesc("fremovexattr", unimplementedFunc),
/* 187 */ SyscallDesc("tkill", unimplementedFunc),
- /* 188 */ SyscallDesc("exit_group", exitFunc),
+ /* 188 */ SyscallDesc("exit_group", exitGroupFunc),
/* 189 */ SyscallDesc("uname", unameFunc),
/* 190 */ SyscallDesc("init_module", unimplementedFunc),
/* 191 */ SyscallDesc("personality", unimplementedFunc),
@@ -611,7 +611,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 214 */ SyscallDesc("sysinfo", unimplementedFunc),
/* 215 */ SyscallDesc("ipc", unimplementedFunc),
/* 216 */ SyscallDesc("sigreturn", unimplementedFunc),
- /* 217 */ SyscallDesc("clone", unimplementedFunc),
+ /* 217 */ SyscallDesc("clone", cloneFunc),
/* 218 */ SyscallDesc("ioprio_get", unimplementedFunc),
/* 219 */ SyscallDesc("adjtimex", unimplementedFunc),
/* 220 */ SyscallDesc("sigprocmask", unimplementedFunc),
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
index 1c172a4d5..4efac3d4e 100644
--- a/src/arch/sparc/regfile.cc
+++ b/src/arch/sparc/regfile.cc
@@ -352,10 +352,31 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest)
{
- // First loop through the integer registers.
- for (int i = 0; i < SparcISA::NumIntRegs; ++i) {
- dest->setIntReg(i, src->readIntReg(i));
+ //First loop through the integer registers.
+ int old_gl = src->readMiscRegNoEffect(MISCREG_GL);
+ int old_cwp = src->readMiscRegNoEffect(MISCREG_CWP);
+ //Globals
+ for (int x = 0; x < MaxGL; ++x) {
+ src->setMiscRegNoEffect(MISCREG_GL, x);
+ dest->setMiscRegNoEffect(MISCREG_GL, x);
+ for (int y = 0; y < 8; y++)
+ dest->setIntReg(y, src->readIntReg(y));
}
+ //Locals/Ins/Outs
+ for (int x = 0; x < NWindows; ++x) {
+ src->setMiscRegNoEffect(MISCREG_CWP, x);
+ dest->setMiscRegNoEffect(MISCREG_CWP, x);
+ for (int y = 8; y < 32; y++)
+ dest->setIntReg(y, src->readIntReg(y));
+ }
+ //MicroIntRegs
+ for (int y = 0; y < NumMicroIntRegs; ++y)
+ dest->setIntReg(y+32, src->readIntReg(y+32));
+
+ //Restore src's GL, CWP
+ src->setMiscRegNoEffect(MISCREG_GL, old_gl);
+ src->setMiscRegNoEffect(MISCREG_CWP, old_cwp);
+
// Then loop through the floating point registers.
for (int i = 0; i < SparcISA::NumFloatRegs; ++i) {
@@ -365,8 +386,10 @@ void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest)
// Copy misc. registers
copyMiscRegs(src, dest);
+
// Lastly copy PC/NPC
dest->setPC(src->readPC());
dest->setNextPC(src->readNextPC());
dest->setNextNPC(src->readNextNPC());
}
+
diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc
index 49a7d8b77..4d7bca95c 100644
--- a/src/arch/x86/linux/syscalls.cc
+++ b/src/arch/x86/linux/syscalls.cc
@@ -267,7 +267,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
/* 36 */ SyscallDesc("getitimer", unimplementedFunc),
/* 37 */ SyscallDesc("alarm", unimplementedFunc),
/* 38 */ SyscallDesc("setitimer", unimplementedFunc),
- /* 39 */ SyscallDesc("getpid", unimplementedFunc),
+ /* 39 */ SyscallDesc("getpid", getpidFunc),
/* 40 */ SyscallDesc("sendfile", unimplementedFunc),
/* 41 */ SyscallDesc("socket", unimplementedFunc),
/* 42 */ SyscallDesc("connect", unimplementedFunc),
@@ -284,7 +284,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
/* 53 */ SyscallDesc("socketpair", unimplementedFunc),
/* 54 */ SyscallDesc("setsockopt", unimplementedFunc),
/* 55 */ SyscallDesc("getsockopt", unimplementedFunc),
- /* 56 */ SyscallDesc("clone", unimplementedFunc),
+ /* 56 */ SyscallDesc("clone", cloneFunc),
/* 57 */ SyscallDesc("fork", unimplementedFunc),
/* 58 */ SyscallDesc("vfork", unimplementedFunc),
/* 59 */ SyscallDesc("execve", unimplementedFunc),
@@ -430,7 +430,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
/* 199 */ SyscallDesc("fremovexattr", unimplementedFunc),
/* 200 */ SyscallDesc("tkill", unimplementedFunc),
/* 201 */ SyscallDesc("time", unimplementedFunc),
- /* 202 */ SyscallDesc("futex", unimplementedFunc),
+ /* 202 */ SyscallDesc("futex", ignoreFunc),
/* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
/* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
/* 205 */ SyscallDesc("set_thread_area", unimplementedFunc),
@@ -459,7 +459,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
/* 228 */ SyscallDesc("clock_gettime", unimplementedFunc),
/* 229 */ SyscallDesc("clock_getres", unimplementedFunc),
/* 230 */ SyscallDesc("clock_nanosleep", unimplementedFunc),
- /* 231 */ SyscallDesc("exit_group", exitFunc),
+ /* 231 */ SyscallDesc("exit_group", exitGroupFunc),
/* 232 */ SyscallDesc("epoll_wait", unimplementedFunc),
/* 233 */ SyscallDesc("epoll_ctl", unimplementedFunc),
/* 234 */ SyscallDesc("tgkill", unimplementedFunc),
diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc
index 7d01c4bb4..83279902e 100644
--- a/src/arch/x86/regfile.cc
+++ b/src/arch/x86/regfile.cc
@@ -250,7 +250,17 @@ RegFile::unserialize(EventManager *em, Checkpoint *cp, const string &section)
void X86ISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
- panic("copyMiscRegs not implemented for x86!\n");
+ //panic("copyMiscRegs not implemented for x86!\n");
+ warn("copyMiscRegs is naively implemented for x86\n");
+ for (int i = 0; i < X86ISA::NumMiscRegs; ++i) {
+ if ( ( i != MISCREG_CR1 &&
+ !(i > MISCREG_CR4 && i < MISCREG_CR8) &&
+ !(i > MISCREG_CR8 && i <= MISCREG_CR15) ) == false) {
+ continue;
+ }
+ dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
+ }
+
}
void X86ISA::copyRegs(ThreadContext *src, ThreadContext *dest)
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index f0a693db0..d3161de26 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -106,6 +106,19 @@ exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
SyscallReturn
+exitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ // really should just halt all thread contexts belonging to this
+ // process in case there's another process running...
+ exitSimLoop("target called exit()",
+ process->getSyscallArg(tc, 0) & 0xff);
+
+ return 1;
+}
+
+
+SyscallReturn
getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
return (int)VMPageSize;
@@ -641,3 +654,81 @@ getegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
+SyscallReturn
+cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ DPRINTF(SyscallVerbose, "In sys_clone:\n");
+ DPRINTF(SyscallVerbose, " Flags=%llx\n", tc->getSyscallArg(0));
+ DPRINTF(SyscallVerbose, " Child stack=%llx\n", tc->getSyscallArg(1));
+
+
+ if (tc->getSyscallArg(0) != 0x10f00) {
+ warn("This sys_clone implementation assumes flags CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD (0x10f00), and may not work correctly with given flags 0x%llx\n", tc->getSyscallArg(0));
+ }
+
+ ThreadContext* ctc; //child thread context
+ if ( ( ctc = process->findFreeContext() ) != NULL ) {
+ DPRINTF(SyscallVerbose, " Found unallocated thread context\n");
+
+ ctc->clearArchRegs();
+
+ //Arch-specific cloning code
+ #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA
+ //Cloning the misc. regs for these archs is enough
+ TheISA::copyMiscRegs(tc, ctc);
+ #elif THE_ISA == SPARC_ISA
+ TheISA::copyRegs(tc, ctc);
+
+ //TODO: Explain what this code actually does :-)
+ ctc->setIntReg(NumIntArchRegs + 6, 0);
+ ctc->setIntReg(NumIntArchRegs + 4, 0);
+ ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2);
+ ctc->setIntReg(NumIntArchRegs + 5, NWindows);
+ ctc->setMiscRegNoEffect(MISCREG_CWP, 0);
+ ctc->setIntReg(NumIntArchRegs + 7, 0);
+ ctc->setMiscRegNoEffect(MISCREG_TL, 0);
+ ctc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
+
+ for (int y = 8; y < 32; y++)
+ ctc->setIntReg(y, tc->readIntReg(y));
+ #else
+ fatal("sys_clone is not implemented for this ISA\n");
+ #endif
+
+ //Set up stack register
+ ctc->setIntReg(TheISA::StackPointerReg, tc->getSyscallArg(1));
+
+ //Set up syscall return values in parent and child
+ ctc->setIntReg(ReturnValueReg, 0); //return value, child
+
+ //Alpha needs SyscallSuccessReg=0 in child
+ #if THE_ISA == ALPHA_ISA
+ ctc->setIntReg(SyscallSuccessReg, 0);
+ #endif
+
+ //In SPARC/Linux, clone returns 0 on pseudo-return register if parent, non-zero if child
+ #if THE_ISA == SPARC_ISA
+ tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0);
+ ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1);
+ #endif
+
+ ctc->setPC(tc->readNextPC());
+ ctc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+
+ //In SPARC, need NNPC too...
+ #if THE_ISA == SPARC_ISA
+ ctc->setNextNPC(tc->readNextNPC() + sizeof(TheISA::MachInst));
+ #endif
+
+ ctc->activate();
+
+ // Should return nonzero child TID in parent's syscall return register,
+ // but for our pthread library any non-zero value will work
+ return 1;
+ } else {
+ fatal("Called sys_clone, but no unallocated thread contexts found!\n");
+ return 0;
+ }
+}
+
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 0b0e73692..e995bd487 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -183,10 +183,14 @@ SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
-/// Target exit() handler: terminate simulation.
+/// Target exit() handler: terminate current context.
SyscallReturn exitFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
+/// Target exit_group() handler: terminate simulation. (exit all threads)
+SyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
+
/// Target getpagesize() handler.
SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
@@ -308,6 +312,9 @@ SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
SyscallReturn getegidFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
+/// Target clone() handler.
+SyscallReturn cloneFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
/// Pseudo Funcs - These functions use a different return convension,
@@ -1013,8 +1020,8 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
getElapsedTime(tp->tv_sec, tp->tv_usec);
tp->tv_sec += seconds_since_epoch;
- tp->tv_sec = htog(tp->tv_sec);
- tp->tv_usec = htog(tp->tv_usec);
+ tp->tv_sec = TheISA::htog(tp->tv_sec);
+ tp->tv_usec = TheISA::htog(tp->tv_usec);
tp.copyOut(tc->getMemPort());