arch-riscv: Add PCEvent for RISCV FS Workload kernel panic/oops
Inspired by a similar feature in ARM's full system workload, this change adds an option to halt gem5 simulation if the guest system encounter kernel panic or kernel oops. On RiscvISA::BootloaderKernelWorkload, by default, the simulation will exit upon kernel panic, while kernel oops will not induce simulation halt. This is because the system will essentially do nop after a kernel panic, while the system might be still functional after a kernel oops. Dumping kernel's dmesg is useful for diagonizing the cause of kernel panic, so ideally, we want to dump the guest's dmesg to the host. However, due to a bug described in [1], kernel v5.18+ dmesg might not be dumped properly. Hence, the dmesg will not be dumped to the host. On RiscvISA::FsLinux, this feature is turned off by default as the symbols from the official RISC-V kernel resource are stripped from the binary. However, if this feature is enable, the dmesg will be dumped to the host system. [1] https://github.com/gem5/gem5/issues/550 Change-Id: I8f52257727a3a789ebf99fdd4dffe5b3d89f1ebf Signed-off-by: Hoa Nguyen <hn@hnpl.org> Co-authored-by: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
committed by
Jason Lowe-Power
parent
569e21f798
commit
cf087d4d11
@@ -55,6 +55,16 @@ class RiscvLinux(KernelWorkload):
|
||||
)
|
||||
dtb_addr = Param.Addr(0x87E00000, "DTB address")
|
||||
|
||||
# gem5 event upon guest's kernel panic
|
||||
# Default to false because when the kernel is compiled into the bootloader
|
||||
# it will not have symbols
|
||||
exit_on_kernel_panic = Param.Bool(
|
||||
False, "Generate gem5 panic upon the guest's kernel panic."
|
||||
)
|
||||
exit_on_kernel_oops = Param.Bool(
|
||||
False, "Generate gem5 panic upon the guest's kernel oops."
|
||||
)
|
||||
|
||||
|
||||
class RiscvBootloaderKernelWorkload(Workload):
|
||||
type = "RiscvBootloaderKernelWorkload"
|
||||
@@ -84,5 +94,28 @@ class RiscvBootloaderKernelWorkload(Workload):
|
||||
|
||||
# booting parameters
|
||||
command_line = Param.String(
|
||||
"", "Booting arguments, to be passed to the kernel"
|
||||
"", "Booting arguments, to be passed to the kernel."
|
||||
)
|
||||
|
||||
# gem5 event upon guest's kernel panic
|
||||
# Note that if the kernel doesn't have symbols there will be a warning and
|
||||
# gem5 will not exit
|
||||
exit_on_kernel_panic = Param.Bool(
|
||||
True, "Generate gem5 exit upon the guest's kernel panic."
|
||||
)
|
||||
exit_on_kernel_oops = Param.Bool(
|
||||
False, "Generate gem5 exit upon the guest's kernel oops."
|
||||
)
|
||||
|
||||
# Note: Duplicated from KernelWorkload for now
|
||||
on_panic = Param.KernelPanicOopsBehaviour(
|
||||
"DumpDmesgAndExit",
|
||||
"Define how gem5 should behave after a Linux Kernel Panic. "
|
||||
"Handler might not be implemented for all architectures.",
|
||||
)
|
||||
|
||||
on_oops = Param.KernelPanicOopsBehaviour(
|
||||
"DumpDmesgAndExit",
|
||||
"Define how gem5 should behave after a Linux Kernel Oops. "
|
||||
"Handler might not be implemented for all architectures.",
|
||||
)
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
#include "base/loader/dtb_file.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "cpu/pc_event.hh"
|
||||
#include "kern/linux/events.hh"
|
||||
#include "sim/kernel_workload.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
namespace gem5
|
||||
@@ -75,6 +78,42 @@ FsLinux::initState()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FsLinux::startup()
|
||||
{
|
||||
KernelWorkload::startup();
|
||||
|
||||
addExitOnKernelPanicEvent();
|
||||
addExitOnKernelOopsEvent();
|
||||
}
|
||||
|
||||
void
|
||||
FsLinux::addExitOnKernelPanicEvent()
|
||||
{
|
||||
const std::string dmesg_output = name() + ".dmesg";
|
||||
if (params().exit_on_kernel_panic) {
|
||||
kernelPanicPcEvent = addKernelFuncEvent<linux::PanicOrOopsEvent>(
|
||||
"panic", "Kernel panic in simulated system.",
|
||||
dmesg_output, params().on_panic
|
||||
);
|
||||
warn_if(!kernelPanicPcEvent, "Failed to find kernel symbol 'panic'");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FsLinux::addExitOnKernelOopsEvent()
|
||||
{
|
||||
const std::string dmesg_output = name() + ".dmesg";
|
||||
if (params().exit_on_kernel_oops) {
|
||||
kernelOopsPcEvent = addKernelFuncEvent<linux::PanicOrOopsEvent>(
|
||||
"oops_exit", "Kernel oops in simulated system.",
|
||||
dmesg_output, params().on_oops
|
||||
);
|
||||
warn_if(!kernelOopsPcEvent,
|
||||
"Failed to find kernel symbol 'oops_exit'");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BootloaderKernelWorkload::loadBootloaderSymbolTable()
|
||||
{
|
||||
@@ -169,6 +208,30 @@ BootloaderKernelWorkload::loadDtb()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BootloaderKernelWorkload::addExitOnKernelPanicEvent()
|
||||
{
|
||||
const std::string dmesg_output = name() + ".dmesg";
|
||||
if (params().exit_on_kernel_panic) {
|
||||
kernelPanicPcEvent = addFuncEvent<linux::PanicOrOopsEvent>(
|
||||
kernelSymbolTable, "panic", "Kernel panic in simulated system.",
|
||||
dmesg_output, params().on_panic
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BootloaderKernelWorkload::addExitOnKernelOopsEvent()
|
||||
{
|
||||
const std::string dmesg_output = name() + ".dmesg";
|
||||
if (params().exit_on_kernel_oops) {
|
||||
kernelOopsPcEvent = addFuncEvent<linux::PanicOrOopsEvent>(
|
||||
kernelSymbolTable, "oops_exit", "Kernel oops in simulated system.",
|
||||
dmesg_output, params().on_oops
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BootloaderKernelWorkload::initState()
|
||||
{
|
||||
@@ -182,6 +245,15 @@ BootloaderKernelWorkload::initState()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BootloaderKernelWorkload::startup()
|
||||
{
|
||||
Workload::startup();
|
||||
|
||||
addExitOnKernelPanicEvent();
|
||||
addExitOnKernelOopsEvent();
|
||||
}
|
||||
|
||||
void
|
||||
BootloaderKernelWorkload::serialize(CheckpointOut &checkpoint) const
|
||||
{
|
||||
|
||||
@@ -44,11 +44,30 @@ namespace RiscvISA
|
||||
|
||||
class FsLinux : public KernelWorkload
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Event to halt the simulator if the kernel calls panic() or
|
||||
* oops_exit()
|
||||
**/
|
||||
PCEvent *kernelPanicPcEvent = nullptr;
|
||||
PCEvent *kernelOopsPcEvent = nullptr;
|
||||
void addExitOnKernelPanicEvent();
|
||||
void addExitOnKernelOopsEvent();
|
||||
public:
|
||||
PARAMS(RiscvLinux);
|
||||
FsLinux(const Params &p) : KernelWorkload(p) {}
|
||||
~FsLinux()
|
||||
{
|
||||
if (kernelPanicPcEvent != nullptr) {
|
||||
delete kernelPanicPcEvent;
|
||||
}
|
||||
if (kernelOopsPcEvent != nullptr) {
|
||||
delete kernelOopsPcEvent;
|
||||
}
|
||||
}
|
||||
|
||||
void initState() override;
|
||||
void startup() override;
|
||||
|
||||
void
|
||||
setSystem(System *sys) override
|
||||
@@ -71,12 +90,21 @@ class BootloaderKernelWorkload: public Workload
|
||||
loader::SymbolTable bootloaderSymbolTable;
|
||||
const std::string bootArgs;
|
||||
|
||||
/**
|
||||
* Event to halt the simulator if the kernel calls panic() or
|
||||
* oops_exit()
|
||||
**/
|
||||
PCEvent *kernelPanicPcEvent = nullptr;
|
||||
PCEvent *kernelOopsPcEvent = nullptr;
|
||||
|
||||
private:
|
||||
void loadBootloaderSymbolTable();
|
||||
void loadKernelSymbolTable();
|
||||
void loadBootloader();
|
||||
void loadKernel();
|
||||
void loadDtb();
|
||||
void addExitOnKernelPanicEvent();
|
||||
void addExitOnKernelOopsEvent();
|
||||
|
||||
public:
|
||||
PARAMS(RiscvBootloaderKernelWorkload);
|
||||
@@ -87,7 +115,18 @@ class BootloaderKernelWorkload: public Workload
|
||||
loadKernelSymbolTable();
|
||||
}
|
||||
|
||||
~BootloaderKernelWorkload()
|
||||
{
|
||||
if (kernelPanicPcEvent != nullptr) {
|
||||
delete kernelPanicPcEvent;
|
||||
}
|
||||
if (kernelOopsPcEvent != nullptr) {
|
||||
delete kernelOopsPcEvent;
|
||||
}
|
||||
}
|
||||
|
||||
void initState() override;
|
||||
void startup() override;
|
||||
|
||||
void
|
||||
setSystem(System *sys) override
|
||||
|
||||
Reference in New Issue
Block a user