arm,kern: Use GuestABI to call printk from the kernel.
authorGabe Black <gabeblack@google.com>
Sat, 28 Dec 2019 07:38:50 +0000 (23:38 -0800)
committerGabe Black <gabeblack@google.com>
Fri, 20 Mar 2020 03:08:43 +0000 (03:08 +0000)
Change-Id: I07b0f1c01f5ec8d6761903fa4aa15b9e8ae35069
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24113
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
src/arch/arm/linux/fs_workload.cc
src/arch/arm/linux/fs_workload.hh
src/kern/linux/events.cc
src/kern/linux/events.hh
src/kern/linux/printk.cc
src/kern/linux/printk.hh

index c21ce09f7b636233d056c76b285f8b327e283ba7..fe023cc4e1e08423bee8f7f46dc8b631397cda1b 100644 (file)
@@ -168,6 +168,7 @@ FsLinux::initState()
 
 FsLinux::~FsLinux()
 {
+    delete debugPrintk;
     delete skipUDelay;
     delete skipConstUDelay;
     delete kernelOops;
@@ -237,7 +238,13 @@ FsLinux::startup()
             "__const_udelay", "__const_udelay", 1000, 107374);
     }
 
-    debugPrintk = addKernelFuncEvent<DebugPrintk<SkipFunc>>("dprintk");
+    if (highestELIs64()) {
+        debugPrintk = addKernelFuncEvent<
+            DebugPrintk<SkipFuncLinux64>>("dprintk");
+    } else {
+        debugPrintk = addKernelFuncEvent<
+            DebugPrintk<SkipFuncLinux32>>("dprintk");
+    }
 }
 
 void
index 73a006b3490f101bff446df6f2764771584a2861..6ab3c6c3da846b74d130b8945a1b64fa1f7e4491 100644 (file)
 #include <map>
 #include <string>
 
+#include "arch/arm/aapcs32.hh"
+#include "arch/arm/aapcs64.hh"
 #include "arch/arm/fs_workload.hh"
+#include "arch/arm/system.hh"
 #include "base/output.hh"
 #include "kern/linux/events.hh"
 #include "params/ArmFsLinux.hh"
 namespace ArmISA
 {
 
-class DumpStats;
+class SkipFuncLinux32 : public SkipFunc
+{
+  public:
+    using SkipFunc::SkipFunc;
+    using ABI = Aapcs32Vfp;
+};
+
+class SkipFuncLinux64 : public SkipFunc
+{
+  public:
+    using SkipFunc::SkipFunc;
+    using ABI = Aapcs64;
+};
 
 class FsLinux : public ArmISA::FsWorkload
 {
index be72671b292b8f643929f735412752e8690a63ef..e576a39b2a26b8c964794565bc76be411bacec3e 100644 (file)
@@ -47,9 +47,7 @@
 #include "base/trace.hh"
 #include "cpu/base.hh"
 #include "cpu/thread_context.hh"
-#include "debug/DebugPrintf.hh"
 #include "kern/linux/helpers.hh"
-#include "kern/linux/printk.hh"
 #include "kern/system_events.hh"
 #include "sim/arguments.hh"
 #include "sim/core.hh"
 namespace Linux
 {
 
-void
-onDebugPrintk(ThreadContext *tc)
-{
-    if (DTRACE(DebugPrintf)) {
-        std::stringstream ss;
-        Arguments args(tc);
-        Printk(ss, args);
-        StringWrap name(tc->getSystemPtr()->name() + ".dprintk");
-        DPRINTFN("%s", ss.str());
-    }
-}
-
 void
 DmesgDump::process(ThreadContext *tc)
 {
index b4ee6db3adf2add0c4db2f133567d4dd75e60d23..c5a297b4eb69a4b7a3242c10375cbc4e476d5508 100644 (file)
 #ifndef __KERN_LINUX_EVENTS_HH__
 #define __KERN_LINUX_EVENTS_HH__
 
+#include <functional>
+#include <string>
+
+#include "base/trace.hh"
+#include "debug/DebugPrintf.hh"
+#include "kern/linux/printk.hh"
 #include "kern/system_events.hh"
+#include "sim/guest_abi.hh"
+
+class ThreadContext;
 
 namespace Linux
 {
 
-void onDebugPrintk(ThreadContext *tc);
-
 template <typename Base>
 class DebugPrintk : public Base
 {
@@ -56,7 +63,16 @@ class DebugPrintk : public Base
     void
     process(ThreadContext *tc) override
     {
-        onDebugPrintk(tc);
+        if (DTRACE(DebugPrintf)) {
+            std::string str;
+            std::function<int(ThreadContext *, Addr, PrintkVarArgs)> func =
+                [&str](ThreadContext *tc, Addr format_ptr,
+                    PrintkVarArgs args) -> int {
+                return printk(str, tc, format_ptr, args);
+            };
+            invokeSimcall<typename Base::ABI>(tc, func);
+            DPRINTFN("%s", str);
+        }
         Base::process(tc);
     }
 };
index 7b9e3c27f2b71397fcbe9b6fe2bffcc1c5b579e4..f6661df82957b56134818bc7031e0f98525764df 100644 (file)
 #include <sys/types.h>
 
 #include <algorithm>
+#include <iostream>
+#include <sstream>
 
-#include "base/trace.hh"
 #include "cpu/thread_context.hh"
-#include "sim/arguments.hh"
-
-using namespace std;
+#include "mem/port_proxy.hh"
 
+namespace Linux
+{
 
-void
-Printk(stringstream &out, Arguments args)
+int
+printk(std::string &str, ThreadContext *tc, Addr format_ptr,
+        PrintkVarArgs args)
 {
-    char *p = (char *)args++;
+    std::string format;
+    std::ostringstream out;
+    tc->getVirtProxy().readString(format, format_ptr);
+
+    const char *p = format.c_str();
 
     while (*p) {
         switch (*p) {
           case '%': {
-              bool more = true;
-              bool islong = false;
-              bool leftjustify = false;
-              bool format = false;
-              bool zero = false;
-              int width = 0;
-              while (more && *++p) {
-                  switch (*p) {
-                    case 'l':
-                    case 'L':
-                      islong = true;
-                      break;
-                    case '-':
-                      leftjustify = true;
-                      break;
-                    case '#':
-                      format = true;
-                      break;
-                    case '0':
-                      if (width)
-                          width *= 10;
-                      else
-                          zero = true;
-                      break;
-                    default:
-                      if (*p >= '1' && *p <= '9')
-                          width = 10 * width + *p - '0';
-                      else
-                          more = false;
-                      break;
-                  }
-              }
-
-              bool hexnum = false;
-              bool octal = false;
-              bool sign = false;
-              switch (*p) {
-                case 'X':
-                case 'x':
-                  hexnum = true;
-                  break;
-                case 'O':
-                case 'o':
-                  octal = true;
-                  break;
-                case 'D':
-                case 'd':
-                  sign = true;
-                  break;
-                case 'P':
-                  format = true;
-                  M5_FALLTHROUGH;
-                case 'p':
-                  hexnum = true;
-                  break;
-              }
-
-              switch (*p) {
-                case 'D':
-                case 'd':
-                case 'U':
-                case 'u':
-                case 'X':
-                case 'x':
-                case 'O':
-                case 'o':
-                case 'P':
-                case 'p': {
-                  if (hexnum)
-                      out << hex;
-
-                  if (octal)
-                      out << oct;
-
-                  if (format) {
-                      if (!zero)
-                          out.setf(ios::showbase);
-                      else {
-                          if (hexnum) {
-                              out << "0x";
-                              width -= 2;
-                          } else if (octal) {
-                              out << "0";
-                              width -= 1;
-                          }
-                      }
-                  }
-
-                  if (zero)
-                      out.fill('0');
-
-                  if (width > 0)
-                      out.width(width);
-
-                  if (leftjustify && !zero)
-                      out.setf(ios::left);
-
-                  if (sign) {
-                      if (islong)
-                          out << (int64_t)args;
-                      else
-                          out << (int32_t)args;
-                  } else {
-                      if (islong)
-                          out << (uint64_t)args;
-                      else
-                          out << (uint32_t)args;
-                  }
-
-                  if (zero)
-                      out.fill(' ');
-
-                  if (width > 0)
-                      out.width(0);
-
-                  out << dec;
-
-                  ++args;
+            bool more = true;
+            bool islong = false;
+            bool leftjustify = false;
+            bool format = false;
+            bool zero = false;
+            int width = 0;
+            while (more && *++p) {
+                switch (*p) {
+                  case 'l':
+                  case 'L':
+                    islong = true;
+                    break;
+                  case '-':
+                    leftjustify = true;
+                    break;
+                  case '#':
+                    format = true;
+                    break;
+                  case '0':
+                    if (width)
+                        width *= 10;
+                    else
+                        zero = true;
+                    break;
+                  default:
+                    if (*p >= '1' && *p <= '9')
+                        width = 10 * width + *p - '0';
+                    else
+                        more = false;
+                    break;
                 }
-                  break;
+            }
+
+            bool hexnum = false;
+            bool octal = false;
+            bool sign = false;
+            switch (*p) {
+              case 'X':
+              case 'x':
+                hexnum = true;
+                break;
+              case 'O':
+              case 'o':
+                octal = true;
+                break;
+              case 'D':
+              case 'd':
+                sign = true;
+                break;
+              case 'P':
+                format = true;
+                M5_FALLTHROUGH;
+              case 'p':
+                hexnum = true;
+                break;
+            }
+
+            switch (*p) {
+              case 'D':
+              case 'd':
+              case 'U':
+              case 'u':
+              case 'X':
+              case 'x':
+              case 'O':
+              case 'o':
+              case 'P':
+              case 'p': {
+                    if (hexnum)
+                        out << std::hex;
+
+                    if (octal)
+                        out << std::oct;
+
+                    if (format) {
+                        if (!zero)
+                            out.setf(std::ios::showbase);
+                        else {
+                            if (hexnum) {
+                                out << "0x";
+                                width -= 2;
+                            } else if (octal) {
+                                out << "0";
+                                width -= 1;
+                            }
+                        }
+                    }
+
+                    if (zero)
+                        out.fill('0');
+
+                    if (width > 0)
+                        out.width(width);
+
+                    if (leftjustify && !zero)
+                        out.setf(std::ios::left);
+
+                    if (sign) {
+                        if (islong)
+                            out << args.get<int64_t>();
+                        else
+                            out << args.get<int32_t>();
+                    } else {
+                        if (islong)
+                            out << args.get<uint64_t>();
+                        else
+                            out << args.get<uint32_t>();
+                    }
+
+                    if (zero)
+                        out.fill(' ');
 
-                case 's': {
-                    const char *s = (char *)args;
-                    if (!s)
+                    if (width > 0)
+                        out.width(0);
+
+                    out << std::dec;
+                }
+                break;
+
+              case 's': {
+                    Addr s_ptr = args.get<Addr>();
+                    std::string s;
+                    if (s_ptr)
+                        tc->getVirtProxy().readString(s, s_ptr);
+                    else
                         s = "<NULL>";
 
                     if (width > 0)
                         out.width(width);
                     if (leftjustify)
-                        out.setf(ios::left);
+                        out.setf(std::ios::left);
 
                     out << s;
-                    ++args;
                 }
-                  break;
-                case 'C':
-                case 'c': {
+                break;
+              case 'C':
+              case 'c': {
                     uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL;
                     uint64_t num;
                     int cwidth;
 
                     if (islong) {
-                        num = (uint64_t)args;
+                        num = args.get<uint64_t>();
                         cwidth = sizeof(uint64_t);
                     } else {
-                        num = (uint32_t)args;
+                        num = args.get<uint32_t>();
                         cwidth = sizeof(uint32_t);
                     }
 
@@ -202,49 +208,43 @@ Printk(stringstream &out, Arguments args)
                             out << c;
                         num >>= 8;
                     }
-
-                    ++args;
-                }
-                  break;
-                case 'b': {
-                  uint64_t n = (uint64_t)args++;
-                  char *s = (char *)args++;
-                  out << s << ": " << n;
-                }
-                  break;
-                case 'n':
-                case 'N': {
-                    args += 2;
                 }
-                  break;
-                case 'r':
-                case 'R': {
-                    args += 2;
+                break;
+              case 'b': {
+                    uint64_t n = args.get<uint64_t>();
+                    Addr s_ptr = args.get<Addr>();
+                    std::string s;
+                    tc->getVirtProxy().readString(s, s_ptr);
+                    out << s << ": " << n;
                 }
-                  break;
-                case '%':
-                  out << '%';
-                  break;
-              }
-              ++p;
-          }
-            break;
-          case '\n':
-            out << endl;
-            ++p;
-            break;
-          case '\r':
+                break;
+              case '%':
+                out << '%';
+                break;
+            }
             ++p;
-            if (*p != '\n')
-                out << endl;
-            break;
-
-          default: {
+          }
+          break;
+        case '\n':
+          out << std::endl;
+          ++p;
+          break;
+        case '\r':
+          ++p;
+          if (*p != '\n')
+              out << std::endl;
+          break;
+
+        default: {
               size_t len = strcspn(p, "%\n\r\0");
               out.write(p, len);
               p += len;
-          }
+            }
         }
     }
 
+    str = out.str();
+    return str.length();
 }
+
+} // namespace Linux
index 8a18a00dd30f3230db37ea158f5a2bf41aca4add..cb7bc9ad84bef82f5970af40f5363de76dc6bfb7 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __PRINTK_HH__
-#define __PRINTK_HH__
+#ifndef __KERN_LINUX_PRINTK_HH__
+#define __KERN_LINUX_PRINTK_HH__
 
-#include <sstream>
+#include <string>
 
-class Arguments;
+#include "base/types.hh"
+#include "sim/guest_abi.hh"
 
-void Printk(std::stringstream &out, Arguments args);
+namespace Linux
+{
 
-#endif // __PRINTK_HH__
+using PrintkVarArgs =
+    GuestABI::VarArgs<Addr, int32_t, uint32_t, int64_t, uint64_t>;
+int printk(std::string &out, ThreadContext *tc, Addr format_ptr,
+           PrintkVarArgs args);
+
+} // namespace Linux
+
+#endif // __KERN_LINUX_PRINTK_HH__