Rust for Linux is an ongoing project started in 2020 to add add support for the Rust language to the Linux kernel software. Since the Rust support for the kernel project is not particularly straightforward, this posts aims to help to setup it up.

The Rust support was merged in v6.1 into mainline in order to help in determining whether Rust as a language was suitable for the kernel and if it’s worth to be introduced into it.

Currently, the Rust support is primarily intended for kernel developers interested in the Rust support to experiment it, start working on abstractions and drivers, and helping the development of infrastructure and tools. Note that, as of today, there are currently no in-tree drivers/modules suitable or intended for production use, and that the Rust support is still in development/experimental, especially for certain kernel configurations.

Please see the kernel documentation section for more details.

Install Rust

The first step is to install Rust and is easily done through rustup, a command line tool for managing Rust versions and associated tools.

# For Linux or MacOS users
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

The command downloads a script and starts the installation of the rustup tool, which installs the latest stable version of Rust. You might be prompted for your password. If the install is successful, the following line will appear:

Rust is installed now. Great! If you prefer a specific Rust version, you can specify it in rustup and install the one more suitable for you, specifing the date of the release.

# Install another stable version
rustup override set stable-20XX-XX-XX 

# Install a nightly version
rustup override set nightly-20XX-XX-XX

Finally, check Cargo and Rustc versions:

$ cargo --version
$ rustc --version

Prepare the build

First install the prerequisites:

# Arch Linux
pacman -S rust rust-src rust-bindgen

# Debian-Ubuntu
apt install rustc rust-src bindgen rustfmt rust-clippy

# Fedora
dnf install rust rust-src bindgen-cli rustfmt clippy

# Gentoo
USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen

# SUSE
zypper install rust rust1.79-src rust-bindgen clang

This section explains how to fetch the tools needed for building.

To check whether the requirements are met, the following target can be used:

$ make LLVM=1 rustavailable

Rust is available! This triggers the same logic used by Kconfig to determine whether RUST_IS_AVAILABLE should be enabled; but it also explains why not if that is the case.

Build the rusty kernel

Install the Rust required components

$ rustup component add rust-src rustfmt clippy
$ cargo install --locked bindgen-cli
$ make LLVM=1 rust-analyzer

Now, we need to configure the kernel to enable Rust support. To do that, enter the following commands

make LLVM=1 allnoconfig rust.config

Then open the configuration and enable Rust support and various other related features with the menuconfig interface:

make LLVM=1 menuconfig

menuconfig

enable the following options:

  • General setup -> Rust support
  • Kernel hacking -> Sample Kernel code -> Rust samples -> [all of them]
  • Kernel hacking -> Rust hacking -> [all of them]

also, enable the KUnit support and KUnit test framework:

  • Kernel hacking -> Kernel testing and coverage -> KUnit
  • Kernel hacking -> Rust hacking -> KUnit test for the kernel crate

Finally, we can build the Kernel:

$ make LLVM=1 -j$(nproc)

$ make LLVM=1 CLIPPY=1 -j$(nproc) # add clippy add extra lints and analyses via clippy

Build the documentation

We can build the Rust documentation with the command:

$ make LLVM=1 rustdoc
CALL scripts/checksyscalls.sh
DESCEND objtool
INSTALL libsubcmd_headers
RUSTDOC /home/alessandro/.rustup/toolchains/nightly-2024–09–23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/lib.rs
RUSTDOC H rust/macros/lib.rs
RUSTDOC rust/compiler_builtins.rs
RUSTDOC rust/ffi.rs
RUSTDOC rust/kernel/lib.rs

and open the docs locally in your web browser

$ xdg-open Documentation/output/rust/rustdoc/kernel/index.html
Opening in existing browser session.

The generated documentation provides a lot of information about the supported crates, and it can be opened with your web browser:

menuconfig

Other options

The kernel has a rust-analyzer target for generating the rust-project.json file used by the rust-analyzer with the following command

make LLVM=1 rust-analyzer

You can also find plugins for your favorite editor, like vscode, neovim, etc.

For checking source code style, based on rustfmt-check, you can use the rustfmtcheck target:

make LLVM=1 rustfmtcheck

For fixing the source code style, based on rustfmt, you can use the rustfmt tool:

make LLVM=1 rustfmt

For running the tests, you can use the rusttest target:

make LLVM=1 rusttest

Troubleshooting

Rust version

Only some versions of Rust are supported

*** Rust compiler 'rustc' is too new. This may or may not work.
***   Your version:     1.81.0
***   Expected version: 1.73.0

so, you may need to update your Rust version because

$ rustup update stable # for stable release
# or
$ rustup toolchain install nightly # for the nightly build

Bindgen

Bindgen is a component that automatically generates Rust FFI bindings to C (and some C++) libraries. As of today, the Ubuntu default version of Bindgen is 0.66.1 which is not compatible to compile the kernel

*** Rust bindings generator 'bindgen' is too new. This may or may not work.
***   Your version:     0.66.1
***   Expected version: 0.65.1
***
*** Please see Documentation/rust/quick-start.rst for details
*** on how to set up the Rust support.

and we may need to downgrade manually to a different bindgen version (for example Debian versions).

Rust support

Enabling the Rust support may not be straightforward and to know what’s missing you can search for “Rust”

rust-support

and see the features that triggers it to make sure to have RUST [=y]

Symbol: RUST [=y]                                                                                                                                                                     │  
  │ Type  : bool                                                                                                                                                                          │  
  │ Defined at init/Kconfig:1941                                                                                                                                                          │  
  │   Prompt: Rust support                                                                                                                                                                │  
  │   Depends on: HAVE_RUST [=y] && RUST_IS_AVAILABLE [=y] && !MODVERSIONS [=n] && !GCC_PLUGIN_RANDSTRUCT [=n] && !RANDSTRUCT [=n] && (!DEBUG_INFO_BTF [=n] || PAHOLE_HAS_LANG_EXCLUDE [=n]) && (!CFI_CLANG [=n] || RUSTC_VERSION [=108300]>=107900 && HAVE_CFI_ICALL_NORMALIZE_INTEGERS [=n]) && (!CALL_PADDING [=n] || RUSTC_VERSION [=108300]>=108100) && !KASAN_SW_TAGS [=n] && (!MITIGATION_RETHUNK [=n] || !KASAN [=n] || RUSTC_VERSION [=108300]>=108300)│
  │   Location:                                                                                                                                                                           │  
  │     -> General setup                                                                                                                                                                  │  
  │ (1)   -> Rust support (RUST [=y])                                                                                                                                                     │  
  │ Selects: CFI_ICALL_NORMALIZE_INTEGERS [=n]

Stack frame size during build

You might get compilation errors related to stack frame size:

$ make LLVM=1 CLIPPY=1
...
arch/x86/kvm/hyperv.c:2002:12: error: stack frame size (1336) exceeds limit (1024) in 'kvm_hv_flush_tlb' [-Werror,-Wframe-larger-than]
 2002 | static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
      |            ^
1 error generated.
make[4]: *** [scripts/Makefile.build:229: arch/x86/kvm/hyperv.o] Error 1
make[3]: *** [scripts/Makefile.build:478: arch/x86/kvm] Error 2
make[2]: *** [scripts/Makefile.build:478: arch/x86] Error 2
make[1]: *** [/home/alessandro/linux_work/rust/linux/Makefile:1943: .] Error 2
make: *** [Makefile:224: __sub-make] Error 2

In this case, edit the .config file extendding the defualt (=1024) frame size:

CONFIG_FRAME_WARN=2048

and recompile it.