X86: Add a vsyscall page for 32 bit processes to use.
authorGabe Black <gblack@eecs.umich.edu>
Fri, 27 Feb 2009 17:25:51 +0000 (09:25 -0800)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 27 Feb 2009 17:25:51 +0000 (09:25 -0800)
src/arch/x86/process.cc
src/arch/x86/process.hh

index 54d5d07ab642106fccb8a08071765e2be06c09fc..4a61ed1687f11cd60e552a8c5b548b6285d1be3d 100644 (file)
@@ -152,12 +152,32 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
     mmap_start = mmap_end = (Addr)0x2aaaaaaab000ULL;
 }
 
+void
+I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
+{
+    Addr eip = tc->readPC();
+    if (eip >= vsyscallPage.base &&
+            eip < vsyscallPage.base + vsyscallPage.size) {
+        tc->setNextPC(vsyscallPage.base + vsyscallPage.vsysexitOffset);
+    }
+    X86LiveProcess::syscall(callnum, tc);
+}
+
+
 I386LiveProcess::I386LiveProcess(LiveProcessParams *params,
         ObjectFile *objFile, SyscallDesc *_syscallDescs,
         int _numSyscallDescs) :
     X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
 {
-    stack_base = (Addr)0xffffe000ULL;
+    _gdtStart = 0x100000000;
+    _gdtSize = VMPageSize;
+
+    vsyscallPage.base = 0xffffe000ULL;
+    vsyscallPage.size = VMPageSize;
+    vsyscallPage.vsyscallOffset = 0x400;
+    vsyscallPage.vsysexitOffset = 0x410;
+
+    stack_base = vsyscallPage.base;
 
     // Set pointer for next thread stack.  Reserve 8M for main stack.
     next_thread_stack_base = stack_base - (8 * 1024 * 1024);
@@ -255,8 +275,6 @@ I386LiveProcess::startup()
      * Set up a GDT for this process. The whole GDT wouldn't really be for
      * this process, but the only parts we care about are.
      */
-    _gdtStart = stack_base;
-    _gdtSize = VMPageSize;
     pTable->allocate(_gdtStart, _gdtSize);
     uint64_t zero = 0;
     assert(_gdtSize % sizeof(zero) == 0);
@@ -265,6 +283,27 @@ I386LiveProcess::startup()
         initVirtMem->write(gdtCurrent, zero);
     }
 
+    // Set up the vsyscall page for this process.
+    pTable->allocate(vsyscallPage.base, vsyscallPage.size);
+    uint8_t vsyscallBlob[] = {
+        0x51,       // push %ecx
+        0x52,       // push %edp
+        0x55,       // push %ebp
+        0x89, 0xe5, // mov %esp, %ebp
+        0x0f, 0x34  // sysenter
+    };
+    initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
+            vsyscallBlob, sizeof(vsyscallBlob));
+
+    uint8_t vsysexitBlob[] = {
+        0x5d,       // pop %ebp
+        0x5a,       // pop %edx
+        0x59,       // pop %ecx
+        0xc3        // ret
+    };
+    initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
+            vsysexitBlob, sizeof(vsysexitBlob));
+
     for (int i = 0; i < contextIds.size(); i++) {
         ThreadContext * tc = system->getThreadContext(contextIds[i]);
 
@@ -332,12 +371,13 @@ I386LiveProcess::startup()
 
 template<class IntType>
 void
-X86LiveProcess::argsInit(int pageSize)
+X86LiveProcess::argsInit(int pageSize,
+        std::vector<AuxVector<IntType> > extraAuxvs)
 {
     int intSize = sizeof(IntType);
 
     typedef AuxVector<IntType> auxv_t;
-    std::vector<auxv_t>  auxv;
+    std::vector<auxv_t> auxv = extraAuxvs;
 
     string filename;
     if(argv.size() < 1)
@@ -608,13 +648,19 @@ X86LiveProcess::argsInit(int pageSize)
 void
 X86_64LiveProcess::argsInit(int intSize, int pageSize)
 {
-    X86LiveProcess::argsInit<uint64_t>(pageSize);
+    std::vector<AuxVector<uint64_t> > extraAuxvs;
+    X86LiveProcess::argsInit<uint64_t>(pageSize, extraAuxvs);
 }
 
 void
 I386LiveProcess::argsInit(int intSize, int pageSize)
 {
-    X86LiveProcess::argsInit<uint32_t>(pageSize);
+    std::vector<AuxVector<uint32_t> > extraAuxvs;
+    //Tell the binary where the vsyscall part of the vsyscall page is.
+    extraAuxvs.push_back(AuxVector<uint32_t>(0x20,
+                vsyscallPage.base + vsyscallPage.vsyscallOffset));
+    extraAuxvs.push_back(AuxVector<uint32_t>(0x21, vsyscallPage.base));
+    X86LiveProcess::argsInit<uint32_t>(pageSize, extraAuxvs);
 }
 
 void
index 2d72d3fd0d109a1c29f31446a355135a6c31e882..cd6d99e667c8a6f5650b213375b0234664d0996c 100644 (file)
@@ -80,7 +80,8 @@ namespace X86ISA
                 SyscallDesc *_syscallDescs, int _numSyscallDescs);
 
         template<class IntType>
-        void argsInit(int pageSize);
+        void argsInit(int pageSize,
+                std::vector<AuxVector<IntType> > extraAuxvs);
 
       public:
         Addr gdtStart()
@@ -114,10 +115,21 @@ namespace X86ISA
         I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
                 SyscallDesc *_syscallDescs, int _numSyscallDescs);
 
+        class VSyscallPage
+        {
+          public:
+            Addr base;
+            Addr size;
+            Addr vsyscallOffset;
+            Addr vsysexitOffset;
+        };
+        VSyscallPage vsyscallPage;
+
       public:
         void argsInit(int intSize, int pageSize);
         void startup();
 
+        void syscall(int64_t callnum, ThreadContext *tc);
         X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i);
         void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
     };