Linux drivers · Course contents
Machine not started
30 min·Intermediate

Bind a Linux platform driver

Compile code into a real kernel module and expose MMIO readings through Linux sysfs.

Jump to code and terminal ↓

Move ownership into the kernel

The device tree describes the Acme register range and PLIC interrupt. The supplied platform_driver harness uses devm_ioremap_resource, request_irq, and sysfs attributes, and unwinds those resources when you remove the module. Your callbacks execute inside Linux kernel context, not a userspace process.

A small in-browser module toolchain

TinyCC compiles your callbacks against lab_driver.h. build-driver links them with the GCC-built harness and module metadata for this exact source-built kernel. The narrow callback API calls real readl/writel and DMA barriers; it avoids downloading a full GCC compiler and kernel headers. Inspect /usr/lib/lab-driver/lab_driver.h in the terminal.

Probe and read

Use api->read32(api->context, LAB_ID) to verify 0xAC1E0001. Return -19 for an absent device. Enable CONTROL bits 0 and 1, then return zero. The temperature callback reads LAB_TEMPERATURE every time sysfs is read; casting to int preserves signed temperatures.

Your goal

Implement the platform probe callback and temperature reader so Linux binds the sensor and sysfs follows hardware state.

What the tests observe

  • The module links and loads inside Linux
  • The platform device binds and publishes sysfs
  • The reading changes when hardware is disabled and re-enabled

Need a nudge?

Hint 1

The context pointer belongs to the supplied kernel harness. Pass it unchanged to read32 and write32.

Hint 2

Return zero only after identifying and enabling the sensor. A module can load even when its device probe fails.

Hint 3

Use api->write32(api->context, LAB_CONTROL, 3), then implement the temperature callback as a current register read.

What happens inside Linux

insmod invokes Linux's module loader. The platform bus matches the device-tree compatible string, invokes probe, maps the MMIO region, and publishes sysfs attributes. Reading the attribute runs your C callback in the kernel. rmmod disables the source, removes sysfs, and releases managed resources.

Optional account sync. Exercises work without an account.

Reference headers and helper functions

Read-only lesson support. Your editable implementation is below.

lab_driver.h

/* SPDX-License-Identifier: GPL-2.0-only
 * Narrow module callback ABI. Implementations execute in Linux kernel context.
 * The supplied platform harness owns registration, mappings, IRQ registration,
 * coherent allocation, sysfs lifetime, and module cleanup.
 */
#ifndef LAB_DRIVER_H
#define LAB_DRIVER_H
typedef unsigned int lab_u32;
typedef unsigned long lab_u64;
#define LAB_ID 0x00
#define LAB_TEMPERATURE 0x04
#define LAB_CONTROL 0x08
#define LAB_STATUS 0x0c
#define LAB_IRQ_STATUS 0x10
#define LAB_IRQ_ACK 0x14
#define LAB_SAMPLE 0x18
#define LAB_DMA_LO 0x20
#define LAB_DMA_HI 0x24
#define LAB_DMA_START 0x28
#define LAB_DMA_STATUS 0x2c
#define LAB_DEVICE_OWNS 1U
#define LAB_DMA_DONE 2U
struct lab_dma_descriptor {
    lab_u64 address;
    lab_u32 length, flags, completed, reserved;
};
struct lab_api {
    void *context;
    lab_u32 (*read32)(void *, unsigned int);
    void (*write32)(void *, unsigned int, lab_u32);
    void (*write_barrier)(void);
    void (*read_barrier)(void);
};
struct lab_irq_state { lab_u32 count, last_temperature; };
int student_probe(const struct lab_api *);
int student_temperature(const struct lab_api *);
void student_interrupt(const struct lab_api *, lab_u32, struct lab_irq_state *);
int student_dma_submit(const struct lab_api *, struct lab_dma_descriptor *, lab_u64, lab_u64, lab_u32);
int student_dma_complete(const struct lab_api *, struct lab_dma_descriptor *);
#endif
C/work/driver.cLoading local work…
Restoring your workspace…
⌘ / Ctrl ↵
TerminalRISC-V 64 · root · /work

Your Linux machine is ready to start.

Boot a disposable environment in this browser. You’ll get a real root shell, with no remote server or account required.

Acme temperature sensor

Linux kernel driver
42°C
Address
0x40000000
Connection
connected
Control
unobserved
Accesses shown
0
IRQ enable
unobserved
Hardware events shown
0

Start Linux and run your driver. Reads and writes to the device will appear here as they happen.

Interrupts and DMA

The emulator records hardware interrupts, acknowledgments, and DMA transfers here. Load your driver and request a sample to observe the device.