summaryrefslogtreecommitdiff
path: root/src/arch/x86/linux
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-08-04 20:02:41 -0700
committerGabe Black <gblack@eecs.umich.edu>2007-08-04 20:02:41 -0700
commit0e6be2a9b16660903306b2762e69a2678a54a6ba (patch)
tree6153074fdb4b696a5cf2da51a2a81edaa039b0d9 /src/arch/x86/linux
parent121a894ce0d551e860392f9aa6bd381329a25b96 (diff)
downloadgem5-0e6be2a9b16660903306b2762e69a2678a54a6ba.tar.xz
X86: Add the arch_prctl system call and fix up some microcoding.
The arch_prctl system call is used to set and get the FS and GS segment bases. The FS segment is use for TLS, so glibc needs to be able to set it up. --HG-- extra : convert_revision : 79501491a15967a7a862add846ff88a934fb1b37
Diffstat (limited to 'src/arch/x86/linux')
-rw-r--r--src/arch/x86/linux/syscalls.cc42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc
index efbe33dfa..1146af708 100644
--- a/src/arch/x86/linux/syscalls.cc
+++ b/src/arch/x86/linux/syscalls.cc
@@ -57,6 +57,7 @@
#include "arch/x86/linux/process.hh"
#include "arch/x86/linux/linux.hh"
+#include "arch/x86/miscregs.hh"
#include "kern/linux/linux.hh"
#include "sim/syscall_emul.hh"
@@ -80,6 +81,45 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return 0;
}
+static SyscallReturn
+archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ enum ArchPrctlCodes
+ {
+ SetFS = 0x1002,
+ GetFS = 0x1003,
+ SetGS = 0x1001,
+ GetGS = 0x1004
+ };
+
+ //First argument is the code, second is the address
+ int code = tc->getSyscallArg(0);
+ uint64_t addr = tc->getSyscallArg(1);
+ uint64_t fsBase, gsBase;
+ TranslatingPort *p = tc->getMemPort();
+ switch(code)
+ {
+ //Each of these valid options should actually check addr.
+ case SetFS:
+ tc->setMiscRegNoEffect(MISCREG_FS_BASE, addr);
+ return 0;
+ case GetFS:
+ fsBase = tc->readMiscRegNoEffect(MISCREG_FS_BASE);
+ p->write(addr, fsBase);
+ return 0;
+ case SetGS:
+ tc->setMiscRegNoEffect(MISCREG_GS_BASE, addr);
+ return 0;
+ case GetGS:
+ gsBase = tc->readMiscRegNoEffect(MISCREG_GS_BASE);
+ p->write(addr, gsBase);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
SyscallDesc X86LinuxProcess::syscallDescs[] = {
/* 0 */ SyscallDesc("read", readFunc),
/* 1 */ SyscallDesc("write", writeFunc),
@@ -239,7 +279,7 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = {
/* 155 */ SyscallDesc("pivot_root", unimplementedFunc),
/* 156 */ SyscallDesc("_sysctl", unimplementedFunc),
/* 157 */ SyscallDesc("prctl", unimplementedFunc),
- /* 158 */ SyscallDesc("arch_prctl", unimplementedFunc),
+ /* 158 */ SyscallDesc("arch_prctl", archPrctlFunc),
/* 159 */ SyscallDesc("adjtimex", unimplementedFunc),
/* 160 */ SyscallDesc("setrlimit", unimplementedFunc),
/* 161 */ SyscallDesc("chroot", unimplementedFunc),