arch,cpu,mem,sim: Reimplement the SE translating proxy using the FS one.
authorGabe Black <gabeblack@google.com>
Mon, 9 Mar 2020 23:50:32 +0000 (16:50 -0700)
committerGabe Black <gabeblack@google.com>
Thu, 19 Mar 2020 07:21:13 +0000 (07:21 +0000)
The only functional difference between them was that the SE one might
have optionally fixed up missing translations for demand paging.

This lets us get rid of some code recreating the proxy ports in
setProcessPtr since the SE translating port no longer keeps a copy of
the process object pointer.

Change-Id: Id97df1874f1de138ffd4f2dbb5846dda79d9e4ac
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/26550
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Matthew Poremba <matthew.poremba@amd.com>
Maintainer: Gabe Black <gabeblack@google.com>

15 files changed:
src/arch/arm/fastmodel/iris/thread_context.cc
src/arch/arm/process.cc
src/arch/mips/process.cc
src/arch/power/process.cc
src/arch/riscv/process.cc
src/arch/sparc/process.cc
src/arch/x86/process.cc
src/cpu/thread_state.cc
src/cpu/thread_state.hh
src/mem/fs_translating_port_proxy.cc
src/mem/fs_translating_port_proxy.hh
src/mem/se_translating_port_proxy.cc
src/mem/se_translating_port_proxy.hh
src/sim/process.cc
src/sim/process.hh

index 85171fcf8c8ae6d81f9186dc87352649f37c4358..516565eb5052a532d6df6564e650b4d062417ac1 100644 (file)
@@ -410,8 +410,7 @@ ThreadContext::initMemProxies(::ThreadContext *tc)
         virtProxy.reset(new FSTranslatingPortProxy(tc));
     } else {
         assert(!virtProxy);
-        virtProxy.reset(new SETranslatingPortProxy(
-                        _cpu->getSendFunctional(), getProcessPtr(),
+        virtProxy.reset(new SETranslatingPortProxy(this,
                         SETranslatingPortProxy::NextPage));
     }
 }
index 9cfa43127c94ae0e00d1c0aca84d8dfa47bd6f4e..3d041eef5771bab2743c6e526ecbd7408c17097d 100644 (file)
@@ -404,16 +404,16 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
 
     //Write out the sentry void *
     IntType sentry_NULL = 0;
-    initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
+    initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
 
     //Fix up the aux vectors which point to other data
     for (int i = auxv.size() - 1; i >= 0; i--) {
         if (auxv[i].type == M5_AT_PLATFORM) {
             auxv[i].val = platform_base;
-            initVirtMem.writeString(platform_base, platform.c_str());
+            initVirtMem->writeString(platform_base, platform.c_str());
         } else if (auxv[i].type == M5_AT_EXECFN) {
             auxv[i].val = aux_data_base;
-            initVirtMem.writeString(aux_data_base, filename.c_str());
+            initVirtMem->writeString(aux_data_base, filename.c_str());
         } else if (auxv[i].type == M5_AT_RANDOM) {
             auxv[i].val = aux_random_base;
             // Just leave the value 0, we don't want randomness
@@ -423,20 +423,20 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
     //Copy the aux stuff
     Addr auxv_array_end = auxv_array_base;
     for (const auto &aux: auxv) {
-        initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
+        initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
         auxv_array_end += sizeof(aux);
     }
     //Write out the terminating zeroed auxillary vector
     const AuxVector<IntType> zero(0, 0);
-    initVirtMem.write(auxv_array_end, zero);
+    initVirtMem->write(auxv_array_end, zero);
     auxv_array_end += sizeof(zero);
 
     copyStringArray(envp, envp_array_base, env_data_base,
-                    LittleEndianByteOrder, initVirtMem);
+                    LittleEndianByteOrder, *initVirtMem);
     copyStringArray(argv, argv_array_base, arg_data_base,
-                    LittleEndianByteOrder, initVirtMem);
+                    LittleEndianByteOrder, *initVirtMem);
 
-    initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
+    initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
 
     ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //Set the stack pointer register
index afeef8bd15419b640d0012329ce5d633d6dfe041..c3880875898c5c4d352a8dad365c780d5014f95e 100644 (file)
@@ -159,24 +159,24 @@ MipsProcess::argsInit(int pageSize)
 
     argc = htole((IntType)argc);
 
-    initVirtMem.writeBlob(memState->getStackMin(), &argc, intSize);
+    initVirtMem->writeBlob(memState->getStackMin(), &argc, intSize);
 
     copyStringArray(argv, argv_array_base, arg_data_base,
-                    LittleEndianByteOrder, initVirtMem);
+                    LittleEndianByteOrder, *initVirtMem);
 
     copyStringArray(envp, envp_array_base, env_data_base,
-                    LittleEndianByteOrder, initVirtMem);
+                    LittleEndianByteOrder, *initVirtMem);
 
     // Copy the aux vector
     Addr auxv_array_end = auxv_array_base;
     for (const auto &aux: auxv) {
-        initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
+        initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
         auxv_array_end += sizeof(aux);
     }
 
     // Write out the terminating zeroed auxilliary vector
     const AuxVector<IntType> zero(0, 0);
-    initVirtMem.write(auxv_array_end, zero);
+    initVirtMem->write(auxv_array_end, zero);
     auxv_array_end += sizeof(zero);
 
     ThreadContext *tc = system->getThreadContext(contextIds[0]);
index 3af8788ed4e5496ea324e66d4a788a4639b5e733..6ebdd6f2ffd3944eab7625b0d3a21a56efac2ddd 100644 (file)
@@ -93,8 +93,8 @@ PowerProcess::argsInit(int intSize, int pageSize)
     uint64_t align = 16;
 
     // load object file into target memory
-    image.write(initVirtMem);
-    interpImage.write(initVirtMem);
+    image.write(*initVirtMem);
+    interpImage.write(*initVirtMem);
 
     //Setup the auxilliary vectors. These will already have endian conversion.
     //Auxilliary vectors are loaded only for elf formatted executables.
@@ -227,36 +227,36 @@ PowerProcess::argsInit(int intSize, int pageSize)
 
     //Write out the sentry void *
     uint32_t sentry_NULL = 0;
-    initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
+    initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
 
     //Fix up the aux vectors which point to other data
     for (int i = auxv.size() - 1; i >= 0; i--) {
         if (auxv[i].type == M5_AT_PLATFORM) {
             auxv[i].val = platform_base;
-            initVirtMem.writeString(platform_base, platform.c_str());
+            initVirtMem->writeString(platform_base, platform.c_str());
         } else if (auxv[i].type == M5_AT_EXECFN) {
             auxv[i].val = aux_data_base;
-            initVirtMem.writeString(aux_data_base, filename.c_str());
+            initVirtMem->writeString(aux_data_base, filename.c_str());
         }
     }
 
     //Copy the aux stuff
     Addr auxv_array_end = auxv_array_base;
     for (const auto &aux: auxv) {
-        initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
+        initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
         auxv_array_end += sizeof(aux);
     }
     //Write out the terminating zeroed auxilliary vector
     const AuxVector<uint64_t> zero(0, 0);
-    initVirtMem.write(auxv_array_end, zero);
+    initVirtMem->write(auxv_array_end, zero);
     auxv_array_end += sizeof(zero);
 
     copyStringArray(envp, envp_array_base, env_data_base,
-                    BigEndianByteOrder, initVirtMem);
+                    BigEndianByteOrder, *initVirtMem);
     copyStringArray(argv, argv_array_base, arg_data_base,
-                    BigEndianByteOrder, initVirtMem);
+                    BigEndianByteOrder, *initVirtMem);
 
-    initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
+    initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
 
     ThreadContext *tc = system->getThreadContext(contextIds[0]);
 
index 360ff11b6775fa458d8dedc1229a371e2987330d..5feff4353c04822c44f28c7be2edce3d264a7b96 100644 (file)
@@ -155,17 +155,17 @@ RiscvProcess::argsInit(int pageSize)
     uint8_t at_random[RandomBytes];
     generate(begin(at_random), end(at_random),
              [&]{ return random_mt.random(0, 0xFF); });
-    initVirtMem.writeBlob(memState->getStackMin(), at_random, RandomBytes);
+    initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes);
 
     // Copy argv to stack
     vector<Addr> argPointers;
     for (const string& arg: argv) {
         memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
-        initVirtMem.writeString(memState->getStackMin(), arg.c_str());
+        initVirtMem->writeString(memState->getStackMin(), arg.c_str());
         argPointers.push_back(memState->getStackMin());
         if (DTRACE(Stack)) {
             string wrote;
-            initVirtMem.readString(wrote, argPointers.back());
+            initVirtMem->readString(wrote, argPointers.back());
             DPRINTFN("Wrote arg \"%s\" to address %p\n",
                     wrote, (void*)memState->getStackMin());
         }
@@ -176,7 +176,7 @@ RiscvProcess::argsInit(int pageSize)
     vector<Addr> envPointers;
     for (const string& env: envp) {
         memState->setStackMin(memState->getStackMin() - (env.size() + 1));
-        initVirtMem.writeString(memState->getStackMin(), env.c_str());
+        initVirtMem->writeString(memState->getStackMin(), env.c_str());
         envPointers.push_back(memState->getStackMin());
         DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
                 env, (void*)memState->getStackMin());
@@ -195,7 +195,7 @@ RiscvProcess::argsInit(int pageSize)
     Addr sp = memState->getStackMin();
     const auto pushOntoStack =
         [this, &sp](IntType data) {
-            initVirtMem.write(sp, data, GuestByteOrder);
+            initVirtMem->write(sp, data, GuestByteOrder);
             sp += sizeof(data);
         };
 
index f2d1de2e741d13c98da34af90c2166f679629e78..816df4f47e7d13b327a3026f84eff9275461a1a1 100644 (file)
@@ -351,29 +351,29 @@ SparcProcess::argsInit(int pageSize)
 
     // Write out the sentry void *
     uint64_t sentry_NULL = 0;
-    initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
+    initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
 
     // Write the file name
-    initVirtMem.writeString(file_name_base, filename.c_str());
+    initVirtMem->writeString(file_name_base, filename.c_str());
 
     // Copy the aux stuff
     Addr auxv_array_end = auxv_array_base;
     for (const auto &aux: auxv) {
-        initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
+        initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
         auxv_array_end += sizeof(aux);
     }
 
     // Write out the terminating zeroed auxilliary vector
     const AuxVector<IntType> zero(0, 0);
-    initVirtMem.write(auxv_array_end, zero);
+    initVirtMem->write(auxv_array_end, zero);
     auxv_array_end += sizeof(zero);
 
     copyStringArray(envp, envp_array_base, env_data_base,
-                    BigEndianByteOrder, initVirtMem);
+                    BigEndianByteOrder, *initVirtMem);
     copyStringArray(argv, argv_array_base, arg_data_base,
-                    BigEndianByteOrder, initVirtMem);
+                    BigEndianByteOrder, *initVirtMem);
 
-    initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
+    initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
 
     // Set up space for the trap handlers into the processes address space.
     // Since the stack grows down and there is reserved address space abov
@@ -404,9 +404,9 @@ Sparc64Process::argsInit(int intSize, int pageSize)
     SparcProcess::argsInit<uint64_t>(pageSize);
 
     // Stuff the trap handlers into the process address space
-    initVirtMem.writeBlob(fillStart,
+    initVirtMem->writeBlob(fillStart,
             fillHandler64, sizeof(MachInst) * numFillInsts);
-    initVirtMem.writeBlob(spillStart,
+    initVirtMem->writeBlob(spillStart,
             spillHandler64, sizeof(MachInst) *  numSpillInsts);
 }
 
@@ -416,9 +416,9 @@ Sparc32Process::argsInit(int intSize, int pageSize)
     SparcProcess::argsInit<uint32_t>(pageSize);
 
     // Stuff the trap handlers into the process address space
-    initVirtMem.writeBlob(fillStart,
+    initVirtMem->writeBlob(fillStart,
             fillHandler32, sizeof(MachInst) * numFillInsts);
-    initVirtMem.writeBlob(spillStart,
+    initVirtMem->writeBlob(spillStart,
             spillHandler32, sizeof(MachInst) *  numSpillInsts);
 }
 
index 04c9db9b9c60e577312f36c462bca2e0d3b683b9..f37a5186f8f7e1f6be7c50b6924912b3deb06bcd 100644 (file)
@@ -195,7 +195,7 @@ X86_64Process::initState()
         0x0f,0x05,                             // syscall
         0xc3                                   // retq
     };
-    initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset,
+    initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset,
             vtimeBlob, sizeof(vtimeBlob));
 
     uint8_t vgettimeofdayBlob[] = {
@@ -203,7 +203,8 @@ X86_64Process::initState()
         0x0f,0x05,                             // syscall
         0xc3                                   // retq
     };
-    initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vgettimeofdayOffset,
+    initVirtMem->writeBlob(
+            vsyscallPage.base + vsyscallPage.vgettimeofdayOffset,
             vgettimeofdayBlob, sizeof(vgettimeofdayBlob));
 
     if (kvmInSE) {
@@ -635,7 +636,7 @@ I386Process::initState()
     assert(_gdtSize % sizeof(zero) == 0);
     for (Addr gdtCurrent = _gdtStart;
             gdtCurrent < _gdtStart + _gdtSize; gdtCurrent += sizeof(zero)) {
-        initVirtMem.write(gdtCurrent, zero);
+        initVirtMem->write(gdtCurrent, zero);
     }
 
     // Set up the vsyscall page for this process.
@@ -647,7 +648,7 @@ I386Process::initState()
         0x89, 0xe5, // mov %esp, %ebp
         0x0f, 0x34  // sysenter
     };
-    initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
+    initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
             vsyscallBlob, sizeof(vsyscallBlob));
 
     uint8_t vsysexitBlob[] = {
@@ -656,7 +657,7 @@ I386Process::initState()
         0x59,       // pop %ecx
         0xc3        // ret
     };
-    initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
+    initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
             vsysexitBlob, sizeof(vsysexitBlob));
 
     for (int i = 0; i < contextIds.size(); i++) {
@@ -976,10 +977,10 @@ X86Process::argsInit(int pageSize,
 
     // Write out the sentry void *
     IntType sentry_NULL = 0;
-    initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
+    initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
 
     // Write the file name
-    initVirtMem.writeString(file_name_base, filename.c_str());
+    initVirtMem->writeString(file_name_base, filename.c_str());
 
     // Fix up the aux vectors which point to data
     assert(auxv[auxv.size() - 3].type == M5_AT_RANDOM);
@@ -993,22 +994,22 @@ X86Process::argsInit(int pageSize,
     // Copy the aux stuff
     Addr auxv_array_end = auxv_array_base;
     for (const auto &aux: auxv) {
-        initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
+        initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
         auxv_array_end += sizeof(aux);
     }
     // Write out the terminating zeroed auxiliary vector
     const AuxVector<uint64_t> zero(0, 0);
-    initVirtMem.write(auxv_array_end, zero);
+    initVirtMem->write(auxv_array_end, zero);
     auxv_array_end += sizeof(zero);
 
-    initVirtMem.writeString(aux_data_base, platform.c_str());
+    initVirtMem->writeString(aux_data_base, platform.c_str());
 
     copyStringArray(envp, envp_array_base, env_data_base,
-                    LittleEndianByteOrder, initVirtMem);
+                    LittleEndianByteOrder, *initVirtMem);
     copyStringArray(argv, argv_array_base, arg_data_base,
-                    LittleEndianByteOrder, initVirtMem);
+                    LittleEndianByteOrder, *initVirtMem);
 
-    initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
+    initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
 
     ThreadContext *tc = system->getThreadContext(contextIds[0]);
     // Set the stack pointer register
index a1d5026b08ce9ffb4fcb9ed8aaa0b6cefd4ff756..2210a7628a0d6d16dbdd67d76a4a42d59f1cf9bd 100644 (file)
@@ -115,9 +115,8 @@ ThreadState::initMemProxies(ThreadContext *tc)
         virtProxy = new FSTranslatingPortProxy(tc);
     } else {
         assert(virtProxy == NULL);
-        virtProxy = new SETranslatingPortProxy(baseCpu->getSendFunctional(),
-                                           process,
-                                           SETranslatingPortProxy::NextPage);
+        virtProxy = new SETranslatingPortProxy(
+                tc, SETranslatingPortProxy::NextPage);
     }
 }
 
index b90015556a24d73d2c02ec843650ee6a77c6ee36..df80cdc4a1e727ae1e096967eda1d24a6f4109e1 100644 (file)
@@ -105,20 +105,7 @@ struct ThreadState : public Serializable {
 
     Process *getProcessPtr() { return process; }
 
-    void setProcessPtr(Process *p)
-    {
-        process = p;
-        /**
-         * When the process pointer changes while operating in SE Mode,
-         * the se translating port proxy needs to be reinitialized since it
-         * holds a pointer to the process class.
-         */
-        if (virtProxy) {
-            delete virtProxy;
-            virtProxy = NULL;
-            initMemProxies(NULL);
-        }
-    }
+    void setProcessPtr(Process *p) { process = p; }
 
     /** Reads the number of instructions functionally executed and
      * committed.
index b33be4a55576e79fc081151ebada2767aa72d1a1..99a4b8e48dc28b955f09fcf1e78e28fee4eb0617 100644 (file)
@@ -45,7 +45,6 @@
 
 #include "mem/fs_translating_port_proxy.hh"
 
-#include "arch/generic/tlb.hh"
 #include "base/chunk_generator.hh"
 #include "cpu/base.hh"
 #include "cpu/thread_context.hh"
@@ -58,21 +57,35 @@ FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc) :
 {}
 
 bool
-FSTranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
+FSTranslatingPortProxy::tryTLBsOnce(RequestPtr req, BaseTLB::Mode mode) const
 {
     BaseTLB *dtb = _tc->getDTBPtr();
     BaseTLB *itb = _tc->getDTBPtr();
+    return dtb->translateFunctional(req, _tc, mode) == NoFault ||
+           itb->translateFunctional(req, _tc, BaseTLB::Read) == NoFault;
+}
 
+bool
+FSTranslatingPortProxy::tryTLBs(RequestPtr req, BaseTLB::Mode mode) const
+{
+    // If at first this doesn't succeed, try to fixup and translate again. If
+    // it still fails, report failure.
+    return tryTLBsOnce(req, mode) ||
+        (fixupAddr(req->getVaddr(), mode) && tryTLBsOnce(req, mode));
+}
+
+bool
+FSTranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
+{
     for (ChunkGenerator gen(addr, size, pageBytes); !gen.done();
          gen.next())
     {
         auto req = std::make_shared<Request>(
                 gen.addr(), gen.size(), 0, Request::funcMasterId, 0,
                 _tc->contextId());
-        if (dtb->translateFunctional(req, _tc, BaseTLB::Read) != NoFault &&
-            itb->translateFunctional(req, _tc, BaseTLB::Read) != NoFault) {
+
+        if (!tryTLBs(req, BaseTLB::Read))
             return false;
-        }
 
         PortProxy::readBlobPhys(
                 req->getPaddr(), req->getFlags(), p, gen.size());
@@ -86,19 +99,15 @@ bool
 FSTranslatingPortProxy::tryWriteBlob(
         Addr addr, const void *p, int size) const
 {
-    BaseTLB *dtb = _tc->getDTBPtr();
-    BaseTLB *itb = _tc->getDTBPtr();
-
     for (ChunkGenerator gen(addr, size, pageBytes); !gen.done();
          gen.next())
     {
         auto req = std::make_shared<Request>(
                 gen.addr(), gen.size(), 0, Request::funcMasterId, 0,
                 _tc->contextId());
-        if (dtb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault &&
-            itb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault) {
+
+        if (!tryTLBs(req, BaseTLB::Write))
             return false;
-        }
 
         PortProxy::writeBlobPhys(
                 req->getPaddr(), req->getFlags(), p, gen.size());
@@ -110,19 +119,15 @@ FSTranslatingPortProxy::tryWriteBlob(
 bool
 FSTranslatingPortProxy::tryMemsetBlob(Addr address, uint8_t v, int size) const
 {
-    BaseTLB *dtb = _tc->getDTBPtr();
-    BaseTLB *itb = _tc->getDTBPtr();
-
     for (ChunkGenerator gen(address, size, pageBytes); !gen.done();
          gen.next())
     {
         auto req = std::make_shared<Request>(
                 gen.addr(), gen.size(), 0, Request::funcMasterId, 0,
                 _tc->contextId());
-        if (dtb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault &&
-            itb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault) {
+
+        if (!tryTLBs(req, BaseTLB::Write))
             return false;
-        }
 
         PortProxy::memsetBlobPhys(
                 req->getPaddr(), req->getFlags(), v, gen.size());
index e536a38bce660a578f24341a865cf588098b3ce7..c3f1bc6ebeda5f834444d25f3ea8f91a4ffbe1b6 100644 (file)
 #ifndef __MEM_FS_TRANSLATING_PORT_PROXY_HH__
 #define __MEM_FS_TRANSLATING_PORT_PROXY_HH__
 
+#include "arch/generic/tlb.hh"
 #include "mem/port_proxy.hh"
 
 class ThreadContext;
 
 /**
- * A TranslatingPortProxy in FS mode translates a virtual address to a
- * physical address and then calls the read/write functions of the
- * port. If a thread context is provided the address can alway be
- * translated, If not it can only be translated if it is a simple
- * address masking operation (such as alpha super page accesses).
+ * This proxy attempts to translate virtual addresses using the TLBs. If it
+ * fails, subclasses can override the fixupAddr virtual method to try to
+ * recover, and then attempt the translation again. If it still fails then the
+ * access as a whole fails.
  */
 class FSTranslatingPortProxy : public PortProxy
 {
   private:
+    bool tryTLBsOnce(RequestPtr req, BaseTLB::Mode) const;
+    bool tryTLBs(RequestPtr req, BaseTLB::Mode) const;
+
+  protected:
     ThreadContext* _tc;
     const Addr pageBytes;
 
+    virtual bool
+    fixupAddr(Addr addr, BaseTLB::Mode mode) const
+    {
+        return false;
+    }
+
   public:
 
     FSTranslatingPortProxy(ThreadContext* tc);
index d31f0b448a32da676478af8a74061e427410d398..8bab243cb84203171c4711c135d5edb5c1355fab 100644 (file)
 
 #include "mem/se_translating_port_proxy.hh"
 
-#include <string>
-
-#include "arch/isa_traits.hh"
-#include "base/chunk_generator.hh"
-#include "config/the_isa.hh"
-#include "mem/page_table.hh"
 #include "sim/process.hh"
 #include "sim/system.hh"
 
-using namespace TheISA;
-
 SETranslatingPortProxy::SETranslatingPortProxy(
-        SendFunctionalFunc func, Process *p, AllocType alloc)
-    : PortProxy(func, p->system->cacheLineSize()), pTable(p->pTable),
-      process(p), allocating(alloc)
-{ }
-SETranslatingPortProxy::SETranslatingPortProxy(MasterPort &port,
-                                               Process *p, AllocType alloc)
-    : PortProxy(port, p->system->cacheLineSize()), pTable(p->pTable),
-      process(p), allocating(alloc)
-{ }
-
-bool
-SETranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
-{
-    int prevSize = 0;
-    auto *bytes = static_cast<uint8_t *>(p);
-
-    for (ChunkGenerator gen(addr, size, PageBytes); !gen.done(); gen.next()) {
-        Addr paddr;
-
-        if (!pTable->translate(gen.addr(),paddr))
-            return false;
-
-        PortProxy::readBlobPhys(paddr, 0, bytes + prevSize, gen.size());
-        prevSize += gen.size();
-    }
-
-    return true;
-}
-
-
-bool
-SETranslatingPortProxy::tryWriteBlob(Addr addr, const void *p, int size) const
-{
-    int prevSize = 0;
-    auto *bytes = static_cast<const uint8_t *>(p);
-
-    for (ChunkGenerator gen(addr, size, PageBytes); !gen.done(); gen.next()) {
-        Addr paddr;
-
-        if (!pTable->translate(gen.addr(), paddr)) {
-            if (allocating == Always) {
-                process->allocateMem(roundDown(gen.addr(), PageBytes),
-                                     PageBytes);
-            } else if (allocating == NextPage) {
-                // check if we've accessed the next page on the stack
-                if (!process->fixupStackFault(gen.addr()))
-                    panic("Page table fault when accessing virtual address %#x "
-                            "during functional write\n", gen.addr());
-            } else {
-                return false;
-            }
-            pTable->translate(gen.addr(), paddr);
-        }
-
-        PortProxy::writeBlobPhys(paddr, 0, bytes + prevSize, gen.size());
-        prevSize += gen.size();
-    }
-
-    return true;
-}
-
+        ThreadContext *tc, AllocType alloc)
+    : FSTranslatingPortProxy(tc), allocating(alloc)
+{}
 
 bool
-SETranslatingPortProxy::tryMemsetBlob(Addr addr, uint8_t val, int size) const
+SETranslatingPortProxy::fixupAddr(Addr addr, BaseTLB::Mode mode) const
 {
-    for (ChunkGenerator gen(addr, size, PageBytes); !gen.done(); gen.next()) {
-        Addr paddr;
-
-        if (!pTable->translate(gen.addr(), paddr)) {
-            if (allocating == Always) {
-                process->allocateMem(roundDown(gen.addr(), PageBytes),
-                                     PageBytes);
-                pTable->translate(gen.addr(), paddr);
-            } else {
-                return false;
-            }
+    auto *process = _tc->getProcessPtr();
+
+    if (mode == BaseTLB::Write) {
+        if (allocating == Always) {
+            process->allocateMem(roundDown(addr, pageBytes), pageBytes);
+            return true;
+        } else if (allocating == NextPage && process->fixupStackFault(addr)) {
+            // We've accessed the next page on the stack.
+            return true;
         }
-
-        PortProxy::memsetBlobPhys(paddr, 0, val, gen.size());
     }
-
-    return true;
+    panic("Page table fault when accessing virtual address %#x "
+          "during functional write.", addr);
 }
index ce55ed794ca9eb85e301f55118b08fcf16f3a5a5..96e17714cbda9dc016e0d4ebda8871b7297eced3 100644 (file)
 #ifndef __MEM_SE_TRANSLATING_PORT_PROXY_HH__
 #define __MEM_SE_TRANSLATING_PORT_PROXY_HH__
 
-#include "mem/port_proxy.hh"
+#include "mem/fs_translating_port_proxy.hh"
 
-class EmulationPageTable;
-class Process;
-
-/**
- * @file
- * TranslatingPortProxy Object Declaration for SE.
- *
- * Port proxies are used when non structural entities need access to
- * the memory system. Proxy objects replace the previous
- * FunctionalPort, TranslatingPort and VirtualPort objects, which
- * provided the same functionality as the proxies, but were instances
- * of ports not corresponding to real structural ports of the
- * simulated system. Via the port proxies all the accesses go through
- * an actual port and thus are transparent to a potentially
- * distributed memory and automatically adhere to the memory map of
- * the system.
- */
-class SETranslatingPortProxy : public PortProxy
+class SETranslatingPortProxy : public FSTranslatingPortProxy
 {
 
   public:
@@ -71,21 +54,13 @@ class SETranslatingPortProxy : public PortProxy
     };
 
   private:
-    EmulationPageTable *pTable;
-    Process *process;
     AllocType allocating;
 
-  public:
-    SETranslatingPortProxy(SendFunctionalFunc func,
-                           Process* p, AllocType alloc);
-    SETranslatingPortProxy(MasterPort &port, Process* p, AllocType alloc);
-    ~SETranslatingPortProxy() {}
+  protected:
+    bool fixupAddr(Addr addr, BaseTLB::Mode mode) const override;
 
-    void setPageTable(EmulationPageTable *p) { pTable = p; }
-    void setProcess(Process *p) { process = p; }
-    bool tryReadBlob(Addr addr, void *p, int size) const override;
-    bool tryWriteBlob(Addr addr, const void *p, int size) const override;
-    bool tryMemsetBlob(Addr addr, uint8_t val, int size) const override;
+  public:
+    SETranslatingPortProxy(ThreadContext *tc, AllocType alloc);
 };
 
 #endif // __MEM_SE_TRANSLATING_PORT_PROXY_HH__
index 709983227427c951ce5ac9e31407b302d88b037b..ba2a1505aa855b0d6b4f058b2e03da1dc6df5620 100644 (file)
@@ -116,8 +116,6 @@ Process::Process(ProcessParams *params, EmulationPageTable *pTable,
       kvmInSE(params->kvmInSE),
       useForClone(false),
       pTable(pTable),
-      initVirtMem(system->getSystemPort(), this,
-                  SETranslatingPortProxy::Always),
       objFile(obj_file),
       argv(params->cmd), envp(params->env),
       executable(params->executable),
@@ -189,9 +187,6 @@ Process::clone(ThreadContext *otc, ThreadContext *ntc,
          */
         delete np->pTable;
         np->pTable = pTable;
-        auto &proxy = dynamic_cast<SETranslatingPortProxy &>(
-                ntc->getVirtProxy());
-        proxy.setPageTable(np->pTable);
 
         np->memState = memState;
     } else {
@@ -312,9 +307,12 @@ Process::initState()
 
     pTable->initState();
 
+    initVirtMem.reset(new SETranslatingPortProxy(
+                tc, SETranslatingPortProxy::Always));
+
     // load object file into target memory
-    image.write(initVirtMem);
-    interpImage.write(initVirtMem);
+    image.write(*initVirtMem);
+    interpImage.write(*initVirtMem);
 }
 
 DrainState
index 35be983b00097b4ee0724a49aa717aa2493f3867..7fd3571ec78baea7b87c6e9b3ab02a1f0ed5ea01 100644 (file)
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 
 #include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -172,7 +173,8 @@ class Process : public SimObject
 
     EmulationPageTable *pTable;
 
-    SETranslatingPortProxy initVirtMem; // memory proxy for initial image load
+    // Memory proxy for initial image load.
+    std::unique_ptr<SETranslatingPortProxy> initVirtMem;
 
     /**
      * Each instance of a Loader subclass will have a chance to try to load