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 <noreply+kokoro@google.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
This commit is contained in:
Gabe Black
2019-12-27 23:38:50 -08:00
parent 2d142070c5
commit fe1d103e0e
6 changed files with 230 additions and 197 deletions

View 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

View File

@@ -45,7 +45,10 @@
#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"
@@ -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
{

View 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"
@@ -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)
{

View File

@@ -41,13 +41,20 @@
#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);
}
};

View File

@@ -31,168 +31,174 @@
#include <sys/types.h>
#include <algorithm>
#include <iostream>
#include <sstream>
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "sim/arguments.hh"
#include "mem/port_proxy.hh"
using namespace std;
void
Printk(stringstream &out, Arguments args)
namespace Linux
{
char *p = (char *)args++;
int
printk(std::string &str, ThreadContext *tc, Addr format_ptr,
PrintkVarArgs 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;
}
case 's': {
const char *s = (char *)args;
if (!s)
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(' ');
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 '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 'n':
case 'N': {
args += 2;
}
break;
case 'r':
case 'R': {
args += 2;
}
break;
case '%':
out << '%';
break;
}
++p;
break;
case '%':
out << '%';
break;
}
++p;
}
break;
case '\n':
out << endl;
++p;
break;
case '\r':
++p;
if (*p != '\n')
out << endl;
break;
break;
case '\n':
out << std::endl;
++p;
break;
case '\r':
++p;
if (*p != '\n')
out << std::endl;
break;
default: {
default: {
size_t len = strcspn(p, "%\n\r\0");
out.write(p, len);
p += len;
}
}
}
}
str = out.str();
return str.length();
}
} // namespace Linux

View File

@@ -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 <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__