Add Linux Kernel Modules in Rust
[rust
kernel
linux
software-development
]
To know how to configure Rust in the Linux Kernel, check out this post and to know how to test it check out this other post.
Add an empty module
In the kernel folder, open the Kconfig
file which contains the configuration options organized in a tree structure within the menuconfig
and custimizable through it.
$ cd linux
$ vim samples/rust/Kconfig
Copy another option and add it with the propoer modifications such as:
menuconfig SAMPLES_RUST_TEST_MODULE
tristate "Test module"
help
This option builds the Rust test program samples.
To compile this as a module, choose M here:
the module will be called rust_test.
If unsure, say N.
Then, open the makefile
$ vim samples/rust/Makefile
and edit it addign the new option:
obj-$(SAMPLES_RUST_TEST_MODULE) += rust_test_module.o
Create an empty file for the module where we’ll add the code in the next step:
$ touch sampel/rust/rust_test_module.rs
You can check that your module has been added by running the rust-analyzer and check into the rust-project.json file
$ make rust-analyzer
$ cat rust-project.json | grep rust_test_module
"display_name": "rust_test_module",
"root_module": "linux/samples/rust/rust_test_module.rs"
Write the Rust source file
Open the samples/rust/rust_test_module.rs
file and insert your Rust code:
// Test module
use kernel::prelude::*;
module! {
type: TestMod,
name: b"test",
license: b"GPL",
}
struct TestMod;
impl kernel::Module for TestMod {
fn init(_name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
pr_info!("------------------------\n");
pr_info!("hello world test module!\n");
pr_info!("------------------------\n");
Ok(TestMod)
}
}
The module!
macro creates the module, while the init()
function prints a message during the initialization
in order to see it during the OS start.
Build the kernel with the new module
To build the kernel with the new module, we need to select the new module option and compile the kernel.
So, open menuconfig to configure the kernel source
make menuconfig
and enable the Rust test module that is located at:
Main menu -> Kernel hacking -> Sample kernel code -> Rust samples -> Rust test module [*]
Save the configurations file and overwrite the old .config
file.
Finally, build the kernel:
make -j8
Start the kernel
Once the kernel is ready, you can start a qemu
instance of the kernel
qemu-system-x86_64 -nographic -kernel vmlinux -initrd initrd.img -nic user,model=rtl8139,hostfwd=tcp::5555-:23
and, if everything works well, you should see during the boot on the terminal
[] test_module: -----------------------
[] test_module: hello world test module!
[] test_module: -----------------------
Reload the module
If you want to modifiy the Rust source code and reload the module you can use the cargo-watch
tool that watches over the source file and runs the cargo
commands, such as:
cargo init .
cargo install cargo-watch
cargo watch -w ./samples/rust/rust_test_module.rs -cs 'make && qemu-system-x86_64 -m 3G -smp 2 -kernel bzImage -append "root=/dev/sda console=ttyS0 earlyprintk=serial net.ifnames=0" -drive file=bullseye.img,format=raw -net user,host=10.0.2.10,hostfwd=tcp::10021-:22 -net nic,model=e1000 -enable-kvm -nographic'
With similar result, you can add the rust-watch
configuration in the Makefile to add the command and execute it from terminal:
PHONY += rustwatch
rustwatch:
$(Q) cargo watch -w ./samples/rust/rust_test_module.rs -cs 'make && qemu-system-x86_64 -m 3G -smp 2 -kernel bzImage -append "root=/dev/sda console=ttyS0 earlyprintk=serial net.ifnames=0" -drive file=bullseye.img,format=raw -net user,host=10.0.2.10,hostfwd=tcp::10021-:22 -net nic,model=e1000 -enable-kvm -nographic'
PHONY += rustvm
rustvm:
$(Q) make && qemu-system-x86_64 -m 3G -smp 2 -kernel bzImage -append "root=/dev/sda console=ttyS0 earlyprintk=serial net.ifnames=0" -drive file=bullseye.img,format=raw -net user,host=10.0.2.10,hostfwd=tcp::10021-:22 -net nic,model=e1000 -enable-kvm -nographic
and, then, use the commands:
# Build and start the VM
make rustvm
# Start a rust-watch that rebuilds and start the VM when file changes
make rustwatch