diff --git a/src/arch/riscv/RiscvFsWorkload.py b/src/arch/riscv/RiscvFsWorkload.py index 467d7ec26a..24dff58828 100644 --- a/src/arch/riscv/RiscvFsWorkload.py +++ b/src/arch/riscv/RiscvFsWorkload.py @@ -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.", ) diff --git a/src/arch/riscv/linux/fs_workload.cc b/src/arch/riscv/linux/fs_workload.cc index da1af8d59b..309d324bcb 100644 --- a/src/arch/riscv/linux/fs_workload.cc +++ b/src/arch/riscv/linux/fs_workload.cc @@ -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( + "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( + "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( + 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( + 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 { diff --git a/src/arch/riscv/linux/fs_workload.hh b/src/arch/riscv/linux/fs_workload.hh index 95269e6f93..c5fcd70eb0 100644 --- a/src/arch/riscv/linux/fs_workload.hh +++ b/src/arch/riscv/linux/fs_workload.hh @@ -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