summaryrefslogtreecommitdiff
path: root/Documentation/rust
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/rust')
-rw-r--r--Documentation/rust/arch-support.rst7
-rw-r--r--Documentation/rust/coding-guidelines.rst221
-rw-r--r--Documentation/rust/general-information.rst106
-rw-r--r--Documentation/rust/index.rst22
-rw-r--r--Documentation/rust/quick-start.rst206
-rw-r--r--Documentation/rust/testing.rst236
6 files changed, 704 insertions, 94 deletions
diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst
index 73203ba1e901..6e6a515d0899 100644
--- a/Documentation/rust/arch-support.rst
+++ b/Documentation/rust/arch-support.rst
@@ -15,8 +15,11 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
============= ================ ==============================================
Architecture Level of support Constraints
============= ================ ==============================================
-``loongarch`` Maintained -
-``um`` Maintained ``x86_64`` only.
+``arm`` Maintained ARMv7 Little Endian only.
+``arm64`` Maintained Little Endian only.
+``loongarch`` Maintained \-
+``riscv`` Maintained ``riscv64`` and LLVM/Clang only.
+``um`` Maintained \-
``x86`` Maintained ``x86_64`` only.
============= ================ ==============================================
diff --git a/Documentation/rust/coding-guidelines.rst b/Documentation/rust/coding-guidelines.rst
index 05542840b16c..6ff9e754755d 100644
--- a/Documentation/rust/coding-guidelines.rst
+++ b/Documentation/rust/coding-guidelines.rst
@@ -85,6 +85,18 @@ written after the documentation, e.g.:
// ...
}
+This applies to both public and private items. This increases consistency with
+public items, allows changes to visibility with less changes involved and will
+allow us to potentially generate the documentation for private items as well.
+In other words, if documentation is written for a private item, then ``///``
+should still be used. For instance:
+
+.. code-block:: rust
+
+ /// My private function.
+ // TODO: ...
+ fn f() {}
+
One special kind of comments are the ``// SAFETY:`` comments. These must appear
before every ``unsafe`` block, and they explain why the code inside the block is
correct/sound, i.e. why it cannot trigger undefined behavior in any case, e.g.:
@@ -145,32 +157,32 @@ This is how a well-documented Rust function may look like:
This example showcases a few ``rustdoc`` features and some conventions followed
in the kernel:
- - The first paragraph must be a single sentence briefly describing what
- the documented item does. Further explanations must go in extra paragraphs.
+- The first paragraph must be a single sentence briefly describing what
+ the documented item does. Further explanations must go in extra paragraphs.
- - Unsafe functions must document their safety preconditions under
- a ``# Safety`` section.
+- Unsafe functions must document their safety preconditions under
+ a ``# Safety`` section.
- - While not shown here, if a function may panic, the conditions under which
- that happens must be described under a ``# Panics`` section.
+- While not shown here, if a function may panic, the conditions under which
+ that happens must be described under a ``# Panics`` section.
- Please note that panicking should be very rare and used only with a good
- reason. In almost all cases, a fallible approach should be used, typically
- returning a ``Result``.
+ Please note that panicking should be very rare and used only with a good
+ reason. In almost all cases, a fallible approach should be used, typically
+ returning a ``Result``.
- - If providing examples of usage would help readers, they must be written in
- a section called ``# Examples``.
+- If providing examples of usage would help readers, they must be written in
+ a section called ``# Examples``.
- - Rust items (functions, types, constants...) must be linked appropriately
- (``rustdoc`` will create a link automatically).
+- Rust items (functions, types, constants...) must be linked appropriately
+ (``rustdoc`` will create a link automatically).
- - Any ``unsafe`` block must be preceded by a ``// SAFETY:`` comment
- describing why the code inside is sound.
+- Any ``unsafe`` block must be preceded by a ``// SAFETY:`` comment
+ describing why the code inside is sound.
- While sometimes the reason might look trivial and therefore unneeded,
- writing these comments is not just a good way of documenting what has been
- taken into account, but most importantly, it provides a way to know that
- there are no *extra* implicit constraints.
+ While sometimes the reason might look trivial and therefore unneeded,
+ writing these comments is not just a good way of documenting what has been
+ taken into account, but most importantly, it provides a way to know that
+ there are no *extra* implicit constraints.
To learn more about how to write documentation for Rust and extra features,
please take a look at the ``rustdoc`` book at:
@@ -191,6 +203,23 @@ or:
/// [`struct mutex`]: srctree/include/linux/mutex.h
+C FFI types
+-----------
+
+Rust kernel code refers to C types, such as ``int``, using type aliases such as
+``c_int``, which are readily available from the ``kernel`` prelude. Please do
+not use the aliases from ``core::ffi`` -- they may not map to the correct types.
+
+These aliases should generally be referred directly by their identifier, i.e.
+as a single segment path. For instance:
+
+.. code-block:: rust
+
+ fn f(p: *const c_char) -> c_int {
+ // ...
+ }
+
+
Naming
------
@@ -227,3 +256,157 @@ The equivalent in Rust may look like (ignoring documentation):
That is, the equivalent of ``GPIO_LINE_DIRECTION_IN`` would be referred to as
``gpio::LineDirection::In``. In particular, it should not be named
``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN``.
+
+
+Lints
+-----
+
+In Rust, it is possible to ``allow`` particular warnings (diagnostics, lints)
+locally, making the compiler ignore instances of a given warning within a given
+function, module, block, etc.
+
+It is similar to ``#pragma GCC diagnostic push`` + ``ignored`` + ``pop`` in C
+[#]_:
+
+.. code-block:: c
+
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-function"
+ static void f(void) {}
+ #pragma GCC diagnostic pop
+
+.. [#] In this particular case, the kernel's ``__{always,maybe}_unused``
+ attributes (C23's ``[[maybe_unused]]``) may be used; however, the example
+ is meant to reflect the equivalent lint in Rust discussed afterwards.
+
+But way less verbose:
+
+.. code-block:: rust
+
+ #[allow(dead_code)]
+ fn f() {}
+
+By that virtue, it makes it possible to comfortably enable more diagnostics by
+default (i.e. outside ``W=`` levels). In particular, those that may have some
+false positives but that are otherwise quite useful to keep enabled to catch
+potential mistakes.
+
+On top of that, Rust provides the ``expect`` attribute which takes this further.
+It makes the compiler warn if the warning was not produced. For instance, the
+following will ensure that, when ``f()`` is called somewhere, we will have to
+remove the attribute:
+
+.. code-block:: rust
+
+ #[expect(dead_code)]
+ fn f() {}
+
+If we do not, we get a warning from the compiler::
+
+ warning: this lint expectation is unfulfilled
+ --> x.rs:3:10
+ |
+ 3 | #[expect(dead_code)]
+ | ^^^^^^^^^
+ |
+ = note: `#[warn(unfulfilled_lint_expectations)]` on by default
+
+This means that ``expect``\ s do not get forgotten when they are not needed, which
+may happen in several situations, e.g.:
+
+- Temporary attributes added while developing.
+
+- Improvements in lints in the compiler, Clippy or custom tools which may
+ remove a false positive.
+
+- When the lint is not needed anymore because it was expected that it would be
+ removed at some point, such as the ``dead_code`` example above.
+
+It also increases the visibility of the remaining ``allow``\ s and reduces the
+chance of misapplying one.
+
+Thus prefer ``expect`` over ``allow`` unless:
+
+- Conditional compilation triggers the warning in some cases but not others.
+
+ If there are only a few cases where the warning triggers (or does not
+ trigger) compared to the total number of cases, then one may consider using
+ a conditional ``expect`` (i.e. ``cfg_attr(..., expect(...))``). Otherwise,
+ it is likely simpler to just use ``allow``.
+
+- Inside macros, when the different invocations may create expanded code that
+ triggers the warning in some cases but not in others.
+
+- When code may trigger a warning for some architectures but not others, such
+ as an ``as`` cast to a C FFI type.
+
+As a more developed example, consider for instance this program:
+
+.. code-block:: rust
+
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+Here, function ``g()`` is dead code if ``CONFIG_X`` is not set. Can we use
+``expect`` here?
+
+.. code-block:: rust
+
+ #[expect(dead_code)]
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+This would emit a lint if ``CONFIG_X`` is set, since it is not dead code in that
+configuration. Therefore, in cases like this, we cannot use ``expect`` as-is.
+
+A simple possibility is using ``allow``:
+
+.. code-block:: rust
+
+ #[allow(dead_code)]
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+An alternative would be using a conditional ``expect``:
+
+.. code-block:: rust
+
+ #[cfg_attr(not(CONFIG_X), expect(dead_code))]
+ fn g() {}
+
+ fn main() {
+ #[cfg(CONFIG_X)]
+ g();
+ }
+
+This would ensure that, if someone introduces another call to ``g()`` somewhere
+(e.g. unconditionally), then it would be spotted that it is not dead code
+anymore. However, the ``cfg_attr`` is more complex than a simple ``allow``.
+
+Therefore, it is likely that it is not worth using conditional ``expect``\ s when
+more than one or two configurations are involved or when the lint may be
+triggered due to non-local changes (such as ``dead_code``).
+
+For more information about diagnostics in Rust, please see:
+
+ https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html
+
+Error handling
+--------------
+
+For some background and guidelines about Rust for Linux specific error handling,
+please see:
+
+ https://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust
diff --git a/Documentation/rust/general-information.rst b/Documentation/rust/general-information.rst
index 236c6dd3c647..6146b49b6a98 100644
--- a/Documentation/rust/general-information.rst
+++ b/Documentation/rust/general-information.rst
@@ -7,6 +7,16 @@ This document contains useful information to know when working with
the Rust support in the kernel.
+``no_std``
+----------
+
+The Rust support in the kernel can link only `core <https://doc.rust-lang.org/core/>`_,
+but not `std <https://doc.rust-lang.org/std/>`_. Crates for use in the
+kernel must opt into this behavior using the ``#![no_std]`` attribute.
+
+
+.. _rust_code_documentation:
+
Code documentation
------------------
@@ -14,10 +24,17 @@ Rust kernel code is documented using ``rustdoc``, its built-in documentation
generator.
The generated HTML docs include integrated search, linked items (e.g. types,
-functions, constants), source code, etc. They may be read at (TODO: link when
-in mainline and generated alongside the rest of the documentation):
+functions, constants), source code, etc. They may be read at:
+
+ https://rust.docs.kernel.org
+
+For linux-next, please see:
+
+ https://rust.docs.kernel.org/next/
- http://kernel.org/
+There are also tags for each main release, e.g.:
+
+ https://rust.docs.kernel.org/6.10/
The docs can also be easily generated and read locally. This is quite fast
(same order as compiling the code itself) and no special tools or environment
@@ -64,6 +81,63 @@ but it is intended that coverage is expanded as time goes on. "Leaf" modules
(e.g. drivers) should not use the C bindings directly. Instead, subsystems
should provide as-safe-as-possible abstractions as needed.
+.. code-block::
+
+ rust/bindings/
+ (rust/helpers/)
+
+ include/ -----+ <-+
+ | |
+ drivers/ rust/kernel/ +----------+ <-+ |
+ fs/ | bindgen | |
+ .../ +-------------------+ +----------+ --+ |
+ | Abstractions | | |
+ +---------+ | +------+ +------+ | +----------+ | |
+ | my_foo | -----> | | foo | | bar | | -------> | Bindings | <-+ |
+ | driver | Safe | | sub- | | sub- | | Unsafe | | |
+ +---------+ | |system| |system| | | bindings | <-----+
+ | | +------+ +------+ | | crate | |
+ | | kernel crate | +----------+ |
+ | +-------------------+ |
+ | |
+ +------------------# FORBIDDEN #--------------------------------+
+
+The main idea is to encapsulate all direct interaction with the kernel's C APIs
+into carefully reviewed and documented abstractions. Then users of these
+abstractions cannot introduce undefined behavior (UB) as long as:
+
+#. The abstractions are correct ("sound").
+#. Any ``unsafe`` blocks respect the safety contract necessary to call the
+ operations inside the block. Similarly, any ``unsafe impl``\ s respect the
+ safety contract necessary to implement the trait.
+
+Bindings
+~~~~~~~~
+
+By including a C header from ``include/`` into
+``rust/bindings/bindings_helper.h``, the ``bindgen`` tool will auto-generate the
+bindings for the included subsystem. After building, see the ``*_generated.rs``
+output files in the ``rust/bindings/`` directory.
+
+For parts of the C header that ``bindgen`` does not auto generate, e.g. C
+``inline`` functions or non-trivial macros, it is acceptable to add a small
+wrapper function to ``rust/helpers/`` to make it available for the Rust side as
+well.
+
+Abstractions
+~~~~~~~~~~~~
+
+Abstractions are the layer between the bindings and the in-kernel users. They
+are located in ``rust/kernel/`` and their role is to encapsulate the unsafe
+access to the bindings into an as-safe-as-possible API that they expose to their
+users. Users of the abstractions include things like drivers or file systems
+written in Rust.
+
+Besides the safety aspect, the abstractions are supposed to be "ergonomic", in
+the sense that they turn the C interfaces into "idiomatic" Rust code. Basic
+examples are to turn the C resource acquisition and release into Rust
+constructors and destructors or C integer error codes into Rust's ``Result``\ s.
+
Conditional compilation
-----------------------
@@ -78,26 +152,10 @@ configuration:
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // Disabled
+For other predicates that Rust's ``cfg`` does not support, e.g. expressions with
+numerical comparisons, one may define a new Kconfig symbol:
-Testing
--------
-
-There are the tests that come from the examples in the Rust documentation
-and get transformed into KUnit tests. These can be run via KUnit. For example
-via ``kunit_tool`` (``kunit.py``) on the command line::
-
- ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
-
-Alternatively, KUnit can run them as kernel built-in at boot. Refer to
-Documentation/dev-tools/kunit/index.rst for the general KUnit documentation
-and Documentation/dev-tools/kunit/architecture.rst for the details of kernel
-built-in vs. command line testing.
-
-Additionally, there are the ``#[test]`` tests. These can be run using
-the ``rusttest`` Make target::
-
- make LLVM=1 rusttest
+.. code-block:: kconfig
-This requires the kernel ``.config`` and downloads external repositories.
-It runs the ``#[test]`` tests on the host (currently) and thus is fairly
-limited in what these tests can test.
+ config RUSTC_VERSION_MIN_107900
+ def_bool y if RUSTC_VERSION >= 107900
diff --git a/Documentation/rust/index.rst b/Documentation/rust/index.rst
index 965f2db529e0..ec62001c7d8c 100644
--- a/Documentation/rust/index.rst
+++ b/Documentation/rust/index.rst
@@ -25,13 +25,27 @@ support is still in development/experimental, especially for certain kernel
configurations.
+Code documentation
+------------------
+
+Given a kernel configuration, the kernel may generate Rust code documentation,
+i.e. HTML rendered by the ``rustdoc`` tool.
+
.. only:: rustdoc and html
- You can also browse `rustdoc documentation <rustdoc/kernel/index.html>`_.
+ This kernel documentation was built with `Rust code documentation
+ <rustdoc/kernel/index.html>`_.
.. only:: not rustdoc and html
- This documentation does not include rustdoc generated information.
+ This kernel documentation was not built with Rust code documentation.
+
+A pregenerated version is provided at:
+
+ https://rust.docs.kernel.org
+
+Please see the :ref:`Code documentation <rust_code_documentation>` section for
+more details.
.. toctree::
:maxdepth: 1
@@ -40,6 +54,10 @@ configurations.
general-information
coding-guidelines
arch-support
+ testing
+
+You can also find learning materials for Rust in its section in
+:doc:`../process/kernel-docs`.
.. only:: subproject and html
diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst
index cc3f11e0d441..155f7107329a 100644
--- a/Documentation/rust/quick-start.rst
+++ b/Documentation/rust/quick-start.rst
@@ -5,17 +5,148 @@ Quick Start
This document describes how to get started with kernel development in Rust.
+There are a few ways to install a Rust toolchain needed for kernel development.
+A simple way is to use the packages from your Linux distribution if they are
+suitable -- the first section below explains this approach. An advantage of this
+approach is that, typically, the distribution will match the LLVM used by Rust
+and Clang.
+
+Another way is using the prebuilt stable versions of LLVM+Rust provided on
+`kernel.org <https://kernel.org/pub/tools/llvm/rust/>`_. These are the same slim
+and fast LLVM toolchains from :ref:`Getting LLVM <getting_llvm>` with versions
+of Rust added to them that Rust for Linux supports. Two sets are provided: the
+"latest LLVM" and "matching LLVM" (please see the link for more information).
+
+Alternatively, the next two "Requirements" sections explain each component and
+how to install them through ``rustup``, the standalone installers from Rust
+and/or building them.
+
+The rest of the document explains other aspects on how to get started.
+
+
+Distributions
+-------------
+
+Arch Linux
+**********
+
+Arch Linux provides recent Rust releases and thus it should generally work out
+of the box, e.g.::
+
+ pacman -S rust rust-src rust-bindgen
+
+
+Debian
+******
+
+Debian Testing and Debian Unstable (Sid), outside of the freeze period, provide
+recent Rust releases and thus they should generally work out of the box, e.g.::
+
+ apt install rustc rust-src bindgen rustfmt rust-clippy
+
+
+Fedora Linux
+************
+
+Fedora Linux provides recent Rust releases and thus it should generally work out
+of the box, e.g.::
+
+ dnf install rust rust-src bindgen-cli rustfmt clippy
+
+
+Gentoo Linux
+************
+
+Gentoo Linux (and especially the testing branch) provides recent Rust releases
+and thus it should generally work out of the box, e.g.::
+
+ USE='rust-src rustfmt clippy' emerge dev-lang/rust dev-util/bindgen
+
+``LIBCLANG_PATH`` may need to be set.
+
+
+Nix
+***
+
+Nix (unstable channel) provides recent Rust releases and thus it should
+generally work out of the box, e.g.::
+
+ { pkgs ? import <nixpkgs> {} }:
+ pkgs.mkShell {
+ nativeBuildInputs = with pkgs; [ rustc rust-bindgen rustfmt clippy ];
+ RUST_LIB_SRC = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
+ }
+
+
+openSUSE
+********
+
+openSUSE Slowroll and openSUSE Tumbleweed provide recent Rust releases and thus
+they should generally work out of the box, e.g.::
+
+ zypper install rust rust1.79-src rust-bindgen clang
+
+
+Ubuntu
+******
+
+25.04
+~~~~~
+
+The latest Ubuntu releases provide recent Rust releases and thus they should
+generally work out of the box, e.g.::
+
+ apt install rustc rust-src bindgen rustfmt rust-clippy
+
+In addition, ``RUST_LIB_SRC`` needs to be set, e.g.::
+
+ RUST_LIB_SRC=/usr/src/rustc-$(rustc --version | cut -d' ' -f2)/library
+
+For convenience, ``RUST_LIB_SRC`` can be exported to the global environment.
+
+
+24.04 LTS and older
+~~~~~~~~~~~~~~~~~~~
+
+Though Ubuntu 24.04 LTS and older versions still provide recent Rust
+releases, they require some additional configuration to be set, using
+the versioned packages, e.g.::
+
+ apt install rustc-1.80 rust-1.80-src bindgen-0.65 rustfmt-1.80 \
+ rust-1.80-clippy
+ ln -s /usr/lib/rust-1.80/bin/rustfmt /usr/bin/rustfmt-1.80
+ ln -s /usr/lib/rust-1.80/bin/clippy-driver /usr/bin/clippy-driver-1.80
+
+None of these packages set their tools as defaults; therefore they should be
+specified explicitly, e.g.::
+
+ make LLVM=1 RUSTC=rustc-1.80 RUSTDOC=rustdoc-1.80 RUSTFMT=rustfmt-1.80 \
+ CLIPPY_DRIVER=clippy-driver-1.80 BINDGEN=bindgen-0.65
+
+Alternatively, modify the ``PATH`` variable to place the Rust 1.80 binaries
+first and set ``bindgen`` as the default, e.g.::
+
+ PATH=/usr/lib/rust-1.80/bin:$PATH
+ update-alternatives --install /usr/bin/bindgen bindgen \
+ /usr/bin/bindgen-0.65 100
+ update-alternatives --set bindgen /usr/bin/bindgen-0.65
+
+``RUST_LIB_SRC`` needs to be set when using the versioned packages, e.g.::
+
+ RUST_LIB_SRC=/usr/src/rustc-$(rustc-1.80 --version | cut -d' ' -f2)/library
+
+For convenience, ``RUST_LIB_SRC`` can be exported to the global environment.
+
+In addition, ``bindgen-0.65`` is available in newer releases (24.04 LTS and
+24.10), but it may not be available in older ones (20.04 LTS and 22.04 LTS),
+thus ``bindgen`` may need to be built manually (please see below).
+
Requirements: Building
----------------------
This section explains how to fetch the tools needed for building.
-Some of these requirements might be available from Linux distributions
-under names like ``rustc``, ``rust-src``, ``rust-bindgen``, etc. However,
-at the time of writing, they are likely not to be recent enough unless
-the distribution tracks the latest releases.
-
To easily check whether the requirements are met, the following target
can be used::
@@ -29,16 +160,15 @@ if that is the case.
rustc
*****
-A particular version of the Rust compiler is required. Newer versions may or
-may not work because, for the moment, the kernel depends on some unstable
-Rust features.
+A recent version of the Rust compiler is required.
If ``rustup`` is being used, enter the kernel build directory (or use
-``--path=<build-dir>`` argument to the ``set`` sub-command) and run::
+``--path=<build-dir>`` argument to the ``set`` sub-command) and run,
+for instance::
- rustup override set $(scripts/min-tool-version.sh rustc)
+ rustup override set stable
-This will configure your working directory to use the correct version of
+This will configure your working directory to use the given version of
``rustc`` without affecting your default toolchain.
Note that the override applies to the current working directory (and its
@@ -53,7 +183,7 @@ Rust standard library source
****************************
The Rust standard library source is required because the build system will
-cross-compile ``core`` and ``alloc``.
+cross-compile ``core``.
If ``rustup`` is being used, run::
@@ -65,9 +195,9 @@ version later on requires re-adding the component.
Otherwise, if a standalone installer is used, the Rust source tree may be
downloaded into the toolchain's installation folder::
- curl -L "https://static.rust-lang.org/dist/rust-src-$(scripts/min-tool-version.sh rustc).tar.gz" |
+ curl -L "https://static.rust-lang.org/dist/rust-src-$(rustc --version | cut -d' ' -f2).tar.gz" |
tar -xzf - -C "$(rustc --print sysroot)/lib" \
- "rust-src-$(scripts/min-tool-version.sh rustc)/rust-src/lib/" \
+ "rust-src-$(rustc --version | cut -d' ' -f2)/rust-src/lib/" \
--strip-components=3
In this case, upgrading the Rust compiler version later on requires manually
@@ -101,26 +231,22 @@ bindgen
*******
The bindings to the C side of the kernel are generated at build time using
-the ``bindgen`` tool. A particular version is required.
-
-Install it via (note that this will download and build the tool from source)::
-
- cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli
-
-``bindgen`` needs to find a suitable ``libclang`` in order to work. If it is
-not found (or a different ``libclang`` than the one found should be used),
-the process can be tweaked using the environment variables understood by
-``clang-sys`` (the Rust bindings crate that ``bindgen`` uses to access
-``libclang``):
+the ``bindgen`` tool.
-* ``LLVM_CONFIG_PATH`` can be pointed to an ``llvm-config`` executable.
+Install it, for instance, via (note that this will download and build the tool
+from source)::
-* Or ``LIBCLANG_PATH`` can be pointed to a ``libclang`` shared library
- or to the directory containing it.
+ cargo install --locked bindgen-cli
-* Or ``CLANG_PATH`` can be pointed to a ``clang`` executable.
+``bindgen`` uses the ``clang-sys`` crate to find a suitable ``libclang`` (which
+may be linked statically, dynamically or loaded at runtime). By default, the
+``cargo`` command above will produce a ``bindgen`` binary that will load
+``libclang`` at runtime. If it is not found (or a different ``libclang`` than
+the one found should be used), the process can be tweaked, e.g. by using the
+``LIBCLANG_PATH`` environment variable. For details, please see ``clang-sys``'s
+documentation at:
-For details, please see ``clang-sys``'s documentation at:
+ https://github.com/KyleMayes/clang-sys#linking
https://github.com/KyleMayes/clang-sys#environment-variables
@@ -164,20 +290,6 @@ can be installed manually::
The standalone installers also come with ``clippy``.
-cargo
-*****
-
-``cargo`` is the Rust native build system. It is currently required to run
-the tests since it is used to build a custom standard library that contains
-the facilities provided by the custom ``alloc`` in the kernel. The tests can
-be run using the ``rusttest`` Make target.
-
-If ``rustup`` is being used, all the profiles already install the tool,
-thus nothing needs to be done.
-
-The standalone installers also come with ``cargo``.
-
-
rustdoc
*******
@@ -248,7 +360,7 @@ If GDB/Binutils is used and Rust symbols are not getting demangled, the reason
is the toolchain does not support Rust's new v0 mangling scheme yet.
There are a few ways out:
- - Install a newer release (GDB >= 10.2, Binutils >= 2.36).
+- Install a newer release (GDB >= 10.2, Binutils >= 2.36).
- - Some versions of GDB (e.g. vanilla GDB 10.1) are able to use
- the pre-demangled names embedded in the debug info (``CONFIG_DEBUG_INFO``).
+- Some versions of GDB (e.g. vanilla GDB 10.1) are able to use
+ the pre-demangled names embedded in the debug info (``CONFIG_DEBUG_INFO``).
diff --git a/Documentation/rust/testing.rst b/Documentation/rust/testing.rst
new file mode 100644
index 000000000000..f43cb77bcc69
--- /dev/null
+++ b/Documentation/rust/testing.rst
@@ -0,0 +1,236 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Testing
+=======
+
+This document contains useful information how to test the Rust code in the
+kernel.
+
+There are three sorts of tests:
+
+- The KUnit tests.
+- The ``#[test]`` tests.
+- The Kselftests.
+
+The KUnit tests
+---------------
+
+These are the tests that come from the examples in the Rust documentation. They
+get transformed into KUnit tests.
+
+Usage
+*****
+
+These tests can be run via KUnit. For example via ``kunit_tool`` (``kunit.py``)
+on the command line::
+
+ ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
+
+Alternatively, KUnit can run them as kernel built-in at boot. Refer to
+Documentation/dev-tools/kunit/index.rst for the general KUnit documentation
+and Documentation/dev-tools/kunit/architecture.rst for the details of kernel
+built-in vs. command line testing.
+
+To use these KUnit doctests, the following must be enabled::
+
+ CONFIG_KUNIT
+ Kernel hacking -> Kernel Testing and Coverage -> KUnit - Enable support for unit tests
+ CONFIG_RUST_KERNEL_DOCTESTS
+ Kernel hacking -> Rust hacking -> Doctests for the `kernel` crate
+
+in the kernel config system.
+
+KUnit tests are documentation tests
+***********************************
+
+These documentation tests are typically examples of usage of any item (e.g.
+function, struct, module...).
+
+They are very convenient because they are just written alongside the
+documentation. For instance:
+
+.. code-block:: rust
+
+ /// Sums two numbers.
+ ///
+ /// ```
+ /// assert_eq!(mymod::f(10, 20), 30);
+ /// ```
+ pub fn f(a: i32, b: i32) -> i32 {
+ a + b
+ }
+
+In userspace, the tests are collected and run via ``rustdoc``. Using the tool
+as-is would be useful already, since it allows verifying that examples compile
+(thus enforcing they are kept in sync with the code they document) and as well
+as running those that do not depend on in-kernel APIs.
+
+For the kernel, however, these tests get transformed into KUnit test suites.
+This means that doctests get compiled as Rust kernel objects, allowing them to
+run against a built kernel.
+
+A benefit of this KUnit integration is that Rust doctests get to reuse existing
+testing facilities. For instance, the kernel log would look like::
+
+ KTAP version 1
+ 1..1
+ KTAP version 1
+ # Subtest: rust_doctests_kernel
+ 1..59
+ # rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13
+ ok 1 rust_doctest_kernel_build_assert_rs_0
+ # rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56
+ ok 2 rust_doctest_kernel_build_assert_rs_1
+ # rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122
+ ok 3 rust_doctest_kernel_init_rs_0
+ ...
+ # rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
+ ok 59 rust_doctest_kernel_types_rs_2
+ # rust_doctests_kernel: pass:59 fail:0 skip:0 total:59
+ # Totals: pass:59 fail:0 skip:0 total:59
+ ok 1 rust_doctests_kernel
+
+Tests using the `? <https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator>`_
+operator are also supported as usual, e.g.:
+
+.. code-block:: rust
+
+ /// ```
+ /// # use kernel::{spawn_work_item, workqueue};
+ /// spawn_work_item!(workqueue::system(), || pr_info!("x\n"))?;
+ /// # Ok::<(), Error>(())
+ /// ```
+
+The tests are also compiled with Clippy under ``CLIPPY=1``, just like normal
+code, thus also benefitting from extra linting.
+
+In order for developers to easily see which line of doctest code caused a
+failure, a KTAP diagnostic line is printed to the log. This contains the
+location (file and line) of the original test (i.e. instead of the location in
+the generated Rust file)::
+
+ # rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
+
+Rust tests appear to assert using the usual ``assert!`` and ``assert_eq!``
+macros from the Rust standard library (``core``). We provide a custom version
+that forwards the call to KUnit instead. Importantly, these macros do not
+require passing context, unlike those for KUnit testing (i.e.
+``struct kunit *``). This makes them easier to use, and readers of the
+documentation do not need to care about which testing framework is used. In
+addition, it may allow us to test third-party code more easily in the future.
+
+A current limitation is that KUnit does not support assertions in other tasks.
+Thus, we presently simply print an error to the kernel log if an assertion
+actually failed. Additionally, doctests are not run for nonpublic functions.
+
+Since these tests are examples, i.e. they are part of the documentation, they
+should generally be written like "real code". Thus, for example, instead of
+using ``unwrap()`` or ``expect()``, use the ``?`` operator. For more background,
+please see:
+
+ https://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust
+
+The ``#[test]`` tests
+---------------------
+
+Additionally, there are the ``#[test]`` tests. Like for documentation tests,
+these are also fairly similar to what you would expect from userspace, and they
+are also mapped to KUnit.
+
+These tests are introduced by the ``kunit_tests`` procedural macro, which takes
+the name of the test suite as an argument.
+
+For instance, assume we want to test the function ``f`` from the documentation
+tests section. We could write, in the same file where we have our function:
+
+.. code-block:: rust
+
+ #[kunit_tests(rust_kernel_mymod)]
+ mod tests {
+ use super::*;
+
+ #[test]
+ fn test_f() {
+ assert_eq!(f(10, 20), 30);
+ }
+ }
+
+And if we run it, the kernel log would look like::
+
+ KTAP version 1
+ # Subtest: rust_kernel_mymod
+ # speed: normal
+ 1..1
+ # test_f.speed: normal
+ ok 1 test_f
+ ok 1 rust_kernel_mymod
+
+Like documentation tests, the ``assert!`` and ``assert_eq!`` macros are mapped
+back to KUnit and do not panic. Similarly, the
+`? <https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator>`_
+operator is supported, i.e. the test functions may return either nothing (i.e.
+the unit type ``()``) or ``Result`` (i.e. any ``Result<T, E>``). For instance:
+
+.. code-block:: rust
+
+ #[kunit_tests(rust_kernel_mymod)]
+ mod tests {
+ use super::*;
+
+ #[test]
+ fn test_g() -> Result {
+ let x = g()?;
+ assert_eq!(x, 30);
+ Ok(())
+ }
+ }
+
+If we run the test and the call to ``g`` fails, then the kernel log would show::
+
+ KTAP version 1
+ # Subtest: rust_kernel_mymod
+ # speed: normal
+ 1..1
+ # test_g: ASSERTION FAILED at rust/kernel/lib.rs:335
+ Expected is_test_result_ok(test_g()) to be true, but is false
+ # test_g.speed: normal
+ not ok 1 test_g
+ not ok 1 rust_kernel_mymod
+
+If a ``#[test]`` test could be useful as an example for the user, then please
+use a documentation test instead. Even edge cases of an API, e.g. error or
+boundary cases, can be interesting to show in examples.
+
+The ``rusttest`` host tests
+---------------------------
+
+These are userspace tests that can be built and run in the host (i.e. the one
+that performs the kernel build) using the ``rusttest`` Make target::
+
+ make LLVM=1 rusttest
+
+This requires the kernel ``.config``.
+
+Currently, they are mostly used for testing the ``macros`` crate's examples.
+
+The Kselftests
+--------------
+
+Kselftests are also available in the ``tools/testing/selftests/rust`` folder.
+
+The kernel config options required for the tests are listed in the
+``tools/testing/selftests/rust/config`` file and can be included with the aid
+of the ``merge_config.sh`` script::
+
+ ./scripts/kconfig/merge_config.sh .config tools/testing/selftests/rust/config
+
+The kselftests are built within the kernel source tree and are intended to
+be executed on a system that is running the same kernel.
+
+Once a kernel matching the source tree has been installed and booted, the
+tests can be compiled and executed using the following command::
+
+ make TARGETS="rust" kselftest
+
+Refer to Documentation/dev-tools/kselftest.rst for the general Kselftest
+documentation.