RSSAmplifier

Blog

Home on Linux kernel programming blog

Recent content in Home on Linux kernel programming blog

rust.christina-quast.deRSS feed ↗19 posts

Latest posts

The Cleanup Pattern - From goto out to Drop

The C Cleanup Pattern While in most programming styles using goto’s is frowned upon, in the Linux Kernel this is the default method of undoing the registration and creation work done by each driver. You oftentimes have the situation that you start registering a driver. When an error occurs in this process, you have to roll back everything you just did in reverse order. This is where goto…

Opaque Pointers and Type Erasure

In the last blog post, we discussed how callback arguments are handled in Rust when interfacing with C. When we want to interface with every C context in the Linux kernel using *mut ffi::c_void , we lose the ability to distinguish different types . If we interpret a device context as a driver context, in the best case we run into a segfault. In the worst case, we hunt a bug that only sometimes…

The Callback Conundrum - Porting void pointers to user data

Platform drivers were one of the first success stories of the Rust-for-Linux project. They were a proof of concept that the integration of Rust into the existing Linux kernel C code base would work. The decision to focus on platform drivers early on was strategic. They are simpler compared to complex GPU or network drivers, and therefore provide a perfect sandbox for testing Rust abstractions.

Inline Assembly

Why inline assembly? If you ever need to do something that’s not possible in your high-level language, or you need that extra bit of performance, inline assembly is your portal to the processor. In C, the asm keyword is a direct portal to the processor. The compiler treats your assembly string like a mysterious __black box__ . You tell the compiler, “I’m going to mess with some…

C to Rust - Memory

One of the big worries of any seasoned embedded developper is always memory and processing overhead. This blog post will show how you can have the cake and eat it as well: You can have the safety guarantees thanks to the Rust compiler without suffering any memory or CPU overhead. The Rust compiler takes care of making sure that you don’t read or write outside of a buffer or try to reference…

Hashset

Why reinventing HashSet? This article will focus on adding a Hashset to the quarto_rs . As previously discussed, because we cannot use the Rust stdlib when writing code for the Linux kernel, we have to implement the HashSet trait and implementation ourselves. I am aware of the fact that it would have been much easier to replace the HashSet with a Vector of size 64 and iterate over it. But I wanted…

Porting a userspace program to Kernel space

Differences between Kernel and Userspace Porting a Rust program to the Linux Kernel is very similar to porting a Rust program to an embedded device. Compared to the program you write on your desktop computer, you cannot use the standard library ( std ). Furthermore, embedded systems and the Linux Kernel have special requirements for memory management. Allocations in Kernel space must not fail,…

Out of tree Kernel module

Compiling an out of tree rust module This chapter will be less Rust focused, and more an introduction on how to compile Out-of-tree kernel modules in general. The examples were compiled with a net-next kernel based on v6.8-rc1 . Module code The easiest way to get started is to copy over a module to your directory, e.g. copy over samples/rust/rust_minimal.rs and try compiling it. You can read up…

Ioctls

Input/Output Controls In computing, ioctl calls (input/output calls) are special function calls used for operations that can not be done with regular file operations like read, write, etc. They provide a general-purpose interface for sending control codes to devices, set parameters, etc. The calls are a type of system call. But while system calls like open, read, write, etc can be applied to all…

Locks and synchronization

Synchronization This LWN article was an attempt to give a side by side code comparison of how the same GPIO driver looks like written in C and Rust. Even though the synchronization code that ended up in the Linux Kernel is different from what we see there, it gives a good overview of how a driver using locking primitives could look like. For this blog post, we will focus on the locking and…

Results and Errors

Rusty error handling In C, it is common that functions return a integer indicating the success or failure of the function execution. Extra data can only be modified or returned through non- const pointer parameters. Rust on the other hand uses explicit error types. The Result type encapsulates error and success. In the context of Rust code in the Linux Kernel, functions that would return an error…

Allocators

User Land When is it used? In user land, the programmer typically does not explicitly call an allocator. Instead, whenever you use types like Box , Vec or String , in the background the global allocator is used to allocate and free memory. This global allocator is part of the Rust standard library std . Therefore, in order to define your own allocator, you have to import the GlobalAlloc trait and…

C vs Rust - In the Linux Kernel

+++ Plus +++ Memory bugs and Concurrency Let’s get the obvious out of the way: With Rust, you will inherently write safer code, because the compiler will complain until you do. Whole error classes will become less common when Rust programs are widely used: Buffer-Overflows , many types of Memory-Leaks, Race conditions are made impossible, because the compiler will force you to have only…

Getting involved

Rust for Linux The best starting place is probably the web page of the project, rust-for-linux.com . This page is meant as a hub of links, documentations and resources to this topic. One source that does not seem to work well is the github Good first issues page, which currently is not up to date, and all good first issues are already done or in progress by somebody. On the other hand, the…

Porting my first phy driver

Why the phy? I saw that Fujita Tomonori had added the Rust version of the ax88796b phy driver for the Asix PHY, which looked very similar to the C version of this driver (compare ax88796b_rust.rs vs ax88796b.c ). This driver is meant as a reference driver for further phy drivers. The phy.rs file uses binding to struct phy_device and to pass through C function calls to phy driver functions.

Creating C bindings

What are bindings? Bindings are ways to create an interface between two programming languages, which allow code written in one language to call from code in another language. In the case of Rust in the Linux kernel code, Rust FFI (Foreign Function Interface) bindings are used to call C functions, conforming to the C calling convention. This means that arguments are placed on the stack or in…

Getting Started

Check out code I recommend checking out the Rust-for-Linux kernel to play around with, because it has many more sample modules than the mainline kernel. Even though the interfaces are probably not stable, you can get an idea where development is headed. Get your tools ready After checking out, you should follow the instructions in Documentation/rust/quick-start.rst for setting up your tools. I had…

about::blog

This blog got started out as a way to document my way into writing Linux Kernel modules in Rust . It seemed hard to find information on this topic, so I started out first with Advent of Code in 2023 in order to learn Rust. From challenge to challenge, I feel like my code became more “rusty”. To get a solid grasp of the core concepts, I also worked through rustlings , which I highly…

about::consulting

about::mission Modern systems require the performance of C with the safety of Rust. I help companies bridge this gap by providing hands-on training for Embedded Rust and Rust for Linux. My goal is to help your team reduce memory-safety bugs and modernize legacy codebases without losing the low-level control required for kernel and hardware development. about::modules Rust for Linux Kernel…