kern

OS Kernel Support โ€” syscall types, kernel events, and OS abstraction layer

๐Ÿ“ 17 files ๐Ÿ“ 2.6K LOC ๐Ÿง 3 OSes ๐Ÿ’ป C++
Linux FreeBSD Solaris Syscall Types Kernel Events
~8 min read
๐Ÿ”Œ Analogy: The 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

ClassParentFileDescription
OperatingSystemโ€”operatingsystem.hhAbstract base: defines target syscall struct interfaces
LinuxOperatingSystemlinux/linux.hhLinux-specific types: stat, stat64, uid_t, gid_t, signal constants
FreeBSDOperatingSystemfreebsd/freebsd.hhFreeBSD types and ioctl codes (TIOCGETA, FIONREAD)
SolarisOperatingSystemsolaris/solaris.hhSolaris/SunOS types: rlim_t, tgt_timespec, tgt_stat
SkipFuncBasePCEventsystem_events.hhBase class for function-skipping events at specific PCs
PanicOrOopsEventPCEventlinux/events.hhHandles kernel panic/oops: configurable halt, warn, or dmesg dump
DebugPrintktemplatelinux/events.hhCaptures kernel printk output during full-system simulation
dumpDmesg()functionlinux/helpers.hhExtracts 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 TypeC++ TypeSizeUsage
size_tuint64_t8 bytesBuffer sizes, counts
off_tint64_t8 bytesFile offsets
time_tint64_t8 bytesTimestamps
clock_tint64_t8 bytesCPU clock ticks
uid_tuint32_t4 bytesUser IDs
gid_tuint32_t4 bytesGroup IDs
dev_tuint64_t8 bytesDevice numbers
ino_tuint64_t8 bytesInode numbers

stat Structures

Linux defines two stat structure variants, matching the kernel's 32-bit and 64-bit ABIs:

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:

BehaviourAction
PanicOnOopsHalt simulation immediately, dump dmesg
WarnOnOopsPrint warning, dump dmesg, continue simulation
IgnoreOnOopsSilently continue execution

Type Mapping Tables

stat Structure Comparison

FieldLinuxFreeBSDSolaris
st_devuint64_tuint64_tuint64_t
st_inouint64_tuint64_tuint64_t
st_modeuint32_tuint16_tuint32_t
st_nlinkuint64_tuint64_tuint32_t
st_uiduint32_tuint32_tuint32_t
st_giduint32_tuint32_tuint32_t
st_sizeint64_tint64_tint64_t
st_atimeuint64_tint64_tint64_t

FreeBSD ioctl Codes

ConstantValuePurpose
TIOCGETAplatform-specificGet terminal attributes
TIOCSETAplatform-specificSet terminal attributes
FIONREADplatform-specificGet 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

DependencyModulePurpose
Syscall emulationsim/syscall_emulUses OS type definitions for syscall data marshalling
Process modelsim/processProcess objects are templated on OS type
Thread contextcpuPCEvent system hooks into CPU execution
Memory proxymemSETranslatingPortProxy for kernel memory access
Base utilitiesbaseTypes, random, trace, compiler attributes
Arch-specificarch/*/linuxArchitecture-specific stat struct variants

Directory Map

src/kern/ โ”œโ”€โ”€ Base Layer โ”‚ โ”œโ”€โ”€ operatingsystem.hh/cc โ€” OperatingSystem abstract base class โ”‚ โ””โ”€โ”€ system_events.hh/cc โ€” SkipFuncBase (PC-triggered function skip) โ”œโ”€โ”€ linux/ โ€” Linux kernel support โ”‚ โ”œโ”€โ”€ linux.hh/cc โ€” Linux type defs, stat structs, constants โ”‚ โ”œโ”€โ”€ events.hh/cc โ€” PanicOrOopsEvent, DebugPrintk โ”‚ โ”œโ”€โ”€ helpers.hh/cc โ€” dumpDmesg() kernel log extraction โ”‚ โ”œโ”€โ”€ printk.hh/cc โ€” printk format string parsing โ”‚ โ””โ”€โ”€ flag_tables.hh โ€” Open/mmap flag translation tables โ”œโ”€โ”€ freebsd/ โ€” FreeBSD kernel support โ”‚ โ”œโ”€โ”€ freebsd.hh โ€” FreeBSD types, ioctl codes โ”‚ โ””โ”€โ”€ events.hh/cc โ€” FreeBSD-specific kernel events โ””โ”€โ”€ solaris/ โ€” Solaris kernel support โ””โ”€โ”€ solaris.hh โ€” Solaris/SunOS type definitions

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:

ParameterLocationDescription
panic_on_oopsSystem configEnable PanicOrOopsEvent at kernel panic address
kernel_panic_oops_behaviourSystem configAction on panic: halt, warn, or ignore
skip_functionsSystem configList of kernel functions to skip during boot
kernel_addr_checkBoot loaderVerify 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;
        }
    }
};