💻 Module 6 · Software Stack · Chapter 6.2 · 10 min read

Linux Kernel and aether-driver

SIDRA's dedicated kernel module — aether-driver internals.

What you'll learn here

  • Explain the aether-driver source layout and build process
  • Read module init/exit, IOCTL handler, and interrupt handler code snippets
  • Name kernel debugging strategies (printk, dmesg, kgdb)
  • Apply driver security best practices
  • Summarize the upstreaming path of aether-driver into the Linux kernel

Hook: aether-driver Anatomy

aether-driver is SIDRA’s official Linux kernel module. Written in C, ~5000 lines. Open source (GPL v2). Hosted on GitHub.

This chapter walks through the source structure, key functions, and how to use it.

Intuition: 5 Main Files

aether-driver/ repo:

src/
├── pci.c           # PCIe enumeration + probe/remove
├── device.c        # /dev/sidra0 char device
├── ioctl.c         # IOCTL handlers (33 commands)
├── dma.c           # DMA buffer management
├── interrupt.c     # IRQ handlers
├── sysfs.c         # /sys/class/sidra debug interface
├── firmware.c      # Firmware loading
└── sidra_dev.h     # Header
Makefile
README.md

Build: make -C /lib/modules/$(uname -r)/build M=$PWD modules.

Install: sudo insmod sidra.ko or modprobe sidra.

Formalism: Driver Internals

L1 · Başlangıç

Module init/exit:

static int __init aether_init(void) {
    int ret = pci_register_driver(&aether_pci_driver);
    if (ret) return ret;
    
    pr_info("aether-driver loaded, version %s\n", AETHER_VERSION);
    return 0;
}

static void __exit aether_exit(void) {
    pci_unregister_driver(&aether_pci_driver);
    pr_info("aether-driver unloaded\n");
}

module_init(aether_init);
module_exit(aether_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SIDRA Team");

Probe (PCIe device found):

static int aether_probe(struct pci_dev *pdev, const struct pci_device_id *id) {
    struct sidra_dev *sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
    pci_set_drvdata(pdev, sdev);
    
    pci_enable_device(pdev);
    pci_set_master(pdev);  // for bus master
    pci_request_regions(pdev, "sidra");
    
    // BAR0 = control registers
    sdev->bar0 = pci_iomap(pdev, 0, 0);
    
    // BAR1 = DMA area
    sdev->bar1 = pci_iomap(pdev, 1, 0);
    
    // IRQ
    pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
    request_irq(pci_irq_vector(pdev, 0), aether_irq_handler,
                0, "sidra", sdev);
    
    // /dev/sidra0
    create_char_device(sdev);
    
    // Load firmware
    aether_load_firmware(sdev);
    
    return 0;
}
L2 · Tam

IOCTL handler:

static long aether_ioctl(struct file *f, unsigned int cmd, unsigned long arg) {
    struct sidra_dev *sdev = f->private_data;
    
    switch (cmd) {
    case SIDRA_IOCTL_VERSION: {
        u32 ver = readl(sdev->bar0 + REG_VERSION);
        return copy_to_user((void __user *)arg, &ver, sizeof(ver));
    }
    case SIDRA_IOCTL_LOAD_MODEL: {
        struct model_data m;
        copy_from_user(&m, (void __user *)arg, sizeof(m));
        return aether_load_model(sdev, &m);
    }
    case SIDRA_IOCTL_INFER: {
        struct inference_req req;
        copy_from_user(&req, (void __user *)arg, sizeof(req));
        return aether_run_inference(sdev, &req);
    }
    // ... 33 IOCTLs
    default:
        return -ENOTTY;
    }
}

Interrupt handler:

static irqreturn_t aether_irq_handler(int irq, void *data) {
    struct sidra_dev *sdev = data;
    u32 status = readl(sdev->bar0 + REG_INT_STATUS);
    
    if (status & INT_INFERENCE_DONE) {
        wake_up(&sdev->infer_wait);
        writel(INT_INFERENCE_DONE, sdev->bar0 + REG_INT_CLEAR);
    }
    
    if (status & INT_ERROR) {
        u32 err = readl(sdev->bar0 + REG_ERROR_CODE);
        pr_warn("SIDRA error: 0x%x\n", err);
    }
    
    return IRQ_HANDLED;
}
L3 · Derin

Debug strategies:

  1. printk: pr_info, pr_warn, pr_err. Visible via dmesg.
  2. sysfs: /sys/class/sidra/sidra0/temperature, /error_count.
  3. debugfs: /sys/kernel/debug/sidra/. Detailed stats.
  4. kgdb: kernel debugger. Tricky.
  5. ftrace: function trace. Performance profiling.

Race conditions:

The kernel is preemptive. Critical sections need spinlocks or mutexes:

mutex_lock(&sdev->cmd_lock);
// critical section
mutex_unlock(&sdev->cmd_lock);

Power management:

Suspend/resume callbacks:

static int aether_suspend(struct pci_dev *pdev, pm_message_t state) {
    // Put chip to sleep, save state
    return 0;
}

static int aether_resume(struct pci_dev *pdev) {
    // Wake chip, restore state
    return 0;
}

Multi-instance:

If multiple SIDRA chips: /dev/sidra0, /dev/sidra1, … separate major/minor. The driver picks by minor number.

Upstream submission:

To be accepted into the Linux kernel:

  1. Coding style (kernel checkpatch.pl).
  2. Documentation/.
  3. SubmittingPatches rules.
  4. LKML (Linux Kernel Mailing List) review.
  5. Maintainer review.

SIDRA upstream target: post-2027 Y1 production. ASELSAN/university Linux community contribution.

Kernel ABI:

aether-driver’s IOCTL interface is stable. Versioning:

  • AETHER_API_V1 (Y1): 33 IOCTLs.
  • AETHER_API_V2 (Y3): + 10 IOCTLs (new features).

User-space apps support both (compile-time check).

Experiment: aether-driver Build + Test

Build:

cd aether-driver/
make
# Output: sidra.ko

Load:

sudo insmod sidra.ko
dmesg | tail
# Output: aether-driver loaded, version 1.0.0
#         sidra 0000:01:00.0: PCIe device probed
#         sidra: /dev/sidra0 created

Test:

ls /dev/sidra0
# crw-rw---- 1 root sidra  243, 0 Apr 19 16:00 /dev/sidra0

cat /sys/class/sidra/sidra0/temperature
# 65

cat /sys/class/sidra/sidra0/version
# 0x00010000

Error check:

cat /sys/class/sidra/sidra0/error_count
# 0

Unload:

sudo rmmod sidra
dmesg | tail
# Output: aether-driver unloaded

Total: the whole cycle ~1 minute. Standard developer workflow.

Quick Quiz

1/6What language is aether-driver written in?

Lab Exercise

aether-driver developer cycle.

Scenario: add a new IOCTL (SIDRA_IOCTL_GET_TEMP).

Steps:

  1. In sidra_dev.h add: #define SIDRA_IOCTL_GET_TEMP _IOR('s', 5, int).
  2. In ioctl.c add a switch case, read bar0 + REG_TEMP, copy_to_user.
  3. Build: make.
  4. Reload: sudo rmmod sidra && sudo insmod sidra.ko.
  5. Write a test C program that calls the ioctl.
  6. Check dmesg for logs.

Time: new feature ~30 minutes (for an experienced driver dev).

Practical tip: keep ioctl numbers ('s', 5) collision-free. Linux ioctl-number.txt is the reference.

Cheat Sheet

  • aether-driver: SIDRA’s official Linux kernel module, C, ~5K lines, GPL.
  • Layout: pci.c, device.c, ioctl.c, dma.c, interrupt.c, sysfs.c, firmware.c.
  • Build: standard kernel module Makefile.
  • Debug: printk + dmesg, sysfs, debugfs, kgdb.
  • Multi-instance: /dev/sidra0, sidra1, …
  • Upstream: 2027 target, mainline kernel.

Vision: aether-driver, Türkiye Kernel Community

When aether-driver lands upstream:

  • Türkiye’s first major hardware driver in mainline (ASELSAN/BİLGEM had small contributions).
  • Turkish developers can become mainline maintainers.
  • Kernel community visibility → SIDRA brand.
  • Academic bonus: PhD theses on kernel-side work.

Further Reading