mem-cache: Add multiple eviction stats
[gem5.git] / src / arch / arm / semihosting.cc
index 98b50f46899b3ad6207d32b3662a47a98b714843..a0c865d8bcdc081896582395462fee6752d40827 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 ARM Limited
+ * Copyright (c) 2018, 2019 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -47,7 +47,7 @@
 #include "debug/Semihosting.hh"
 #include "dev/serial/serial.hh"
 #include "mem/physical.hh"
-#include "mem/port_proxy.hh"
+#include "mem/secure_port_proxy.hh"
 #include "params/ArmSemihosting.hh"
 #include "sim/byteswap.hh"
 #include "sim/sim_exit.hh"
@@ -76,7 +76,7 @@ const std::map<uint32_t, ArmSemihosting::SemiCall> ArmSemihosting::calls{
     { 0x11, { "SYS_TIME", &ArmSemihosting::callTime, 0, 0} },
     { 0x12, { "SYS_SYSTEM", &ArmSemihosting::callSystem, 2, 2} },
     { 0x13, { "SYS_ERRNO", &ArmSemihosting::callErrno, 0, 0 } },
-    { 0x15, { "SYS_GET_CMDLINE", &ArmSemihosting::callGetCmdLine, 1, 1} },
+    { 0x15, { "SYS_GET_CMDLINE", &ArmSemihosting::callGetCmdLine, 2, 2} },
     { 0x16, { "SYS_HEAPINFO", &ArmSemihosting::callHeapInfo, 1, 1} },
 
     // Exit is special and requires custom handling in aarch32.
@@ -121,6 +121,15 @@ const std::vector<uint8_t> ArmSemihosting::features{
     0x3,                    // EXT_EXIT_EXTENDED, EXT_STDOUT_STDERR
 };
 
+const std::map<const std::string, FILE *> ArmSemihosting::stdioMap{
+    {"cin",    ::stdin},
+    {"stdin",  ::stdin},
+    {"cout",   ::stdout},
+    {"stdout", ::stdout},
+    {"cerr",   ::stderr},
+    {"stderr", ::stderr},
+};
+
 ArmSemihosting::ArmSemihosting(const ArmSemihostingParams *p)
     : SimObject(p),
       cmdLine(p->cmd_line),
@@ -128,7 +137,14 @@ ArmSemihosting::ArmSemihosting(const ArmSemihostingParams *p)
       stackSize(p->stack_size),
       timeBase([p]{ struct tm t = p->time; return mkutctime(&t); }()),
       tickShift(calcTickShift()),
-      semiErrno(0)
+      semiErrno(0),
+      filesRootDir(!p->files_root_dir.empty() &&
+                   p->files_root_dir.back() != '/' ?
+                   p->files_root_dir + '/' : p->files_root_dir),
+      stdin(getSTDIO("stdin", p->stdin, "r")),
+      stdout(getSTDIO("stdout", p->stdout, "w")),
+      stderr(p->stderr == p->stdout ?
+             stdout : getSTDIO("stderr", p->stderr, "w"))
 {
     // Create an empty place-holder file for position 0 as semi-hosting
     // calls typically expect non-zero file handles.
@@ -157,13 +173,13 @@ ArmSemihosting::call64(ThreadContext *tc, uint32_t op, uint64_t param)
     }
 
     std::vector<uint64_t> argv(call->argc64 + 1);
-    PortProxy &proxy = tc->getPhysProxy();
+    PortProxy &proxy = physProxy(tc);
     ByteOrder endian = ArmISA::byteOrder(tc);
 
     DPRINTF(Semihosting, "Semihosting call64: %s(0x%x)\n", call->name, param);
     argv[0] = param;
     for (int i = 0; i < call->argc64; ++i) {
-        argv[i + 1] = proxy.readGtoH<uint64_t>(param + i * 8, endian);
+        argv[i + 1] = proxy.read<uint64_t>(param + i * 8, endian);
         DPRINTF(Semihosting, "\t: 0x%x\n", argv[i + 1]);
     }
 
@@ -192,13 +208,13 @@ ArmSemihosting::call32(ThreadContext *tc, uint32_t op, uint32_t param)
     }
 
     std::vector<uint64_t> argv(call->argc32 + 1);
-    PortProxy &proxy = tc->getPhysProxy();
+    PortProxy &proxy = physProxy(tc);
     ByteOrder endian = ArmISA::byteOrder(tc);
 
     DPRINTF(Semihosting, "Semihosting call32: %s(0x%x)\n", call->name, param);
     argv[0] = param;
     for (int i = 0; i < call->argc32; ++i) {
-        argv[i + 1] = proxy.readGtoH<uint32_t>(param + i * 4, endian);
+        argv[i + 1] = proxy.read<uint32_t>(param + i * 4, endian);
         DPRINTF(Semihosting, "\t: 0x%x\n", argv[i + 1]);
     }
 
@@ -236,13 +252,30 @@ ArmSemihosting::unserialize(CheckpointIn &cp)
         files[i] = FileBase::create(*this, cp, csprintf("file%i", i));
 }
 
+PortProxy &
+ArmSemihosting::physProxy(ThreadContext *tc)
+{
+    if (ArmISA::inSecureState(tc)) {
+        if (!physProxyS) {
+            System *sys = tc->getSystemPtr();
+            physProxyS.reset(new SecurePortProxy(
+                                 sys->getSystemPort(),
+                                 sys->cacheLineSize()));
+        }
+        return *physProxyS;
+    } else {
+        return tc->getPhysProxy();
+    }
+}
+
+
 std::string
 ArmSemihosting::readString(ThreadContext *tc, Addr ptr, size_t len)
 {
     std::vector<char> buf(len + 1);
 
     buf[len] = '\0';
-    tc->getPhysProxy().readBlob(ptr, (uint8_t *)buf.data(), len);
+    physProxy(tc).readBlob(ptr, buf.data(), len);
 
     return std::string(buf.data());
 }
@@ -261,6 +294,8 @@ ArmSemihosting::callOpen(ThreadContext *tc, bool aarch64,
         return retError(EINVAL);
 
     std::string fname = readString(tc, name_base, name_size);
+    if (!fname.empty() && fname.front() != '/')
+        fname = filesRootDir + fname;
 
     std::unique_ptr<ArmSemihosting::FileBase> file =
         FileBase::create(*this, fname, mode);
@@ -302,7 +337,7 @@ ArmSemihosting::RetErrno
 ArmSemihosting::callWriteC(ThreadContext *tc, bool aarch64,
                            std::vector<uint64_t> &argv)
 {
-    const char c = tc->getPhysProxy().read<char>(argv[0]);
+    const char c = physProxy(tc).read<char>(argv[0]);
 
     DPRINTF(Semihosting, "Semihosting SYS_WRITEC('%c')\n", c);
     std::cout.put(c);
@@ -315,7 +350,7 @@ ArmSemihosting::callWrite0(ThreadContext *tc, bool aarch64,
                            std::vector<uint64_t> &argv)
 {
     DPRINTF(Semihosting, "Semihosting SYS_WRITE0(...)\n");
-    PortProxy &proxy = tc->getPhysProxy();
+    PortProxy &proxy = physProxy(tc);
     for (Addr addr = (Addr)argv[0]; ; ++addr) {
         char data = proxy.read<char>(addr);
         if (data == 0)
@@ -335,7 +370,7 @@ ArmSemihosting::callWrite(ThreadContext *tc, bool aarch64,
         return RetErrno(argv[3], EBADF);
 
     std::vector<uint8_t> buffer(argv[3]);
-    tc->getPhysProxy().readBlob(argv[2], buffer.data(), buffer.size());
+    physProxy(tc).readBlob(argv[2], buffer.data(), buffer.size());
 
     int64_t ret = files[argv[1]]->write(buffer.data(), buffer.size());
     if (ret < 0) {
@@ -362,7 +397,7 @@ ArmSemihosting::callRead(ThreadContext *tc, bool aarch64,
     } else {
         panic_if(ret > buffer.size(), "Read longer than buffer size.");
 
-        tc->getPhysProxy().writeBlob(argv[2], buffer.data(), ret);
+        physProxy(tc).writeBlob(argv[2], buffer.data(), ret);
 
         // Return the number of bytes not written
         return retOK(argv[3] - ret);
@@ -424,11 +459,11 @@ ArmSemihosting::callFLen(ThreadContext *tc, bool aarch64,
     if (argv[1] > files.size() || !files[argv[1]])
         return retError(EBADF);
 
-    int64_t ret = files[argv[1]]->isTTY();
+    int64_t ret = files[argv[1]]->flen();
     if (ret < 0) {
         return retError(-ret);
     } else {
-        return retOK(0);
+        return retOK(ret);
     }
 }
 
@@ -449,8 +484,7 @@ ArmSemihosting::callTmpNam(ThreadContext *tc, bool aarch64,
     if (path_len >= max_len)
         return retError(ENOSPC);
 
-    tc->getPhysProxy().writeBlob(
-        guest_buf, (const uint8_t *)path, path_len + 1);
+    physProxy(tc).writeBlob(guest_buf, path, path_len + 1);
     return retOK(0);
 }
 
@@ -519,16 +553,14 @@ ArmSemihosting::callGetCmdLine(ThreadContext *tc, bool aarch64,
                                std::vector<uint64_t> &argv)
 {
     if (cmdLine.size() + 1 < argv[2]) {
-        PortProxy &proxy = tc->getPhysProxy();
+        PortProxy &proxy = physProxy(tc);
         ByteOrder endian = ArmISA::byteOrder(tc);
-        proxy.writeBlob(
-            (Addr)argv[1],
-            (const uint8_t *)cmdLine.c_str(), cmdLine.size() + 1);
+        proxy.writeBlob((Addr)argv[1], cmdLine.c_str(), cmdLine.size() + 1);
 
         if (aarch64)
-            proxy.writeHtoG<uint64_t>(argv[0] + 1 * 8, cmdLine.size(), endian);
+            proxy.write<uint64_t>(argv[0] + 1 * 8, cmdLine.size(), endian);
         else
-            proxy.writeHtoG<uint32_t>(argv[0] + 1 * 4, cmdLine.size(), endian);
+            proxy.write<uint32_t>(argv[0] + 1 * 4, cmdLine.size(), endian);
         return retOK(0);
     } else {
         return retError(0);
@@ -576,18 +608,18 @@ ArmSemihosting::callHeapInfo(ThreadContext *tc, bool aarch64,
            heap_base, heap_limit, stack_base, stack_limit);
 
     Addr base = argv[1];
-    PortProxy &proxy = tc->getPhysProxy();
+    PortProxy &proxy = physProxy(tc);
     ByteOrder endian = ArmISA::byteOrder(tc);
     if (aarch64) {
-        proxy.writeHtoG<uint64_t>(base + 0 * 8, heap_base, endian);
-        proxy.writeHtoG<uint64_t>(base + 1 * 8, heap_limit, endian);
-        proxy.writeHtoG<uint64_t>(base + 2 * 8, stack_base, endian);
-        proxy.writeHtoG<uint64_t>(base + 3 * 8, stack_limit, endian);
+        proxy.write<uint64_t>(base + 0 * 8, heap_base, endian);
+        proxy.write<uint64_t>(base + 1 * 8, heap_limit, endian);
+        proxy.write<uint64_t>(base + 2 * 8, stack_base, endian);
+        proxy.write<uint64_t>(base + 3 * 8, stack_limit, endian);
     } else {
-        proxy.writeHtoG<uint32_t>(base + 0 * 4, heap_base, endian);
-        proxy.writeHtoG<uint32_t>(base + 1 * 4, heap_limit, endian);
-        proxy.writeHtoG<uint32_t>(base + 2 * 4, stack_base, endian);
-        proxy.writeHtoG<uint32_t>(base + 3 * 4, stack_limit, endian);
+        proxy.write<uint32_t>(base + 0 * 4, heap_base, endian);
+        proxy.write<uint32_t>(base + 1 * 4, heap_limit, endian);
+        proxy.write<uint32_t>(base + 2 * 4, stack_base, endian);
+        proxy.write<uint32_t>(base + 3 * 4, stack_limit, endian);
     }
 
     return retOK(0);
@@ -631,15 +663,15 @@ ArmSemihosting::RetErrno
 ArmSemihosting::callElapsed(ThreadContext *tc, bool aarch64,
                             std::vector<uint64_t> &argv)
 {
-    PortProxy &proxy = tc->getPhysProxy();
+    PortProxy &proxy = physProxy(tc);
     ByteOrder endian = ArmISA::byteOrder(tc);
     const uint64_t tick = semiTick(curTick());
 
     if (aarch64) {
-        proxy.writeHtoG<uint64_t>(argv[0], tick, endian);
+        proxy.write<uint64_t>(argv[0], tick, endian);
     } else {
-        proxy.writeHtoG<uint32_t>(argv[0] + 0 * 4, tick, endian);
-        proxy.writeHtoG<uint32_t>(argv[0] + 1 * 4, tick >> 32, endian);
+        proxy.write<uint32_t>(argv[0] + 0 * 4, tick, endian);
+        proxy.write<uint32_t>(argv[0] + 1 * 4, tick >> 32, endian);
     }
 
     return retOK(0);
@@ -664,6 +696,23 @@ ArmSemihosting::getCall(uint32_t op, bool aarch64)
     }
 }
 
+FILE *
+ArmSemihosting::getSTDIO(const char *stream_name,
+                         const std::string &name, const char *mode)
+{
+    auto it = stdioMap.find(name);
+    if (it == stdioMap.end()) {
+        FILE *f = fopen(name.c_str(), mode);
+        if (!f) {
+            fatal("Failed to open %s (%s): %s\n",
+                  stream_name, name, strerror(errno));
+        }
+        return f;
+    } else {
+        return it->second;
+    }
+}
+
 std::unique_ptr<ArmSemihosting::FileBase>
 ArmSemihosting::FileBase::create(
     ArmSemihosting &parent, const std::string &fname, const char *mode)
@@ -802,11 +851,11 @@ ArmSemihosting::File::openImpl(bool in_cpt)
 
     if (_name == ":tt") {
         if (mode[0] == 'r') {
-            file = stdin;
+            file = parent.stdin;
         } else if (mode[0] == 'w') {
-            file = stdout;
+            file = parent.stdout;
         } else if (mode[0] == 'a') {
-            file = stderr;
+            file = parent.stderr;
         } else {
             warn("Unknown file mode for the ':tt' special file");
             return -EINVAL;
@@ -840,7 +889,9 @@ ArmSemihosting::File::close()
 bool
 ArmSemihosting::File::isTTY() const
 {
-    return file == stdout || file == stderr || file == stdin;
+    return file == parent.stdout ||
+        file == parent.stderr ||
+        file == parent.stdin;
 }
 
 int64_t