2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-11-27 12:04:22 +08:00

Rust changes for v6.8

Another routine one in terms of features. In terms of lines, this time
 the 'alloc' version upgrade is less prominent, given that it was fairly
 small (and we did not have two upgrades).
 
 Toolchain and infrastructure:
 
  - Upgrade to Rust 1.74.1.
 
    The patch release includes a fix for an ICE that the Apple AGX GPU
    driver was hitting.
 
  - Support 'srctree'-relative links in Rust code documentation.
 
  - Automate part of the manual constants handling (i.e. the ones not
    recognised by 'bindgen').
 
  - Suppress searching builtin sysroot to avoid confusion with installed
    sysroots, needed for the to-be-merged arm64 support which uses
    a builtin target.
 
  - Ignore '__preserve_most' functions for 'bindgen'.
 
  - Reduce header inclusion bloat in exports.
 
 'kernel' crate:
 
  - Implement 'Debug' for 'CString'.
 
  - Make 'CondVar::wait()' an uninterruptible wait.
 
 'macros' crate:
 
  - Update 'paste!' to accept string literals.
 
  - Improve '#[vtable]' documentation.
 
 Documentation:
 
  - Add testing section (KUnit and 'rusttest' target).
 
  - Remove 'CC=clang' mentions.
 
  - Clarify that 'rustup override' applies to build directory.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPjU5OPd5QIZ9jqqOGXyLc2htIW0FAmWbS68ACgkQGXyLc2ht
 IW1V4w//ToMxdyHTnoqFyzI5X4mzxaV8vhEViGs5eXG87d0E8WwSRCA4weEGTbER
 06huyUI1tTbYgpsOEyuUSEDd/0GiA+sGseaqS4kJ7+aA6fSof7E6nA4d2SURBb2O
 0F1c3DucGbeDzZz0GZDWSnoF3RwQWRz1hPR9scMcQi4d69r5mT+HdD1UryXaGkXQ
 9gDeWhmqO4EzEjFR/gd0fYxd/z7OgXsaUQJk4fpDGDJ+/USPzrE99iGoHINB6VRA
 mWsq5g0Po6aPwmlPDcW6bgRrLEWpzHftCNAZjQbjfT4mKjYJg4GJaqShCfM+wkZN
 3NVLxueJ0ZzLXmHxpMjx9WdHM1j/MM31W/n0/Opgnalv0lETZdNKy/Ep1Fj+AOTP
 kKwU2bQT66We78cjY6Fh2noCNv3td9g59/q8TfKAFxsy16BqL/RLqQ21Ft0hyLO+
 ebvOOO0o2ul/7onaOFhrXMRdVvaAXeK1c64kiGRUr16X5D5UcvR+ZkJ/LVf2ozvS
 mDtzXB561WCyVSfTFz0buGdudO4NWE+7Dh7msXhE6W6faFN+7MA6pfWZro64k+az
 gEmcCcwjUMpV0IrvCWH0dW1NG6XGqGQ/PkGTYdIyZ+1GajEhwNILuIPKuM8VXwLZ
 zmu+y4xdpPd7hMjncopCsb8G3DidAN7zeYea5tnAGILCmOZMOX4=
 =w+n8
 -----END PGP SIGNATURE-----

Merge tag 'rust-6.8' of https://github.com/Rust-for-Linux/linux

Pull Rust updates from Miguel Ojeda:
 "Another routine one in terms of features. In terms of lines, this time
  the 'alloc' version upgrade is less prominent, given that it was
  fairly small (and we did not have two upgrades)

  Toolchain and infrastructure:

   - Upgrade to Rust 1.74.1

     The patch release includes a fix for an ICE that the Apple AGX GPU
     driver was hitting

   - Support 'srctree'-relative links in Rust code documentation

   - Automate part of the manual constants handling (i.e. the ones not
     recognised by 'bindgen')

   - Suppress searching builtin sysroot to avoid confusion with
     installed sysroots, needed for the to-be-merged arm64 support which
     uses a builtin target

   - Ignore '__preserve_most' functions for 'bindgen'

   - Reduce header inclusion bloat in exports

  'kernel' crate:

   - Implement 'Debug' for 'CString'

   - Make 'CondVar::wait()' an uninterruptible wait

  'macros' crate:

   - Update 'paste!' to accept string literals

   - Improve '#[vtable]' documentation

  Documentation:

   - Add testing section (KUnit and 'rusttest' target)

   - Remove 'CC=clang' mentions

   - Clarify that 'rustup override' applies to build directory"

* tag 'rust-6.8' of https://github.com/Rust-for-Linux/linux:
  docs: rust: Clarify that 'rustup override' applies to build directory
  docs: rust: Add rusttest info
  docs: rust: remove `CC=clang` mentions
  rust: support `srctree`-relative links
  rust: sync: Makes `CondVar::wait()` an uninterruptible wait
  rust: upgrade to Rust 1.74.1
  rust: Suppress searching builtin sysroot
  rust: macros: improve `#[vtable]` documentation
  rust: macros: update 'paste!' macro to accept string literals
  rust: bindings: rename const binding using sed
  rust: Ignore preserve-most functions
  rust: replace <linux/module.h> with <linux/export.h> in rust/exports.c
  rust: kernel: str: Implement Debug for CString
This commit is contained in:
Linus Torvalds 2024-01-11 13:05:41 -08:00
commit b6964fe239
28 changed files with 275 additions and 73 deletions

View File

@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
====================== =============== ======================================== ====================== =============== ========================================
GNU C 5.1 gcc --version GNU C 5.1 gcc --version
Clang/LLVM (optional) 11.0.0 clang --version Clang/LLVM (optional) 11.0.0 clang --version
Rust (optional) 1.73.0 rustc --version Rust (optional) 1.74.1 rustc --version
bindgen (optional) 0.65.1 bindgen --version bindgen (optional) 0.65.1 bindgen --version
GNU make 3.82 make --version GNU make 3.82 make --version
bash 4.2 bash --version bash 4.2 bash --version

View File

@ -177,6 +177,19 @@ please take a look at the ``rustdoc`` book at:
https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
In addition, the kernel supports creating links relative to the source tree by
prefixing the link destination with ``srctree/``. For instance:
.. code-block:: rust
//! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
or:
.. code-block:: rust
/// [`struct mutex`]: srctree/include/linux/mutex.h
Naming Naming
------ ------

View File

@ -77,3 +77,27 @@ configuration:
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`) #[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`) #[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // Disabled #[cfg(not(CONFIG_X))] // Disabled
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
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.

View File

@ -33,14 +33,18 @@ 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 may not work because, for the moment, the kernel depends on some unstable
Rust features. Rust features.
If ``rustup`` is being used, enter the checked out source code directory If ``rustup`` is being used, enter the kernel build directory (or use
and run:: ``--path=<build-dir>`` argument to the ``set`` sub-command) and run::
rustup override set $(scripts/min-tool-version.sh rustc) rustup override set $(scripts/min-tool-version.sh rustc)
This will configure your working directory to use the correct version of This will configure your working directory to use the correct version of
``rustc`` without affecting your default toolchain. If you are not using ``rustc`` without affecting your default toolchain.
``rustup``, fetch a standalone installer from:
Note that the override applies to the current working directory (and its
sub-directories).
If you are not using ``rustup``, fetch a standalone installer from:
https://forge.rust-lang.org/infra/other-installation-methods.html#standalone https://forge.rust-lang.org/infra/other-installation-methods.html#standalone
@ -76,7 +80,7 @@ libclang
``libclang`` (part of LLVM) is used by ``bindgen`` to understand the C code ``libclang`` (part of LLVM) is used by ``bindgen`` to understand the C code
in the kernel, which means LLVM needs to be installed; like when the kernel in the kernel, which means LLVM needs to be installed; like when the kernel
is compiled with ``CC=clang`` or ``LLVM=1``. is compiled with ``LLVM=1``.
Linux distributions are likely to have a suitable one available, so it is Linux distributions are likely to have a suitable one available, so it is
best to check that first. best to check that first.
@ -229,10 +233,6 @@ at the moment. That is::
make LLVM=1 make LLVM=1
For architectures that do not support a full LLVM toolchain, use::
make CC=clang
Using GCC also works for some configurations, but it is very experimental at Using GCC also works for some configurations, but it is very experimental at
the moment. the moment.

View File

@ -78,6 +78,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
$(rustc_target_flags) -L$(objtree)/$(obj) \ $(rustc_target_flags) -L$(objtree)/$(obj) \
--output $(rustdoc_output) \ --output $(rustdoc_output) \
--crate-name $(subst rustdoc-,,$@) \ --crate-name $(subst rustdoc-,,$@) \
$(if $(rustdoc_host),,--sysroot=/dev/null) \
@$(objtree)/include/generated/rustc_cfg $< @$(objtree)/include/generated/rustc_cfg $<
# The `html_logo_url` and `html_favicon_url` forms of the `doc` attribute # The `html_logo_url` and `html_favicon_url` forms of the `doc` attribute
@ -98,7 +99,8 @@ rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \
$(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \ $(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \
-e 's:rust-logo-[0-9a-f]+\.svg:logo.svg:g' \ -e 's:rust-logo-[0-9a-f]+\.svg:logo.svg:g' \
-e 's:favicon-[0-9a-f]+\.svg:logo.svg:g' \ -e 's:favicon-[0-9a-f]+\.svg:logo.svg:g' \
-e 's:<link rel="alternate icon" type="image/png" href="[/.]+/static\.files/favicon-(16x16|32x32)-[0-9a-f]+\.png">::g' -e 's:<link rel="alternate icon" type="image/png" href="[/.]+/static\.files/favicon-(16x16|32x32)-[0-9a-f]+\.png">::g' \
-e 's:<a href="srctree/([^"]+)">:<a href="$(abs_srctree)/\1">:g'
$(Q)for f in $(rustdoc_output)/static.files/rustdoc-*.css; do \ $(Q)for f in $(rustdoc_output)/static.files/rustdoc-*.css; do \
echo ".logo-container > img { object-fit: contain; }" >> $$f; done echo ".logo-container > img { object-fit: contain; }" >> $$f; done
@ -178,6 +180,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
--extern build_error --extern macros \ --extern build_error --extern macros \
--extern bindings --extern uapi \ --extern bindings --extern uapi \
--no-run --crate-name kernel -Zunstable-options \ --no-run --crate-name kernel -Zunstable-options \
--sysroot=/dev/null \
--test-builder $(objtree)/scripts/rustdoc_test_builder \ --test-builder $(objtree)/scripts/rustdoc_test_builder \
$< $(rustdoc_test_kernel_quiet); \ $< $(rustdoc_test_kernel_quiet); \
$(objtree)/scripts/rustdoc_test_gen $(objtree)/scripts/rustdoc_test_gen
@ -337,6 +340,8 @@ quiet_cmd_bindgen = BINDGEN $@
$(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \ $(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
$(shell grep -Ev '^#|^$$' $(srctree)/$(src)/bindgen_parameters) $(shell grep -Ev '^#|^$$' $(srctree)/$(src)/bindgen_parameters)
$(obj)/bindings/bindings_generated.rs: private bindgen_target_extra = ; \
sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@
$(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \ $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
$(src)/bindgen_parameters FORCE $(src)/bindgen_parameters FORCE
$(call if_changed_dep,bindgen) $(call if_changed_dep,bindgen)
@ -402,6 +407,7 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
--emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \ --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \
--crate-type rlib -L$(objtree)/$(obj) \ --crate-type rlib -L$(objtree)/$(obj) \
--crate-name $(patsubst %.o,%,$(notdir $@)) $< \ --crate-name $(patsubst %.o,%,$(notdir $@)) $< \
--sysroot=/dev/null \
$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@)
rust-analyzer: rust-analyzer:

View File

@ -345,18 +345,31 @@ extern "Rust" {
fn __rust_alloc_error_handler(size: usize, align: usize) -> !; fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
} }
/// Abort on memory allocation error or failure. /// Signal a memory allocation error.
/// ///
/// Callers of memory allocation APIs wishing to abort computation /// Callers of memory allocation APIs wishing to cease execution
/// in response to an allocation error are encouraged to call this function, /// in response to an allocation error are encouraged to call this function,
/// rather than directly invoking `panic!` or similar. /// rather than directly invoking [`panic!`] or similar.
/// ///
/// The default behavior of this function is to print a message to standard error /// This function is guaranteed to diverge (not return normally with a value), but depending on
/// and abort the process. /// global configuration, it may either panic (resulting in unwinding or aborting as per
/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`]. /// configuration for all panics), or abort the process (with no unwinding).
///
/// The default behavior is:
///
/// * If the binary links against `std` (typically the case), then
/// print a message to standard error and abort the process.
/// This behavior can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
/// Future versions of Rust may panic by default instead.
///
/// * If the binary does not link against `std` (all of its crates are marked
/// [`#![no_std]`][no_std]), then call [`panic!`] with a message.
/// [The panic handler] applies as to any panic.
/// ///
/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
/// [The panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute
/// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
#[stable(feature = "global_alloc", since = "1.28.0")] #[stable(feature = "global_alloc", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
#[cfg(all(not(no_global_oom_handling), not(test)))] #[cfg(all(not(no_global_oom_handling), not(test)))]
@ -397,9 +410,10 @@ pub mod __alloc_error_handler {
if unsafe { __rust_alloc_error_handler_should_panic != 0 } { if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
panic!("memory allocation of {size} bytes failed") panic!("memory allocation of {size} bytes failed")
} else { } else {
core::panicking::panic_nounwind_fmt(format_args!( core::panicking::panic_nounwind_fmt(
"memory allocation of {size} bytes failed" format_args!("memory allocation of {size} bytes failed"),
)) /* force_no_backtrace */ false,
)
} }
} }
} }

View File

@ -90,8 +90,8 @@
#![warn(missing_docs)] #![warn(missing_docs)]
#![allow(explicit_outlives_requirements)] #![allow(explicit_outlives_requirements)]
#![warn(multiple_supertrait_upcastable)] #![warn(multiple_supertrait_upcastable)]
#![cfg_attr(not(bootstrap), allow(internal_features))] #![allow(internal_features)]
#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] #![allow(rustdoc::redundant_explicit_links)]
// //
// Library features: // Library features:
// tidy-alphabetical-start // tidy-alphabetical-start
@ -122,6 +122,7 @@
#![feature(const_waker)] #![feature(const_waker)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(core_panic)] #![feature(core_panic)]
#![feature(deprecated_suggestion)]
#![feature(dispatch_from_dyn)] #![feature(dispatch_from_dyn)]
#![feature(error_generic_member_access)] #![feature(error_generic_member_access)]
#![feature(error_in_core)] #![feature(error_in_core)]
@ -145,7 +146,6 @@
#![feature(ptr_metadata)] #![feature(ptr_metadata)]
#![feature(ptr_sub_ptr)] #![feature(ptr_sub_ptr)]
#![feature(receiver_trait)] #![feature(receiver_trait)]
#![feature(saturating_int_impl)]
#![feature(set_ptr_value)] #![feature(set_ptr_value)]
#![feature(sized_type_properties)] #![feature(sized_type_properties)]
#![feature(slice_from_ptr_range)] #![feature(slice_from_ptr_range)]

View File

@ -594,7 +594,7 @@ impl<T> [T] {
/// ``` /// ```
#[rustc_allow_incoherent_impl] #[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.3.0", note = "renamed to join")] #[deprecated(since = "1.3.0", note = "renamed to join", suggestion = "join")]
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where where
Self: Join<Separator>, Self: Join<Separator>,

View File

@ -1228,8 +1228,8 @@ impl<T, A: Allocator> Vec<T, A> {
/// Shortens the vector, keeping the first `len` elements and dropping /// Shortens the vector, keeping the first `len` elements and dropping
/// the rest. /// the rest.
/// ///
/// If `len` is greater than the vector's current length, this has no /// If `len` is greater or equal to the vector's current length, this has
/// effect. /// no effect.
/// ///
/// The [`drain`] method can emulate `truncate`, but causes the excess /// The [`drain`] method can emulate `truncate`, but causes the excess
/// elements to be returned instead of dropped. /// elements to be returned instead of dropped.
@ -1336,6 +1336,15 @@ impl<T, A: Allocator> Vec<T, A> {
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
/// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
/// ///
/// This method guarantees that for the purpose of the aliasing model, this method
/// does not materialize a reference to the underlying slice, and thus the returned pointer
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
/// Note that calling other methods that materialize mutable references to the slice,
/// or mutable references to specific elements you are planning on accessing through this pointer,
/// as well as writing to those elements, may still invalidate this pointer.
/// See the second example below for how this guarantee can be used.
///
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -1349,8 +1358,25 @@ impl<T, A: Allocator> Vec<T, A> {
/// } /// }
/// ``` /// ```
/// ///
/// Due to the aliasing guarantee, the following code is legal:
///
/// ```rust
/// unsafe {
/// let mut v = vec![0, 1, 2];
/// let ptr1 = v.as_ptr();
/// let _ = ptr1.read();
/// let ptr2 = v.as_mut_ptr().offset(2);
/// ptr2.write(2);
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`
/// // because it mutated a different element:
/// let _ = ptr1.read();
/// }
/// ```
///
/// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_mut_ptr`]: Vec::as_mut_ptr
/// [`as_ptr`]: Vec::as_ptr
#[stable(feature = "vec_as_ptr", since = "1.37.0")] #[stable(feature = "vec_as_ptr", since = "1.37.0")]
#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[inline] #[inline]
pub fn as_ptr(&self) -> *const T { pub fn as_ptr(&self) -> *const T {
// We shadow the slice method of the same name to avoid going through // We shadow the slice method of the same name to avoid going through
@ -1366,6 +1392,15 @@ impl<T, A: Allocator> Vec<T, A> {
/// Modifying the vector may cause its buffer to be reallocated, /// Modifying the vector may cause its buffer to be reallocated,
/// which would also make any pointers to it invalid. /// which would also make any pointers to it invalid.
/// ///
/// This method guarantees that for the purpose of the aliasing model, this method
/// does not materialize a reference to the underlying slice, and thus the returned pointer
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
/// Note that calling other methods that materialize references to the slice,
/// or references to specific elements you are planning on accessing through this pointer,
/// may still invalidate this pointer.
/// See the second example below for how this guarantee can be used.
///
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -1383,7 +1418,25 @@ impl<T, A: Allocator> Vec<T, A> {
/// } /// }
/// assert_eq!(&*x, &[0, 1, 2, 3]); /// assert_eq!(&*x, &[0, 1, 2, 3]);
/// ``` /// ```
///
/// Due to the aliasing guarantee, the following code is legal:
///
/// ```rust
/// unsafe {
/// let mut v = vec![0];
/// let ptr1 = v.as_mut_ptr();
/// ptr1.write(1);
/// let ptr2 = v.as_mut_ptr();
/// ptr2.write(2);
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
/// ptr1.write(3);
/// }
/// ```
///
/// [`as_mut_ptr`]: Vec::as_mut_ptr
/// [`as_ptr`]: Vec::as_ptr
#[stable(feature = "vec_as_ptr", since = "1.37.0")] #[stable(feature = "vec_as_ptr", since = "1.37.0")]
#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[inline] #[inline]
pub fn as_mut_ptr(&mut self) -> *mut T { pub fn as_mut_ptr(&mut self) -> *mut T {
// We shadow the slice method of the same name to avoid going through // We shadow the slice method of the same name to avoid going through
@ -3403,6 +3456,36 @@ impl<T: Clone> From<&mut [T]> for Vec<T> {
} }
} }
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array_ref", since = "1.74.0")]
impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> {
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
///
/// # Examples
///
/// ```
/// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]);
/// ```
fn from(s: &[T; N]) -> Vec<T> {
Self::from(s.as_slice())
}
}
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array_ref", since = "1.74.0")]
impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> {
/// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
///
/// # Examples
///
/// ```
/// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
/// ```
fn from(s: &mut [T; N]) -> Vec<T> {
Self::from(s.as_mut_slice())
}
}
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array", since = "1.44.0")] #[stable(feature = "vec_from_array", since = "1.44.0")]
impl<T, const N: usize> From<[T; N]> for Vec<T> { impl<T, const N: usize> From<[T; N]> for Vec<T> {

View File

@ -20,3 +20,7 @@
# `seccomp`'s comment gets understood as a doctest # `seccomp`'s comment gets understood as a doctest
--no-doc-comments --no-doc-comments
# These functions use the `__preserve_most` calling convention, which neither bindgen
# nor Rust currently understand, and which Clang currently declares to be unstable.
--blocklist-function __list_.*_report

View File

@ -18,6 +18,6 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
/* `bindgen` gets confused at certain things. */ /* `bindgen` gets confused at certain things. */
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO; const gfp_t RUST_CONST_HELPER___GFP_ZERO = __GFP_ZERO;

View File

@ -48,6 +48,3 @@ mod bindings_helper {
} }
pub use bindings_raw::*; pub use bindings_raw::*;
pub const GFP_KERNEL: gfp_t = BINDINGS_GFP_KERNEL;
pub const __GFP_ZERO: gfp_t = BINDINGS___GFP_ZERO;

View File

@ -11,7 +11,7 @@
* accidentally exposed. * accidentally exposed.
*/ */
#include <linux/module.h> #include <linux/export.h>
#define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym) #define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym)

View File

@ -21,7 +21,7 @@ unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gf
let mut size = layout.size(); let mut size = layout.size();
if layout.align() > bindings::BINDINGS_ARCH_SLAB_MINALIGN { if layout.align() > bindings::ARCH_SLAB_MINALIGN {
// The alignment requirement exceeds the slab guarantee, thus try to enlarge the size // The alignment requirement exceeds the slab guarantee, thus try to enlarge the size
// to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for // to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for
// more information). // more information).

View File

@ -2,7 +2,7 @@
//! Kernel errors. //! Kernel errors.
//! //!
//! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h) //! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)
use crate::str::CStr; use crate::str::CStr;
@ -335,3 +335,7 @@ where
Err(e) => T::from(e.to_errno() as i16), Err(e) => T::from(e.to_errno() as i16),
} }
} }
/// Error message for calling a default function of a [`#[vtable]`](macros::vtable) trait.
pub const VTABLE_DEFAULT_ERROR: &str =
"This function must not be called, see the #[vtable] documentation.";

View File

@ -2,7 +2,7 @@
//! ioctl() number definitions //! ioctl() number definitions
//! //!
//! C header: [`include/asm-generic/ioctl.h`](../../../../include/asm-generic/ioctl.h) //! C header: [`include/asm-generic/ioctl.h`](srctree/include/asm-generic/ioctl.h)
#![allow(non_snake_case)] #![allow(non_snake_case)]

View File

@ -2,7 +2,7 @@
//! KUnit-based macros for Rust unit tests. //! KUnit-based macros for Rust unit tests.
//! //!
//! C header: [`include/kunit/test.h`](../../../../../include/kunit/test.h) //! C header: [`include/kunit/test.h`](srctree/include/kunit/test.h)
//! //!
//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html> //! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>

View File

@ -2,7 +2,7 @@
//! Printing facilities. //! Printing facilities.
//! //!
//! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h) //! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
//! //!
//! Reference: <https://www.kernel.org/doc/html/latest/core-api/printk-basics.html> //! Reference: <https://www.kernel.org/doc/html/latest/core-api/printk-basics.html>
@ -48,7 +48,7 @@ pub mod format_strings {
/// The format string is always the same for a given level, i.e. for a /// The format string is always the same for a given level, i.e. for a
/// given `prefix`, which are the kernel's `KERN_*` constants. /// given `prefix`, which are the kernel's `KERN_*` constants.
/// ///
/// [`_printk`]: ../../../../include/linux/printk.h /// [`_printk`]: srctree/include/linux/printk.h
const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] { const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] {
// Ensure the `KERN_*` macros are what we expect. // Ensure the `KERN_*` macros are what we expect.
assert!(prefix[0] == b'\x01'); assert!(prefix[0] == b'\x01');
@ -97,7 +97,7 @@ pub mod format_strings {
/// The format string must be one of the ones in [`format_strings`], and /// The format string must be one of the ones in [`format_strings`], and
/// the module name must be null-terminated. /// the module name must be null-terminated.
/// ///
/// [`_printk`]: ../../../../include/linux/_printk.h /// [`_printk`]: srctree/include/linux/_printk.h
#[doc(hidden)] #[doc(hidden)]
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
pub unsafe fn call_printk( pub unsafe fn call_printk(
@ -120,7 +120,7 @@ pub unsafe fn call_printk(
/// ///
/// Public but hidden since it should only be used from public macros. /// Public but hidden since it should only be used from public macros.
/// ///
/// [`_printk`]: ../../../../include/linux/printk.h /// [`_printk`]: srctree/include/linux/printk.h
#[doc(hidden)] #[doc(hidden)]
#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
pub fn call_printk_cont(args: fmt::Arguments<'_>) { pub fn call_printk_cont(args: fmt::Arguments<'_>) {

View File

@ -608,6 +608,12 @@ impl<'a> TryFrom<&'a CStr> for CString {
} }
} }
impl fmt::Debug for CString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
/// A convenience alias for [`core::format_args`]. /// A convenience alias for [`core::format_args`].
#[macro_export] #[macro_export]
macro_rules! fmt { macro_rules! fmt {

View File

@ -50,7 +50,7 @@ macro_rules! new_condvar {
/// fn wait_for_value(e: &Example, v: u32) { /// fn wait_for_value(e: &Example, v: u32) {
/// let mut guard = e.value.lock(); /// let mut guard = e.value.lock();
/// while *guard != v { /// while *guard != v {
/// e.value_changed.wait_uninterruptible(&mut guard); /// e.value_changed.wait(&mut guard);
/// } /// }
/// } /// }
/// ///
@ -69,7 +69,7 @@ macro_rules! new_condvar {
/// } /// }
/// ``` /// ```
/// ///
/// [`struct wait_queue_head`]: ../../../include/linux/wait.h /// [`struct wait_queue_head`]: srctree/include/linux/wait.h
#[pin_data] #[pin_data]
pub struct CondVar { pub struct CondVar {
#[pin] #[pin]
@ -120,26 +120,26 @@ impl CondVar {
unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) }; unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) };
} }
/// Releases the lock and waits for a notification in interruptible mode. /// Releases the lock and waits for a notification in uninterruptible mode.
/// ///
/// Atomically releases the given lock (whose ownership is proven by the guard) and puts the /// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
/// thread to sleep, reacquiring the lock on wake up. It wakes up when notified by /// thread to sleep, reacquiring the lock on wake up. It wakes up when notified by
/// [`CondVar::notify_one`] or [`CondVar::notify_all`], or when the thread receives a signal. /// [`CondVar::notify_one`] or [`CondVar::notify_all`]. Note that it may also wake up
/// It may also wake up spuriously. /// spuriously.
/// pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) {
/// Returns whether there is a signal pending. self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard);
#[must_use = "wait returns if a signal is pending, so the caller must check the return value"]
pub fn wait<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard);
crate::current!().signal_pending()
} }
/// Releases the lock and waits for a notification in uninterruptible mode. /// Releases the lock and waits for a notification in interruptible mode.
/// ///
/// Similar to [`CondVar::wait`], except that the wait is not interruptible. That is, the /// Similar to [`CondVar::wait`], except that the wait is interruptible. That is, the thread may
/// thread won't wake up due to signals. It may, however, wake up supirously. /// wake up due to signals. It may also wake up spuriously.
pub fn wait_uninterruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) { ///
self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard) /// Returns whether there is a signal pending.
#[must_use = "wait_interruptible returns if a signal is pending, so the caller must check the return value"]
pub fn wait_interruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T, B>) -> bool {
self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard);
crate::current!().signal_pending()
} }
/// Calls the kernel function to notify the appropriate number of threads with the given flags. /// Calls the kernel function to notify the appropriate number of threads with the given flags.

View File

@ -84,7 +84,7 @@ macro_rules! new_mutex {
/// } /// }
/// ``` /// ```
/// ///
/// [`struct mutex`]: ../../../../include/linux/mutex.h /// [`struct mutex`]: srctree/include/linux/mutex.h
pub type Mutex<T> = super::Lock<T, MutexBackend>; pub type Mutex<T> = super::Lock<T, MutexBackend>;
/// A kernel `struct mutex` lock backend. /// A kernel `struct mutex` lock backend.

View File

@ -82,7 +82,7 @@ macro_rules! new_spinlock {
/// } /// }
/// ``` /// ```
/// ///
/// [`spinlock_t`]: ../../../../include/linux/spinlock.h /// [`spinlock_t`]: srctree/include/linux/spinlock.h
pub type SpinLock<T> = super::Lock<T, SpinLockBackend>; pub type SpinLock<T> = super::Lock<T, SpinLockBackend>;
/// A kernel `spinlock_t` lock backend. /// A kernel `spinlock_t` lock backend.

View File

@ -2,7 +2,7 @@
//! Tasks (threads and processes). //! Tasks (threads and processes).
//! //!
//! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h). //! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h).
use crate::{bindings, types::Opaque}; use crate::{bindings, types::Opaque};
use core::{marker::PhantomData, ops::Deref, ptr}; use core::{marker::PhantomData, ops::Deref, ptr};

View File

@ -132,7 +132,7 @@
//! } //! }
//! ``` //! ```
//! //!
//! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h) //! C header: [`include/linux/workqueue.h`](srctree/include/linux/workqueue.h)
use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque}; use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque};
use alloc::alloc::AllocError; use alloc::alloc::AllocError;

View File

@ -20,7 +20,7 @@ use proc_macro::TokenStream;
/// The `type` argument should be a type which implements the [`Module`] /// The `type` argument should be a type which implements the [`Module`]
/// trait. Also accepts various forms of kernel metadata. /// trait. Also accepts various forms of kernel metadata.
/// ///
/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) /// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h)
/// ///
/// [`Module`]: ../kernel/trait.Module.html /// [`Module`]: ../kernel/trait.Module.html
/// ///
@ -87,27 +87,49 @@ pub fn module(ts: TokenStream) -> TokenStream {
/// implementation could just return `Error::EINVAL`); Linux typically use C /// implementation could just return `Error::EINVAL`); Linux typically use C
/// `NULL` pointers to represent these functions. /// `NULL` pointers to represent these functions.
/// ///
/// This attribute is intended to close the gap. Traits can be declared and /// This attribute closes that gap. A trait can be annotated with the
/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant /// `#[vtable]` attribute. Implementers of the trait will then also have to
/// will be generated for each method in the trait, indicating if the implementor /// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*`
/// has overridden a method. /// associated constant bool for each method in the trait that is set to true if
/// the implementer has overridden the associated method.
/// ///
/// This attribute is not needed if all methods are required. /// For a trait method to be optional, it must have a default implementation.
/// This is also the case for traits annotated with `#[vtable]`, but in this
/// case the default implementation will never be executed. The reason for this
/// is that the functions will be called through function pointers installed in
/// C side vtables. When an optional method is not implemented on a `#[vtable]`
/// trait, a NULL entry is installed in the vtable. Thus the default
/// implementation is never called. Since these traits are not designed to be
/// used on the Rust side, it should not be possible to call the default
/// implementation. This is done to ensure that we call the vtable methods
/// through the C vtable, and not through the Rust vtable. Therefore, the
/// default implementation should call `kernel::build_error`, which prevents
/// calls to this function at compile time:
///
/// ```compile_fail
/// # use kernel::error::VTABLE_DEFAULT_ERROR;
/// kernel::build_error(VTABLE_DEFAULT_ERROR)
/// ```
///
/// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`].
///
/// This macro should not be used when all functions are required.
/// ///
/// # Examples /// # Examples
/// ///
/// ```ignore /// ```ignore
/// use kernel::error::VTABLE_DEFAULT_ERROR;
/// use kernel::prelude::*; /// use kernel::prelude::*;
/// ///
/// // Declares a `#[vtable]` trait /// // Declares a `#[vtable]` trait
/// #[vtable] /// #[vtable]
/// pub trait Operations: Send + Sync + Sized { /// pub trait Operations: Send + Sync + Sized {
/// fn foo(&self) -> Result<()> { /// fn foo(&self) -> Result<()> {
/// Err(EINVAL) /// kernel::build_error(VTABLE_DEFAULT_ERROR)
/// } /// }
/// ///
/// fn bar(&self) -> Result<()> { /// fn bar(&self) -> Result<()> {
/// Err(EINVAL) /// kernel::build_error(VTABLE_DEFAULT_ERROR)
/// } /// }
/// } /// }
/// ///
@ -125,6 +147,8 @@ pub fn module(ts: TokenStream) -> TokenStream {
/// assert_eq!(<Foo as Operations>::HAS_FOO, true); /// assert_eq!(<Foo as Operations>::HAS_FOO, true);
/// assert_eq!(<Foo as Operations>::HAS_BAR, false); /// assert_eq!(<Foo as Operations>::HAS_BAR, false);
/// ``` /// ```
///
/// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
vtable::vtable(attr, ts) vtable::vtable(attr, ts)
@ -254,8 +278,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
/// single identifier. /// single identifier.
/// ///
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers /// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
/// (literals, lifetimes and documentation strings are not supported). There is a difference in /// literals (lifetimes and documentation strings are not supported). There is a difference in
/// supported modifiers as well. /// supported modifiers as well.
/// ///
/// # Example /// # Example
@ -337,6 +361,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK); /// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
/// ``` /// ```
/// ///
/// # Literals
///
/// Literals can also be concatenated with other identifiers:
///
/// ```ignore
/// macro_rules! create_numbered_fn {
/// ($name:literal, $val:literal) => {
/// kernel::macros::paste! {
/// fn [<some_ $name _fn $val>]() -> u32 { $val }
/// }
/// };
/// }
///
/// create_numbered_fn!("foo", 100);
///
/// assert_eq!(some_foo_fn100(), 100)
/// ```
///
/// [`paste`]: https://docs.rs/paste/ /// [`paste`]: https://docs.rs/paste/
#[proc_macro] #[proc_macro]
pub fn paste(input: TokenStream) -> TokenStream { pub fn paste(input: TokenStream) -> TokenStream {

View File

@ -9,7 +9,15 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
loop { loop {
match tokens.next() { match tokens.next() {
None => break, None => break,
Some(TokenTree::Literal(lit)) => segments.push((lit.to_string(), lit.span())), Some(TokenTree::Literal(lit)) => {
// Allow us to concat string literals by stripping quotes
let mut value = lit.to_string();
if value.starts_with('"') && value.ends_with('"') {
value.remove(0);
value.pop();
}
segments.push((value, lit.span()));
}
Some(TokenTree::Ident(ident)) => { Some(TokenTree::Ident(ident)) => {
let mut value = ident.to_string(); let mut value = ident.to_string();
if value.starts_with("r#") { if value.starts_with("r#") {

View File

@ -275,6 +275,7 @@ rust_common_cmd = \
--extern alloc --extern kernel \ --extern alloc --extern kernel \
--crate-type rlib -L $(objtree)/rust/ \ --crate-type rlib -L $(objtree)/rust/ \
--crate-name $(basename $(notdir $@)) \ --crate-name $(basename $(notdir $@)) \
--sysroot=/dev/null \
--out-dir $(dir $@) --emit=dep-info=$(depfile) --out-dir $(dir $@) --emit=dep-info=$(depfile)
# `--emit=obj`, `--emit=asm` and `--emit=llvm-ir` imply a single codegen unit # `--emit=obj`, `--emit=asm` and `--emit=llvm-ir` imply a single codegen unit

View File

@ -31,7 +31,7 @@ llvm)
fi fi
;; ;;
rustc) rustc)
echo 1.73.0 echo 1.74.1
;; ;;
bindgen) bindgen)
echo 0.65.1 echo 0.65.1