kern module is the translator between simulated programs and the host OS. When a program running inside gem5 calls stat() or open(), the simulator needs to know the exact byte layout of structures like struct stat for the target OS (Linux, FreeBSD, or Solaris). kern provides those OS-specific type definitions โ think of it as a phrase book that translates between "Linux-speak" and "gem5-speak."
Table of Contents
Architecture Overview
The kern module provides OS-specific type definitions, structure layouts, and kernel event handlers needed by gem5's syscall emulation (SE) and full-system (FS) modes. It defines the target-side view of syscall structures โ struct stat, struct rusage, utsname, etc. โ so the simulator can correctly marshal data between simulated user programs and host-side implementations.
flowchart TD
App["Simulated Application"]
SE["Syscall Emulation Layer"]
OS["OperatingSystem (base)"]
LIN["Linux"]
BSD["FreeBSD"]
SOL["Solaris"]
EVT["System Events"]
SKIP["SkipFuncBase"]
PANIC["PanicOrOopsEvent"]
DMESG["dumpDmesg()"]
App -->|"syscall"| SE
SE --> OS
OS --> LIN
OS --> BSD
OS --> SOL
LIN --> EVT
EVT --> SKIP
EVT --> PANIC
PANIC --> DMESG
The module is intentionally small (~2.6K LOC across 17 files), as it primarily defines data structures and event hooks rather than complex logic. Each OS subclass inherits from OperatingSystem and provides target-specific structure layouts that the syscall emulation layer uses for data marshalling.
OS Class Hierarchy
classDiagram
class OperatingSystem {
+tgt_stat
+tgt_stat64
+utsname
+rlimit
+timeval
+rusage
+tgt_iovec
}
class Linux {
+size_t : uint64_t
+off_t : int64_t
+uid_t : uint32_t
+gid_t : uint32_t
+tgt_stat
+tgt_stat64
}
class FreeBSD {
+size_t : uint64_t
+isTtyReq()
+TIOCGETA
+TIOCSETA
}
class Solaris {
+rlim_t : uint64_t
+tgt_timespec
+tgt_stat
}
OperatingSystem <|-- Linux
OperatingSystem <|-- FreeBSD
OperatingSystem <|-- Solaris
Each OS subclass provides the same set of target structures but with OS-specific field layouts, sizes, and constants. The syscall emulation code is templated on the OS type, so it automatically uses the correct structure definitions for the simulated operating system.
Key Classes
| Class | Parent | File | Description |
|---|---|---|---|
OperatingSystem | โ | operatingsystem.hh | Abstract base: defines target syscall struct interfaces |
Linux | OperatingSystem | linux/linux.hh | Linux-specific types: stat, stat64, uid_t, gid_t, signal constants |
FreeBSD | OperatingSystem | freebsd/freebsd.hh | FreeBSD types and ioctl codes (TIOCGETA, FIONREAD) |
Solaris | OperatingSystem | solaris/solaris.hh | Solaris/SunOS types: rlim_t, tgt_timespec, tgt_stat |
SkipFuncBase | PCEvent | system_events.hh | Base class for function-skipping events at specific PCs |
PanicOrOopsEvent | PCEvent | linux/events.hh | Handles kernel panic/oops: configurable halt, warn, or dmesg dump |
DebugPrintk | template | linux/events.hh | Captures kernel printk output during full-system simulation |
dumpDmesg() | function | linux/helpers.hh | Extracts kernel log ring buffer for debugging |
Deep Dive: Linux Support
Type Definitions
The Linux class defines target-architecture types that match the Linux kernel's ABI. These are used by syscall emulation to correctly convert between simulated and host representations:
| Target Type | C++ Type | Size | Usage |
|---|---|---|---|
size_t | uint64_t | 8 bytes | Buffer sizes, counts |
off_t | int64_t | 8 bytes | File offsets |
time_t | int64_t | 8 bytes | Timestamps |
clock_t | int64_t | 8 bytes | CPU clock ticks |
uid_t | uint32_t | 4 bytes | User IDs |
gid_t | uint32_t | 4 bytes | Group IDs |
dev_t | uint64_t | 8 bytes | Device numbers |
ino_t | uint64_t | 8 bytes | Inode numbers |
stat Structures
Linux defines two stat structure variants, matching the kernel's 32-bit and 64-bit ABIs:
tgt_statโ 32-bit stat structure withst_dev,st_ino,st_mode,st_nlink,st_uid,st_gid,st_size,st_atime, etc.tgt_stat64โ 64-bit stat structure with wider fields for large file support
Architecture-specific variants exist under kern/linux/ subdirectories for AArch32, AArch64, TrustZone security extensions, SVE/SVE2 vector processing, PMU, and hardware transactional memory." href="../arch_doc/arm/index.html">ARM, x86, MIPS, SPARC, and RISC-V, handling ABI differences like padding and field ordering.
Linux Kernel Events
In full-system mode, kern/linux/events.hh provides PC-based event hooks for kernel debugging:
๐จ PanicOrOopsEvent
Triggers when the kernel hits a panic() or oops() address. Configurable behaviour: halt simulation, print warning, or dump dmesg buffer. Controlled by KernelPanicOopsBehaviour enum.
๐ DebugPrintk
Template class that intercepts kernel printk() calls, extracting the format string and arguments from simulated memory for console output during boot.
๐ dumpDmesg
Helper function that reads the kernel log ring buffer (__log_buf) from simulated memory using SETranslatingPortProxy. Essential for diagnosing boot failures.
Deep Dive: Kernel Events
Function Skipping
SkipFuncBase enables the simulator to skip expensive or problematic kernel functions during full-system simulation. When the PC matches a registered address, the event handler manipulates the thread context to return from the function immediately:
sequenceDiagram
participant CPU as CPU Core
participant PC as PCEvent System
participant SF as SkipFuncBase
CPU->>PC: PC matches registered address
PC->>SF: process(ThreadContext*)
SF->>SF: Capture return address
SF->>SF: Set PC = return address
SF->>CPU: Continue execution (function skipped)
This mechanism is used to skip slow initialization routines, hardware probes, and other functions that would take millions of simulated cycles without contributing useful information.
Panic/Oops Handling
The PanicOrOopsEvent class responds to kernel panics with configurable actions:
| Behaviour | Action |
|---|---|
PanicOnOops | Halt simulation immediately, dump dmesg |
WarnOnOops | Print warning, dump dmesg, continue simulation |
IgnoreOnOops | Silently continue execution |
Type Mapping Tables
stat Structure Comparison
| Field | Linux | FreeBSD | Solaris |
|---|---|---|---|
st_dev | uint64_t | uint64_t | uint64_t |
st_ino | uint64_t | uint64_t | uint64_t |
st_mode | uint32_t | uint16_t | uint32_t |
st_nlink | uint64_t | uint64_t | uint32_t |
st_uid | uint32_t | uint32_t | uint32_t |
st_gid | uint32_t | uint32_t | uint32_t |
st_size | int64_t | int64_t | int64_t |
st_atime | uint64_t | int64_t | int64_t |
FreeBSD ioctl Codes
| Constant | Value | Purpose |
|---|---|---|
TIOCGETA | platform-specific | Get terminal attributes |
TIOCSETA | platform-specific | Set terminal attributes |
FIONREAD | platform-specific | Get bytes available to read |
The FreeBSD::isTtyReq() method validates whether an ioctl code is a recognized TTY request, returning true for the supported set.
Cross-Module Interactions
| Dependency | Module | Purpose |
|---|---|---|
| Syscall emulation | sim/syscall_emul | Uses OS type definitions for syscall data marshalling |
| Process model | sim/process | Process objects are templated on OS type |
| Thread context | cpu | PCEvent system hooks into CPU execution |
| Memory proxy | mem | SETranslatingPortProxy for kernel memory access |
| Base utilities | base | Types, random, trace, compiler attributes |
| Arch-specific | arch/*/linux | Architecture-specific stat struct variants |
Directory Map
Configuration & Usage
Syscall Emulation Mode
In SE mode, the kern module is used implicitly โ when you create a Process with a Linux binary, the syscall emulation layer automatically uses the Linux class for structure marshalling. No explicit configuration is needed.
Full-System Mode
In FS mode, kernel event handlers are registered at boot time. Key configuration points:
| Parameter | Location | Description |
|---|---|---|
panic_on_oops | System config | Enable PanicOrOopsEvent at kernel panic address |
kernel_panic_oops_behaviour | System config | Action on panic: halt, warn, or ignore |
skip_functions | System config | List of kernel functions to skip during boot |
kernel_addr_check | Boot loader | Verify kernel symbol addresses for event registration |
Code Examples
OS Type Definitions
// kern/linux/linux.hh โ Linux target type definitions
class Linux : public OperatingSystem
{
public:
using size_t = uint64_t;
using off_t = int64_t;
using time_t = int64_t;
using clock_t = int64_t;
using uid_t = uint32_t;
using gid_t = uint32_t;
struct tgt_stat64 {
uint64_t st_dev;
uint64_t st_ino;
uint64_t st_nlink;
uint32_t st_mode;
uint32_t st_uid;
uint32_t st_gid;
uint64_t st_rdev;
int64_t st_size;
int64_t st_blksize;
int64_t st_blocks;
uint64_t st_atimeX;
uint64_t st_atime_nsec;
uint64_t st_mtimeX;
uint64_t st_mtime_nsec;
uint64_t st_ctimeX;
uint64_t st_ctime_nsec;
};
};
Function Skip Event
// kern/system_events.hh โ Skip a kernel function
class SkipFuncBase : public PCEvent
{
public:
SkipFuncBase(PCEventScope *s, const std::string &desc, Addr addr)
: PCEvent(s, desc, addr) {}
void process(ThreadContext *tc) override
{
// Architecture-specific: set PC to return address
returnFromFuncIn(tc);
}
};
Kernel dmesg Dump
// kern/linux/helpers.cc โ Extract kernel log buffer
namespace gem5::linux {
void dumpDmesg(ThreadContext *tc, std::ostream &os)
{
// Use SETranslatingPortProxy to read kernel memory
auto proxy = tc->getVirtProxy();
// Locate __log_buf symbol in kernel
Addr log_buf_addr = /* resolved from kernel symbols */;
Addr log_buf_len = /* resolved from kernel symbols */;
// Read ring buffer contents
std::vector<uint8_t> buf(log_buf_len);
proxy.readBlob(log_buf_addr, buf.data(), log_buf_len);
// Parse and output log entries
os << "=== Kernel dmesg ===" << std::endl;
// ... parse ring buffer format ...
}
} // namespace gem5::linux
FreeBSD ioctl Check
// kern/freebsd/freebsd.hh
class FreeBSD : public OperatingSystem
{
public:
static bool isTtyReq(unsigned req)
{
switch (req) {
case TIOCGETA:
case TIOCSETA:
case FIONREAD:
return true;
default:
return false;
}
}
};