Mastering Rust GPU Kernel Drivers: The Ultimate Guide to How GPU Drivers Really Work
Hello everyone. Today, we’re diving into the fascinating world of GPU drivers, specifically through the lens of a project called Tyr—a state-of-the-art Rust GPU driver for the Linux Kernel, supporting Arm Mali CSF-based GPUs. If you’re the kind of person who gets excited about spinning cubes and kernel-level programming, you’re in for a treat. If not, well, maybe you’ll at least enjoy the sarcasm and a few medical puns along the way.
The Anatomy of a GPU Driver: User Mode vs. Kernel Mode
Let’s start with the basics. A modern GPU driver is split into two main components: the User Mode Driver (UMD) and the Kernel Mode Driver (KMD). Think of the UMD as the charming front desk receptionist—handling all the high-level API calls like Vulkan, OpenGL, and OpenCL. The KMD, on the other hand, is the grumpy doctor in the back room, actually doing the heavy lifting and making sure the hardware doesn’t flatline.
For our purposes, the UMD is represented by panvk
, a Vulkan driver that’s part of Mesa. The KMD is Tyr, the Rust-based kernel driver aiming to make its way into the Linux kernel. The UMD translates your fancy API calls into something the GPU can understand, while the KMD allocates memory, manages hardware queues, and generally keeps the GPU from having a nervous breakdown.
A Case Study: VkCube
To make this all a bit more concrete, let’s talk about VkCube. As the name suggests, this is a program that uses Vulkan to render a rotating cube on the screen. It’s the “Hello World” of GPU programming—simple, elegant, and a great way to test if your driver is actually doing anything useful.
VkCube needs to allocate memory for geometry, textures, and shaders. Shaders, by the way, are full-blown programs running on the GPU. They’re responsible for placing the cube in the scene, coloring its sides, and making it spin like a disco ball. The UMD handles all of this high-level orchestration, but it relies on the KMD to actually allocate GPU memory, submit work to the hardware queue, and notify the user when the job is done.
One of the main jobs of the kernel driver is allocating and mapping memory, preferably in a way that promotes isolation through some sort of context that is private to the application.
In other words, the KMD is like the hospital administrator—making sure everyone has a bed, the right medication, and that no one is stealing the good syringes.
The KMD’s Job Description
- Allocating and mapping memory for geometry, textures, and shaders.
- Submitting work to the hardware queue for execution.
- Notifying the user when the job is done (because nobody likes waiting in the ER without updates).
- Scheduling jobs to ensure fair access to the hardware (no queue-jumping allowed).
- Initializing the device and keeping it operational for all clients.
It’s a tough gig, but someone’s got to do it. And apparently, that someone is a Rust-based kernel driver named Tyr.
The Tyr API: A Doctor’s Prescription
Now, let’s take a look at the actual API offered by Tyr. This is the same API offered by Panthor, the C driver for the same hardware. Here’s a quick rundown:
DRM_PANTHOR_DEV_QUERY: Query device information. DRM_PANTHOR_VM_CREATE: Create a VM. DRM_PANTHOR_VM_DESTROY: Destroy a VM. DRM_PANTHOR_VM_BIND: Bind/unbind memory to a VM. DRM_PANTHOR_VM_GET_STATE: Get VM state. DRM_PANTHOR_BO_CREATE: Create a buffer object. DRM_PANTHOR_BO_MMAP_OFFSET: Get the file offset to pass to mmap to map a GEM object. DRM_PANTHOR_GROUP_CREATE: Create a scheduling group. DRM_PANTHOR_GROUP_DESTROY: Destroy a scheduling group. DRM_PANTHOR_GROUP_SUBMIT: Submit jobs to queues belonging to a specific scheduling group. DRM_PANTHOR_GROUP_GET_STATE: Get the state of a scheduling group. DRM_PANTHOR_TILER_HEAP_CREATE: Create a tiler heap. DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap.
Yes, it’s as exciting as it sounds. This API is compact and far removed from our initial goal of drawing a rotating cube, but it’s essential for the UMD to function. The API can be broken down into a few key areas:
- Device Information: DEV_QUERY ioctl. The UMD needs to know what kind of hardware it’s dealing with—no one wants to prescribe the wrong medication.
- Memory Allocation and Isolation: VM_CREATE, VM_BIND, VM_DESTROY, VM_GET_STATE, BO_CREATE, and BO_MMAP_OFFSET. Think of this as assigning hospital rooms and making sure patients don’t wander into each other’s surgeries.
- Group Creation and Management: GROUP_CREATE, GROUP_DESTROY, and GROUP_GET_STATE. We’ll get into what groups are in a later installment, but for now, just imagine them as specialized wards.
- Job Submission: GROUP_SUBMIT. This is how we actually tell the GPU to do something useful, like drawing our beloved cube.
- Tiler Heap Management: TILER_HEAP_CREATE and TILER_HEAP_DESTROY. This is advanced stuff, but for now, just know that it’s about managing internal memory pools for drawing geometry.
A Key Takeaway: Where’s the Real Work?
If you’ve been paying attention (and haven’t passed out from boredom), you’ll notice that most of the complexity resides in the UMD. The KMD is there to provide essential services—allocating memory, managing hardware queues, and keeping everything running smoothly. It’s like the hospital infrastructure: you don’t see it, but you’d notice pretty quickly if it stopped working.
What’s Next: Paging Dr. CSF
This article introduced some key concepts about how GPU drivers work. In the next installment, we’ll explore the CSF architecture, including components like the Micro Controller Unit (MCU) that underpins the design. We’ll also look at the steps needed to get it to boot—because nothing says “fun” like debugging hardware initialization at 3 AM.
Final Diagnosis
In summary, writing a Rust GPU kernel driver is not for the faint of heart. It’s a complex, multi-layered process that requires a deep understanding of both hardware and software. But if you’re up for the challenge, it’s also incredibly rewarding. Just remember to keep your sense of humor—and maybe a defibrillator—close at hand.
And that, ladies and gentlemen, is entirely my opinion.
Source: Writing a Rust GPU kernel driver: a brief introduction on how GPU drivers work, https://www.collabora.com/news-and-blog/blog/2025/08/06/writing-a-rust-gpu-kernel-driver-a-brief-introduction-on-how-gpu-drivers-work/