sim: Rework the Linux Kernel exit events (#639)

This patch reworks the Linux Kernel panic and oops events. The code has
been re-factored to provide re-usable events that can be applied to all
ISAs from the base `KernelWorkload` `SimObject`. At the moment they are
installed for the Arm workloads.

This update also provides more configuration options that can be
specified using the new `KernelPanicOopsBehaviour` enum. The options are
applied to the Kernel Workload parameters `on_panic` and `on_oops` which
are available to all subclasses of `KernelWorkload`.

The main rationale for this reworking is to add the option to cleanly
exit the simulation after dumping the Dmesg buffer. Without this option,
the simulation would continue running after a Kernel panic. If system
components (e.g. a system timer) keep the event queue alive, this causes
the simulation to run slowly to the maximum allowed tick.
This commit is contained in:
Richard Cooper
2023-12-02 01:33:59 +00:00
committed by GitHub
parent ecb72b74f8
commit d9c870f641
5 changed files with 89 additions and 61 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2013, 2016, 2020 ARM Limited
* Copyright (c) 2010-2013, 2016, 2020, 2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -228,21 +228,22 @@ FsLinux::startup()
}
}
const std::string dmesg_output = name() + ".dmesg";
if (params().panic_on_panic) {
kernelPanic = addKernelFuncEventOrPanic<linux::KernelPanic>(
"panic", "Kernel panic in simulated kernel", dmesg_output);
} else {
kernelPanic = addKernelFuncEventOrPanic<linux::DmesgDump>(
"panic", "Kernel panic in simulated kernel", dmesg_output);
const std::string dmesg_output_fname = name() + ".dmesg";
kernelPanic = addKernelFuncEvent<linux::PanicOrOopsEvent>(
"panic", "Kernel panic in simulated kernel",
dmesg_output_fname, params().on_panic);
if (kernelPanic == nullptr) {
warn("Could not add Kernel Panic event handler. "
"`panic` symbol not found.");
}
if (params().panic_on_oops) {
kernelOops = addKernelFuncEventOrPanic<linux::KernelPanic>(
"oops_exit", "Kernel oops in guest", dmesg_output);
} else {
kernelOops = addKernelFuncEventOrPanic<linux::DmesgDump>(
"oops_exit", "Kernel oops in guest", dmesg_output);
kernelOops = addKernelFuncEvent<linux::PanicOrOopsEvent>(
"oops_exit", "Kernel oops in guest",
dmesg_output_fname, params().on_oops);
if (kernelOops == nullptr) {
warn("Could not add Kernel Oops event handler. "
"`oops_exit` symbol not found.");
}
// With ARM udelay() is #defined to __udelay

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2016 ARM Limited
* Copyright (c) 2011, 2016, 2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -49,6 +49,7 @@
#include "kern/linux/helpers.hh"
#include "kern/system_events.hh"
#include "sim/core.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
namespace gem5
@@ -58,25 +59,22 @@ namespace linux
{
void
DmesgDump::process(ThreadContext *tc)
PanicOrOopsEvent::process(ThreadContext *tc)
{
inform("Dumping kernel dmesg buffer to %s...\n", fname);
OutputStream *os = simout.create(fname);
dumpDmesg(tc, *os->stream());
simout.close(os);
warn(descr());
}
void
KernelPanic::process(ThreadContext *tc)
{
inform("Dumping kernel dmesg buffer to %s...\n", fname);
OutputStream *os = simout.create(fname);
dumpDmesg(tc, *os->stream());
simout.close(os);
if (behaviour != KernelPanicOopsBehaviour::Continue) {
inform("Dumping kernel dmesg buffer to %s...\n", fname);
OutputStream *os = simout.create(fname);
dumpDmesg(tc, *os->stream());
simout.close(os);
}
panic(descr());
if (behaviour == KernelPanicOopsBehaviour::DumpDmesgAndExit) {
exitSimLoop(descr(), static_cast<int>(1), curTick(), false);
} else if (behaviour == KernelPanicOopsBehaviour::DumpDmesgAndPanic) {
panic(descr());
}
}
void

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 ARM Limited
* Copyright (c) 2016, 2023 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -47,6 +47,7 @@
#include "base/compiler.hh"
#include "base/trace.hh"
#include "debug/DebugPrintf.hh"
#include "enums/KernelPanicOopsBehaviour.hh"
#include "kern/linux/printk.hh"
#include "kern/system_events.hh"
#include "mem/se_translating_port_proxy.hh"
@@ -83,43 +84,25 @@ class DebugPrintk : public Base
};
/**
* Dump the guest kernel's dmesg buffer to a file in gem5's output
* directory and print a warning.
* Specify what to do on a Linux Kernel Panic or Oops.
*
* @warn This event uses linux::dumpDmesg() and comes with the same
* @warn This event may use linux::dumpDmesg() and comes with the same
* limitations. Most importantly, the kernel's address mappings must
* be available to the translating proxy.
*/
class DmesgDump : public PCEvent
class PanicOrOopsEvent : public PCEvent
{
protected:
std::string fname;
KernelPanicOopsBehaviour behaviour;
public:
DmesgDump(PCEventScope *s, const std::string &desc, Addr addr,
const std::string &_fname) :
PCEvent(s, desc, addr), fname(_fname)
{}
void process(ThreadContext *tc) override;
};
/**
* Dump the guest kernel's dmesg buffer to a file in gem5's output
* directory and panic.
*
* @warn This event uses linux::dumpDmesg() and comes with the same
* limitations. Most importantly, the kernel's address mappings must
* be available to the translating proxy.
*/
class KernelPanic : public PCEvent
{
protected:
std::string fname;
public:
KernelPanic(PCEventScope *s, const std::string &desc, Addr addr,
const std::string &_fname) :
PCEvent(s, desc, addr), fname(_fname)
PanicOrOopsEvent(PCEventScope *s, const std::string &desc, Addr addr,
const std::string &_fname,
const KernelPanicOopsBehaviour _behaviour)
: PCEvent(s, desc, addr)
, fname(_fname)
, behaviour(_behaviour)
{}
void process(ThreadContext *tc) override;
};

View File

@@ -1,5 +1,16 @@
# -*- mode:python -*-
# Copyright (c) 2023 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright (c) 2006 The Regents of The University of Michigan
# All rights reserved.
#
@@ -31,7 +42,8 @@ Import('*')
SimObject('ClockedObject.py', sim_objects=['ClockedObject'])
SimObject('TickedObject.py', sim_objects=['TickedObject'])
SimObject('Workload.py', sim_objects=[
'Workload', 'StubWorkload', 'KernelWorkload', 'SEWorkload'])
'Workload', 'StubWorkload', 'KernelWorkload', 'SEWorkload'],
enums=['KernelPanicOopsBehaviour'])
SimObject('Root.py', sim_objects=['Root'])
SimObject('ClockDomain.py', sim_objects=[
'ClockDomain', 'SrcClockDomain', 'DerivedClockDomain'])

View File

@@ -1,3 +1,15 @@
# Copyright (c) 2023 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Copyright 2019 Google Inc.
#
# Redistribution and use in source and binary forms, with or without
@@ -62,6 +74,16 @@ class StubWorkload(Workload):
)
class KernelPanicOopsBehaviour(ScopedEnum):
"Define what gem5 should do after a Kernel Panic or Oops."
vals = [
"Continue",
"DumpDmesgAndContinue",
"DumpDmesgAndExit",
"DumpDmesgAndPanic",
]
class KernelWorkload(Workload):
type = "KernelWorkload"
cxx_header = "sim/kernel_workload.hh"
@@ -86,6 +108,18 @@ class KernelWorkload(Workload):
command_line = Param.String("a", "boot flags to pass to the kernel")
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.",
)
class SEWorkloadMeta(type(Workload)):
all_se_workload_classes = []