From: Gabe Black Date: Fri, 27 Dec 2019 00:49:11 +0000 (-0800) Subject: kern,arch: Refactor SkipFuncEvent to not use skipFunction. X-Git-Tag: v20.0.0.0~320 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=309b3032406639690d784138bde4cbb716059542;p=gem5.git kern,arch: Refactor SkipFuncEvent to not use skipFunction. Replace it with a new virtual function. Change-Id: I9d516d21ab3b1d1d70ea1297f984f868d3e7c3fb Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24111 Reviewed-by: Gabe Black Maintainer: Gabe Black Tested-by: kokoro --- diff --git a/src/arch/arm/freebsd/fs_workload.cc b/src/arch/arm/freebsd/fs_workload.cc index c248ff617..1792273d0 100644 --- a/src/arch/arm/freebsd/fs_workload.cc +++ b/src/arch/arm/freebsd/fs_workload.cc @@ -69,7 +69,7 @@ FsFreebsd::FsFreebsd(Params *p) : ArmISA::FsWorkload(p), "oops_exit", "Kernel oops in guest"); } - uDelaySkipEvent = addKernelFuncEvent( + uDelaySkipEvent = addKernelFuncEvent>( "DELAY", "DELAY", 1000, 0); } diff --git a/src/arch/arm/freebsd/fs_workload.hh b/src/arch/arm/freebsd/fs_workload.hh index 7f0ac083f..0e767a50c 100644 --- a/src/arch/arm/freebsd/fs_workload.hh +++ b/src/arch/arm/freebsd/fs_workload.hh @@ -88,7 +88,7 @@ class FsFreebsd : public ArmISA::FsWorkload * processor for the appropriate amount of time. This is not functionally * required but does speed up simulation. */ - FreeBSD::UDelayEvent *uDelaySkipEvent = nullptr; + FreeBSD::UDelayEvent *uDelaySkipEvent = nullptr; /** These variables store addresses of important data structures * that are normaly kept coherent at boot with cache mainetence operations. diff --git a/src/arch/arm/fs_workload.cc b/src/arch/arm/fs_workload.cc index ce9c464fe..b3dd6b5b8 100644 --- a/src/arch/arm/fs_workload.cc +++ b/src/arch/arm/fs_workload.cc @@ -51,6 +51,24 @@ namespace ArmISA { +void +SkipFunc::returnFromFuncIn(ThreadContext *tc) +{ + PCState newPC = tc->pcState(); + if (inAArch64(tc)) { + newPC.set(tc->readIntReg(INTREG_X30)); + } else { + newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1)); + } + + CheckerCPU *checker = tc->getCheckerCpuPtr(); + if (checker) { + tc->pcStateNoRecord(newPC); + } else { + tc->pcState(newPC); + } +} + FsWorkload::FsWorkload(Params *p) : OsKernel(*p) { bootLoaders.reserve(p->boot_loader.size()); diff --git a/src/arch/arm/fs_workload.hh b/src/arch/arm/fs_workload.hh index 936ddd7a4..5e97bba7a 100644 --- a/src/arch/arm/fs_workload.hh +++ b/src/arch/arm/fs_workload.hh @@ -52,6 +52,13 @@ namespace ArmISA { +class SkipFunc : public SkipFuncBase +{ + public: + using SkipFuncBase::SkipFuncBase; + void returnFromFuncIn(ThreadContext *tc) override; +}; + class FsWorkload : public OsKernel { protected: diff --git a/src/arch/arm/linux/fs_workload.cc b/src/arch/arm/linux/fs_workload.cc index 3f5744b1d..e6058baf8 100644 --- a/src/arch/arm/linux/fs_workload.cc +++ b/src/arch/arm/linux/fs_workload.cc @@ -224,21 +224,23 @@ FsLinux::startup() // With ARM udelay() is #defined to __udelay // newer kernels use __loop_udelay and __loop_const_udelay symbols - uDelaySkipEvent = addKernelFuncEvent( + uDelaySkipEvent = addKernelFuncEvent>( "__loop_udelay", "__udelay", 1000, 0); if (!uDelaySkipEvent) - uDelaySkipEvent = addKernelFuncEventOrPanic( + uDelaySkipEvent = addKernelFuncEventOrPanic>( "__udelay", "__udelay", 1000, 0); // constant arguments to udelay() have some precomputation done ahead of // time. Constant comes from code. - constUDelaySkipEvent = addKernelFuncEvent( + constUDelaySkipEvent = addKernelFuncEvent>( "__loop_const_udelay", "__const_udelay", 1000, 107374); if (!constUDelaySkipEvent) - constUDelaySkipEvent = addKernelFuncEventOrPanic( + constUDelaySkipEvent = + addKernelFuncEventOrPanic>( "__const_udelay", "__const_udelay", 1000, 107374); - debugPrintkEvent = addKernelFuncEvent("dprintk"); + debugPrintkEvent = + addKernelFuncEvent>("dprintk"); } void diff --git a/src/arch/arm/linux/fs_workload.hh b/src/arch/arm/linux/fs_workload.hh index aa771c8d9..5a798a84d 100644 --- a/src/arch/arm/linux/fs_workload.hh +++ b/src/arch/arm/linux/fs_workload.hh @@ -63,7 +63,7 @@ class FsLinux : public ArmISA::FsWorkload * PC based event to skip the dprink() call and emulate its * functionality */ - Linux::DebugPrintkEvent *debugPrintkEvent = nullptr; + Linux::DebugPrintkEvent *debugPrintkEvent = nullptr; DumpStatsPCEvent *dumpStatsPCEvent = nullptr; @@ -119,14 +119,14 @@ class FsLinux : public ArmISA::FsWorkload * processor for the appropriate amount of time. This is not functionally * required but does speed up simulation. */ - Linux::UDelayEvent *uDelaySkipEvent; + Linux::UDelayEvent *uDelaySkipEvent = nullptr; /** Another PC based skip event for const_udelay(). Similar to the udelay * skip, but this function precomputes the first multiply that is done * in the generic case since the parameter is known at compile time. * Thus we need to do some division to get back to us. */ - Linux::UDelayEvent *constUDelaySkipEvent; + Linux::UDelayEvent *constUDelaySkipEvent = nullptr; }; diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 8f81a3486..72b03be99 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -115,24 +115,6 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) panic("getArgument() should always return\n"); } -void -skipFunction(ThreadContext *tc) -{ - PCState newPC = tc->pcState(); - if (inAArch64(tc)) { - newPC.set(tc->readIntReg(INTREG_X30)); - } else { - newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1)); - } - - CheckerCPU *checker = tc->getCheckerCpuPtr(); - if (checker) { - tc->pcStateNoRecord(newPC); - } else { - tc->pcState(newPC); - } -} - static void copyVecRegs(ThreadContext *src, ThreadContext *dest) { diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 3d64bdd13..231b8b957 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -389,8 +389,6 @@ bool SPAlignmentCheckEnabled(ThreadContext* tc); uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp); -void skipFunction(ThreadContext *tc); - inline void advancePC(PCState &pc, const StaticInstPtr &inst) { diff --git a/src/arch/mips/linux/system.cc b/src/arch/mips/linux/system.cc index 4afb065c1..e9ba8699f 100644 --- a/src/arch/mips/linux/system.cc +++ b/src/arch/mips/linux/system.cc @@ -77,7 +77,7 @@ LinuxMipsSystem::setDelayLoop(ThreadContext *tc) void LinuxMipsSystem::SkipDelayLoopEvent::process(ThreadContext *tc) { - SkipFuncEvent::process(tc); + MipsISA::SkipFunc::process(tc); // calculate and set loops_per_jiffy ((LinuxMipsSystem *)tc->getSystemPtr())->setDelayLoop(tc); } diff --git a/src/arch/mips/linux/system.hh b/src/arch/mips/linux/system.hh index 4d1183391..8aa8ea5c1 100644 --- a/src/arch/mips/linux/system.hh +++ b/src/arch/mips/linux/system.hh @@ -47,11 +47,13 @@ class IdleStartEvent; class LinuxMipsSystem : public MipsSystem { private: - class SkipDelayLoopEvent : public SkipFuncEvent + using SkipFunc = MipsISA::SkipFunc; + + class SkipDelayLoopEvent : public SkipFunc { public: SkipDelayLoopEvent(PCEventScope *s, const std::string &desc, Addr addr) - : SkipFuncEvent(s, desc, addr) {} + : SkipFunc(s, desc, addr) {} virtual void process(ThreadContext *tc); }; diff --git a/src/arch/mips/system.cc b/src/arch/mips/system.cc index f925cb437..028d570a3 100644 --- a/src/arch/mips/system.cc +++ b/src/arch/mips/system.cc @@ -29,7 +29,8 @@ #include "arch/mips/system.hh" -#include "arch/vtophys.hh" +#include "arch/mips/registers.hh" +#include "arch/mips/vtophys.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" @@ -37,6 +38,14 @@ #include "params/MipsSystem.hh" #include "sim/byteswap.hh" +void +MipsISA::SkipFunc::returnFromFuncIn(ThreadContext *tc) +{ + MipsISA::PCState newPC = tc->pcState(); + newPC.set(tc->readIntReg(MipsISA::ReturnAddressReg)); + tc->pcState(newPC); +} + MipsSystem::MipsSystem(Params *p) : System(p) { } diff --git a/src/arch/mips/system.hh b/src/arch/mips/system.hh index f05bd1b52..87bf205b6 100644 --- a/src/arch/mips/system.hh +++ b/src/arch/mips/system.hh @@ -40,6 +40,20 @@ #include "sim/sim_object.hh" #include "sim/system.hh" + +namespace MipsISA +{ + +class SkipFunc : public SkipFuncBase +{ + public: + using SkipFuncBase::SkipFuncBase; + + void returnFromFuncIn(ThreadContext *tc) override; +}; + +} // namespace MipsaISA + class MipsSystem : public System { public: diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index c65a099b3..d2c964847 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -242,13 +242,5 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) { panic("Copy Misc. Regs Not Implemented Yet\n"); } -void -skipFunction(ThreadContext *tc) -{ - PCState newPC = tc->pcState(); - newPC.set(tc->readIntReg(ReturnAddressReg)); - tc->pcState(newPC); -} - } // namespace MipsISA diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index b0b1169af..c156c82cc 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -102,8 +102,6 @@ RoundPage(Addr addr) void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); -void skipFunction(ThreadContext *tc); - inline void advancePC(PCState &pc, const StaticInstPtr &inst) { diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc index 991a2720e..da4748ddb 100644 --- a/src/arch/power/utility.cc +++ b/src/arch/power/utility.cc @@ -62,10 +62,4 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) return 0; } -void -skipFunction(ThreadContext *tc) -{ - panic("Not Implemented for POWER"); -} - } // namespace PowerISA diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh index b2907aef1..ba28f0720 100644 --- a/src/arch/power/utility.hh +++ b/src/arch/power/utility.hh @@ -52,8 +52,6 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest) { } -void skipFunction(ThreadContext *tc); - inline void advancePC(PCState &pc, const StaticInstPtr &inst) { diff --git a/src/arch/riscv/utility.hh b/src/arch/riscv/utility.hh index deec64ec3..7dcd5e2fd 100644 --- a/src/arch/riscv/utility.hh +++ b/src/arch/riscv/utility.hh @@ -152,12 +152,6 @@ registerName(RegId reg) } } -inline void -skipFunction(ThreadContext *tc) -{ - panic("Not Implemented for Riscv"); -} - inline void advancePC(PCState &pc, const StaticInstPtr &inst) { diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index 5f3dae1a5..04fa7ad80 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -242,12 +242,4 @@ copyRegs(ThreadContext *src, ThreadContext *dest) dest->pcState(src->pcState()); } -void -skipFunction(ThreadContext *tc) -{ - PCState newPC = tc->pcState(); - newPC.set(tc->readIntReg(ReturnAddressReg)); - tc->pcState(newPC); -} - } // namespace SPARC_ISA diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 0a29c6bfc..4738eb438 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -64,8 +64,6 @@ void copyRegs(ThreadContext *src, ThreadContext *dest); void copyMiscRegs(ThreadContext *src, ThreadContext *dest); -void skipFunction(ThreadContext *tc); - inline void advancePC(PCState &pc, const StaticInstPtr &inst) { diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index e88cc7f74..33b9371b5 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -106,12 +106,6 @@ copyRegs(ThreadContext *src, ThreadContext *dest) dest->pcState(src->pcState()); } -void -skipFunction(ThreadContext *tc) -{ - panic("Not implemented for x86\n"); -} - uint64_t getRFlags(ThreadContext *tc) { diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 026132327..b311eefcd 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -71,8 +71,6 @@ namespace X86ISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest); - void skipFunction(ThreadContext *tc); - inline void advancePC(PCState &pc, const StaticInstPtr &inst) { diff --git a/src/kern/freebsd/events.cc b/src/kern/freebsd/events.cc index a9e2854db..b100860e5 100644 --- a/src/kern/freebsd/events.cc +++ b/src/kern/freebsd/events.cc @@ -45,7 +45,7 @@ namespace FreeBSD { void -UDelayEvent::process(ThreadContext *tc) +onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul) { int arg_num; @@ -57,12 +57,10 @@ UDelayEvent::process(ThreadContext *tc) //DPRINTFN("DELAY(%d)\n", time); // convert parameter to ns - if (argDivToNs) - time /= argDivToNs; + if (div) + time /= div; - time *= argMultToNs; - - SkipFuncEvent::process(tc); + time *= mul; // Currently, only ARM full-system simulation uses UDelayEvents to skip // __delay and __loop_delay functions. One form involves setting quiesce diff --git a/src/kern/freebsd/events.hh b/src/kern/freebsd/events.hh index ebee3e084..2c548b52d 100644 --- a/src/kern/freebsd/events.hh +++ b/src/kern/freebsd/events.hh @@ -37,12 +37,15 @@ namespace FreeBSD { +void onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul); + /** A class to skip udelay() and related calls in the kernel. * This class has two additional parameters that take the argument to udelay and * manipulated it to come up with ns and eventually ticks to quiesce for. * See descriptions of argDivToNs and argMultToNs below. */ -class UDelayEvent : public SkipFuncEvent +template +class UDelayEvent : public Base { private: /** value to divide arg by to create ns. This is present beacues the linux @@ -59,8 +62,14 @@ class UDelayEvent : public SkipFuncEvent public: UDelayEvent(PCEventScope *s, const std::string &desc, Addr addr, uint64_t mult, uint64_t div) - : SkipFuncEvent(s, desc, addr), argDivToNs(div), argMultToNs(mult) {} - virtual void process(ThreadContext *xc); + : Base(s, desc, addr), argDivToNs(div), argMultToNs(mult) {} + + void + process(ThreadContext *tc) override + { + onUDelay(tc, argDivToNs, argMultToNs); + Base::process(tc); + } }; } diff --git a/src/kern/linux/events.cc b/src/kern/linux/events.cc index 3c0cbbf88..d548b7279 100644 --- a/src/kern/linux/events.cc +++ b/src/kern/linux/events.cc @@ -58,7 +58,7 @@ namespace Linux { void -DebugPrintkEvent::process(ThreadContext *tc) +onDebugPrintk(ThreadContext *tc) { if (DTRACE(DebugPrintf)) { std::stringstream ss; @@ -67,38 +67,11 @@ DebugPrintkEvent::process(ThreadContext *tc) StringWrap name(tc->getSystemPtr()->name() + ".dprintk"); DPRINTFN("%s", ss.str()); } - SkipFuncEvent::process(tc); -} - -void -UDelayEvent::process(ThreadContext *tc) -{ - int arg_num = 0; - - // Get the time in native size - uint64_t time = TheISA::getArgument(tc, arg_num, (uint16_t)-1, false); - - // convert parameter to ns - if (argDivToNs) - time /= argDivToNs; - - time *= argMultToNs; - - SkipFuncEvent::process(tc); - - // Currently, only ARM full-system simulation uses UDelayEvents to skip - // __delay and __loop_delay functions. One form involves setting quiesce - // time to 0 with the assumption that quiesce will not happen. To avoid - // the quiesce handling in this case, only execute the quiesce if time > 0. - if (time > 0) - tc->quiesceTick(curTick() + SimClock::Int::ns * time); } void DmesgDumpEvent::process(ThreadContext *tc) { - StringWrap name(tc->getCpuPtr()->name() + ".dmesg_dump_event"); - inform("Dumping kernel dmesg buffer to %s...\n", fname); OutputStream *os = simout.create(fname); dumpDmesg(tc, *os->stream()); @@ -110,8 +83,6 @@ DmesgDumpEvent::process(ThreadContext *tc) void KernelPanicEvent::process(ThreadContext *tc) { - StringWrap name(tc->getCpuPtr()->name() + ".dmesg_dump_event"); - inform("Dumping kernel dmesg buffer to %s...\n", fname); OutputStream *os = simout.create(fname); dumpDmesg(tc, *os->stream()); @@ -120,4 +91,26 @@ KernelPanicEvent::process(ThreadContext *tc) panic(descr()); } +void +onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul) +{ + int arg_num = 0; + + // Get the time in native size + uint64_t time = TheISA::getArgument(tc, arg_num, (uint16_t)-1, false); + + // convert parameter to ns + if (div) + time /= div; + + time *= mul; + + // Currently, only ARM full-system simulation uses UDelayEvents to skip + // __delay and __loop_delay functions. One form involves setting quiesce + // time to 0 with the assumption that quiesce will not happen. To avoid + // the quiesce handling in this case, only execute the quiesce if time > 0. + if (time > 0) + tc->quiesceTick(curTick() + SimClock::Int::ns * time); +} + } // namespace linux diff --git a/src/kern/linux/events.hh b/src/kern/linux/events.hh index ed2df2374..b16e6ead1 100644 --- a/src/kern/linux/events.hh +++ b/src/kern/linux/events.hh @@ -45,12 +45,20 @@ namespace Linux { -class DebugPrintkEvent : public SkipFuncEvent +void onDebugPrintk(ThreadContext *tc); + +template +class DebugPrintkEvent : public Base { public: DebugPrintkEvent(PCEventScope *s, const std::string &desc, Addr addr) - : SkipFuncEvent(s, desc, addr) {} - virtual void process(ThreadContext *xc); + : Base(s, desc, addr) {} + virtual void + process(ThreadContext *tc) + { + onDebugPrintk(tc); + Base::process(tc); + } }; /** @@ -70,7 +78,7 @@ class DmesgDumpEvent : public PCEvent DmesgDumpEvent(PCEventScope *s, const std::string &desc, Addr addr, const std::string &_fname) : PCEvent(s, desc, addr), fname(_fname) {} - virtual void process(ThreadContext *xc); + virtual void process(ThreadContext *tc); }; /** @@ -90,15 +98,19 @@ class KernelPanicEvent : public PCEvent KernelPanicEvent(PCEventScope *s, const std::string &desc, Addr addr, const std::string &_fname) : PCEvent(s, desc, addr), fname(_fname) {} - virtual void process(ThreadContext *xc); + virtual void process(ThreadContext *tc); }; -/** A class to skip udelay() and related calls in the kernel. - * This class has two additional parameters that take the argument to udelay and - * manipulated it to come up with ns and eventually ticks to quiesce for. +void onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul); + +/** + * A class to skip udelay() and related calls in the kernel. + * This class has two additional parameters that take the argument to udelay + * and manipulated it to come up with ns and eventually ticks to quiesce for. * See descriptions of argDivToNs and argMultToNs below. */ -class UDelayEvent : public SkipFuncEvent +template +class UDelayEvent : public Base { private: /** value to divide arg by to create ns. This is present beacues the linux @@ -115,10 +127,15 @@ class UDelayEvent : public SkipFuncEvent public: UDelayEvent(PCEventScope *s, const std::string &desc, Addr addr, uint64_t mult, uint64_t div) - : SkipFuncEvent(s, desc, addr), argDivToNs(div), argMultToNs(mult) {} - virtual void process(ThreadContext *xc); -}; + : Base(s, desc, addr), argDivToNs(div), argMultToNs(mult) {} + virtual void + process(ThreadContext *tc) + { + onUDelay(tc, argDivToNs, argMultToNs); + Base::process(tc); + } +}; } diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc index e865be56c..d97b766bd 100644 --- a/src/kern/system_events.cc +++ b/src/kern/system_events.cc @@ -28,19 +28,17 @@ #include "kern/system_events.hh" -#include "arch/utility.hh" #include "base/trace.hh" -#include "config/the_isa.hh" #include "cpu/thread_context.hh" #include "debug/PCEvent.hh" void -SkipFuncEvent::process(ThreadContext *tc) +SkipFuncBase::process(ThreadContext *tc) { TheISA::PCState oldPC M5_VAR_USED = tc->pcState(); - // Call ISA specific code to do the skipping - TheISA::skipFunction(tc); + returnFromFuncIn(tc); + DPRINTF(PCEvent, "skipping %s: pc = %s, newpc = %s\n", description, oldPC, tc->pcState()); } diff --git a/src/kern/system_events.hh b/src/kern/system_events.hh index 83ed37fb6..ecae03c6f 100644 --- a/src/kern/system_events.hh +++ b/src/kern/system_events.hh @@ -31,12 +31,16 @@ #include "cpu/pc_event.hh" -class SkipFuncEvent : public PCEvent +class SkipFuncBase : public PCEvent { + protected: + virtual void returnFromFuncIn(ThreadContext *tc) = 0; + public: - SkipFuncEvent(PCEventScope *s, const std::string &desc, Addr addr) + SkipFuncBase(PCEventScope *s, const std::string &desc, Addr addr) : PCEvent(s, desc, addr) {} + void process(ThreadContext *tc) override; };