summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
authorVince Weaver <vince@csl.cornell.edu>2009-11-04 00:47:12 -0500
committerVince Weaver <vince@csl.cornell.edu>2009-11-04 00:47:12 -0500
commita1042db29098da395d0de96c652c41904feb425a (patch)
treea6ce96e097b8082c6404c819851f0cbe86fa8ca9 /src/arch/x86
parent9b0a747dd41d3383769be1cd737733902875a528 (diff)
downloadgem5-a1042db29098da395d0de96c652c41904feb425a.tar.xz
X86: Enable x86_64 vsyscall support
64-bit vsyscall is different than 32-bit. There are only two syscalls, time and gettimeofday. On a real system, there is complicated code that implements these without entering the kernel. That would be complicated to implement in m5. Instead we just place code that calls the regular syscalls (this is how tools such as valgrind handle this case). This is needed for the perlbmk spec2k benchmark.
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/process.cc24
-rw-r--r--src/arch/x86/process.hh10
2 files changed, 34 insertions, 0 deletions
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index f7b3ce24a..7cc889d7c 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -139,6 +139,12 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
int _numSyscallDescs) :
X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
{
+
+ vsyscallPage.base = 0xffffffffff600000ULL;
+ vsyscallPage.size = VMPageSize;
+ vsyscallPage.vtimeOffset = 0x400;
+ vsyscallPage.vgettimeofdayOffset = 0x410;
+
// Set up stack. On X86_64 Linux, stack goes from the top of memory
// downward, less the hole for the kernel address space plus one page
// for undertermined purposes.
@@ -205,6 +211,24 @@ X86_64LiveProcess::startup()
argsInit(sizeof(uint64_t), VMPageSize);
+ // Set up the vsyscall page for this process.
+ pTable->allocate(vsyscallPage.base, vsyscallPage.size);
+ uint8_t vtimeBlob[] = {
+ 0x48,0xc7,0xc0,0xc9,0x00,0x00,0x00, // mov $0xc9,%rax
+ 0x0f,0x05, // syscall
+ 0xc3 // retq
+ };
+ initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset,
+ vtimeBlob, sizeof(vtimeBlob));
+
+ uint8_t vgettimeofdayBlob[] = {
+ 0x48,0xc7,0xc0,0x60,0x00,0x00,0x00, // mov $0x60,%rax
+ 0x0f,0x05, // syscall
+ 0xc3 // retq
+ };
+ initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vgettimeofdayOffset,
+ vgettimeofdayBlob, sizeof(vgettimeofdayBlob));
+
for (int i = 0; i < contextIds.size(); i++) {
ThreadContext * tc = system->getThreadContext(contextIds[i]);
diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh
index 4d031bd5a..3ad2abe08 100644
--- a/src/arch/x86/process.hh
+++ b/src/arch/x86/process.hh
@@ -101,6 +101,16 @@ namespace X86ISA
X86_64LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
+ class VSyscallPage
+ {
+ public:
+ Addr base;
+ Addr size;
+ Addr vtimeOffset;
+ Addr vgettimeofdayOffset;
+ };
+ VSyscallPage vsyscallPage;
+
public:
void argsInit(int intSize, int pageSize);
void startup();