FsLinux::~FsLinux()
{
+ delete debugPrintk;
delete skipUDelay;
delete skipConstUDelay;
delete kernelOops;
"__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
#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
{
#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)
{
#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
{
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);
}
};
#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);
}
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
* 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__