From fe1d103e0efdbf94dee7829e36e41f2f0c9d2582 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 27 Dec 2019 23:38:50 -0800 Subject: [PATCH] arm,kern: Use GuestABI to call printk from the kernel. Change-Id: I07b0f1c01f5ec8d6761903fa4aa15b9e8ae35069 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24113 Tested-by: kokoro Maintainer: Giacomo Travaglini Reviewed-by: Bobby R. Bruce --- src/arch/arm/linux/fs_workload.cc | 9 +- src/arch/arm/linux/fs_workload.hh | 17 +- src/kern/linux/events.cc | 14 -- src/kern/linux/events.hh | 22 +- src/kern/linux/printk.cc | 344 +++++++++++++++--------------- src/kern/linux/printk.hh | 21 +- 6 files changed, 230 insertions(+), 197 deletions(-) diff --git a/src/arch/arm/linux/fs_workload.cc b/src/arch/arm/linux/fs_workload.cc index c21ce09f7..fe023cc4e 100644 --- a/src/arch/arm/linux/fs_workload.cc +++ b/src/arch/arm/linux/fs_workload.cc @@ -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>("dprintk"); + if (highestELIs64()) { + debugPrintk = addKernelFuncEvent< + DebugPrintk>("dprintk"); + } else { + debugPrintk = addKernelFuncEvent< + DebugPrintk>("dprintk"); + } } void diff --git a/src/arch/arm/linux/fs_workload.hh b/src/arch/arm/linux/fs_workload.hh index 73a006b34..6ab3c6c3d 100644 --- a/src/arch/arm/linux/fs_workload.hh +++ b/src/arch/arm/linux/fs_workload.hh @@ -45,7 +45,10 @@ #include #include +#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" @@ -54,7 +57,19 @@ 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 { diff --git a/src/kern/linux/events.cc b/src/kern/linux/events.cc index be72671b2..e576a39b2 100644 --- a/src/kern/linux/events.cc +++ b/src/kern/linux/events.cc @@ -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" @@ -58,18 +56,6 @@ 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) { diff --git a/src/kern/linux/events.hh b/src/kern/linux/events.hh index b4ee6db3a..c5a297b4e 100644 --- a/src/kern/linux/events.hh +++ b/src/kern/linux/events.hh @@ -41,13 +41,20 @@ #ifndef __KERN_LINUX_EVENTS_HH__ #define __KERN_LINUX_EVENTS_HH__ +#include +#include + +#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 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 func = + [&str](ThreadContext *tc, Addr format_ptr, + PrintkVarArgs args) -> int { + return printk(str, tc, format_ptr, args); + }; + invokeSimcall(tc, func); + DPRINTFN("%s", str); + } Base::process(tc); } }; diff --git a/src/kern/linux/printk.cc b/src/kern/linux/printk.cc index 7b9e3c27f..f6661df82 100644 --- a/src/kern/linux/printk.cc +++ b/src/kern/linux/printk.cc @@ -31,168 +31,174 @@ #include #include +#include +#include -#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(); + else + out << args.get(); + } else { + if (islong) + out << args.get(); + else + out << args.get(); + } + + 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(); + std::string s; + if (s_ptr) + tc->getVirtProxy().readString(s, s_ptr); + else s = ""; 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(); cwidth = sizeof(uint64_t); } else { - num = (uint32_t)args; + num = args.get(); 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(); + Addr s_ptr = args.get(); + 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 diff --git a/src/kern/linux/printk.hh b/src/kern/linux/printk.hh index 8a18a00dd..cb7bc9ad8 100644 --- a/src/kern/linux/printk.hh +++ b/src/kern/linux/printk.hh @@ -26,13 +26,22 @@ * 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 +#include -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; +int printk(std::string &out, ThreadContext *tc, Addr format_ptr, + PrintkVarArgs args); + +} // namespace Linux + +#endif // __KERN_LINUX_PRINTK_HH__ -- 2.30.2