Skip to content

Commit

Permalink
Merge branch 'rust-next' of https://github.com/Rust-for-Linux/linux.git
Browse files Browse the repository at this point in the history
# Conflicts:
#	rust/bindings/bindings_helper.h
  • Loading branch information
sfrothwell committed Jul 25, 2024
2 parents d04abd4 + b126341 commit 6e10018
Show file tree
Hide file tree
Showing 25 changed files with 1,058 additions and 236 deletions.
9 changes: 1 addition & 8 deletions Documentation/process/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,7 @@ docs on :ref:`Building Linux with Clang/LLVM <kbuild_llvm>`.
Rust (optional)
---------------

A particular version of the Rust toolchain is required. Newer versions may or
may not work because the kernel depends on some unstable Rust features, for
the moment.

Each Rust toolchain comes with several "components", some of which are required
(like ``rustc``) and some that are optional. The ``rust-src`` component (which
is optional) needs to be installed to build the kernel. Other components are
useful for developing.
A recent version of the Rust compiler is required.

Please see Documentation/rust/quick-start.rst for instructions on how to
satisfy the build requirements of Rust support. In particular, the ``Makefile``
Expand Down
8 changes: 8 additions & 0 deletions Documentation/rust/general-information.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ 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.


Code documentation
------------------

Expand Down
143 changes: 100 additions & 43 deletions Documentation/rust/quick-start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,93 @@ 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 Unstable (Sid), outside of the freeze period, provides recent Rust
releases and thus it 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


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::

Expand All @@ -29,16 +105,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
Expand All @@ -65,9 +140,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
Expand Down Expand Up @@ -101,26 +176,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.
the ``bindgen`` tool.

Install it via (note that this will download and build the tool from source)::
Install it, for instance, via (note that this will download and build the tool
from source)::

cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli
cargo install --locked 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``):
``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:

* ``LLVM_CONFIG_PATH`` can be pointed to an ``llvm-config`` executable.

* Or ``LIBCLANG_PATH`` can be pointed to a ``libclang`` shared library
or to the directory containing it.

* Or ``CLANG_PATH`` can be pointed to a ``clang`` executable.

For details, please see ``clang-sys``'s documentation at:
https://github.com/KyleMayes/clang-sys#linking

https://github.com/KyleMayes/clang-sys#environment-variables

Expand Down Expand Up @@ -164,20 +235,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
*******

Expand Down
5 changes: 2 additions & 3 deletions Documentation/rust/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,8 @@ Additionally, there are the ``#[test]`` tests. These can be run using the

make LLVM=1 rusttest

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.
This requires the kernel ``.config``. It runs the ``#[test]`` tests on the host
(currently) and thus is fairly limited in what these tests can test.

The Kselftests
--------------
Expand Down
30 changes: 16 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -445,17 +445,17 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
# host programs.
export rust_common_flags := --edition=2021 \
-Zbinary_dep_depinfo=y \
-Dunsafe_op_in_unsafe_fn -Drust_2018_idioms \
-Dunreachable_pub -Dnon_ascii_idents \
-Dunsafe_op_in_unsafe_fn \
-Dnon_ascii_idents \
-Wrust_2018_idioms \
-Wunreachable_pub \
-Wmissing_docs \
-Drustdoc::missing_crate_level_docs \
-Dclippy::correctness -Dclippy::style \
-Dclippy::suspicious -Dclippy::complexity \
-Dclippy::perf \
-Dclippy::let_unit_value -Dclippy::mut_mut \
-Dclippy::needless_bitwise_bool \
-Dclippy::needless_continue \
-Dclippy::no_mangle_with_rust_abi \
-Wrustdoc::missing_crate_level_docs \
-Wclippy::all \
-Wclippy::mut_mut \
-Wclippy::needless_bitwise_bool \
-Wclippy::needless_continue \
-Wclippy::no_mangle_with_rust_abi \
-Wclippy::dbg_macro

KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(HOST_LFS_CFLAGS) \
Expand Down Expand Up @@ -493,7 +493,6 @@ RUSTDOC = rustdoc
RUSTFMT = rustfmt
CLIPPY_DRIVER = clippy-driver
BINDGEN = bindgen
CARGO = cargo
PAHOLE = pahole
RESOLVE_BTFIDS = $(objtree)/tools/bpf/resolve_btfids/resolve_btfids
LEX = flex
Expand Down Expand Up @@ -559,7 +558,7 @@ KBUILD_RUSTFLAGS := $(rust_common_flags) \
-Csymbol-mangling-version=v0 \
-Crelocation-model=static \
-Zfunction-sections=n \
-Dclippy::float_arithmetic
-Wclippy::float_arithmetic

KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
Expand Down Expand Up @@ -587,7 +586,7 @@ endif
export RUSTC_BOOTSTRAP := 1

export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN CARGO
export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN
export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
Expand Down Expand Up @@ -1959,9 +1958,12 @@ quiet_cmd_tags = GEN $@
tags TAGS cscope gtags: FORCE
$(call cmd,tags)

# IDE support targets
# Generate rust-project.json (a file that describes the structure of non-Cargo
# Rust projects) for rust-analyzer (an implementation of the Language Server
# Protocol).
PHONY += rust-analyzer
rust-analyzer:
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
$(Q)$(MAKE) $(build)=rust $@

# Script to generate missing namespace dependencies
Expand Down
46 changes: 32 additions & 14 deletions include/linux/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/fault-inject-usercopy.h>
#include <linux/instrumented.h>
#include <linux/minmax.h>
#include <linux/nospec.h>
#include <linux/sched.h>
#include <linux/thread_info.h>

Expand Down Expand Up @@ -138,13 +139,26 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
return raw_copy_to_user(to, from, n);
}

#ifdef INLINE_COPY_FROM_USER
/*
* Architectures that #define INLINE_COPY_TO_USER use this function
* directly in the normal copy_to/from_user(), the other ones go
* through an extern _copy_to/from_user(), which expands the same code
* here.
*
* Rust code always uses the extern definition.
*/
static inline __must_check unsigned long
_copy_from_user(void *to, const void __user *from, unsigned long n)
_inline_copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long res = n;
might_fault();
if (!should_fail_usercopy() && likely(access_ok(from, n))) {
/*
* Ensure that bad access_ok() speculation will not
* lead to nasty side effects *after* the copy is
* finished:
*/
barrier_nospec();
instrument_copy_from_user_before(to, from, n);
res = raw_copy_from_user(to, from, n);
instrument_copy_from_user_after(to, from, n, res);
Expand All @@ -153,14 +167,11 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
memset(to + (n - res), 0, res);
return res;
}
#else
extern __must_check unsigned long
_copy_from_user(void *, const void __user *, unsigned long);
#endif

#ifdef INLINE_COPY_TO_USER
static inline __must_check unsigned long
_copy_to_user(void __user *to, const void *from, unsigned long n)
_inline_copy_to_user(void __user *to, const void *from, unsigned long n)
{
might_fault();
if (should_fail_usercopy())
Expand All @@ -171,25 +182,32 @@ _copy_to_user(void __user *to, const void *from, unsigned long n)
}
return n;
}
#else
extern __must_check unsigned long
_copy_to_user(void __user *, const void *, unsigned long);
#endif

static __always_inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (check_copy_size(to, n, false))
n = _copy_from_user(to, from, n);
return n;
if (!check_copy_size(to, n, false))
return n;
#ifdef INLINE_COPY_FROM_USER
return _inline_copy_from_user(to, from, n);
#else
return _copy_from_user(to, from, n);
#endif
}

static __always_inline unsigned long __must_check
copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (check_copy_size(from, n, true))
n = _copy_to_user(to, from, n);
return n;
if (!check_copy_size(from, n, true))
return n;

#ifdef INLINE_COPY_TO_USER
return _inline_copy_to_user(to, from, n);
#else
return _copy_to_user(to, from, n);
#endif
}

#ifndef copy_mc_to_kernel
Expand Down
Loading

0 comments on commit 6e10018

Please sign in to comment.