From c3f41b00307f796756ec494b90c9e238800a0ff8 Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Fri, 14 Jul 2023 18:19:33 +0900 Subject: rust: kernel: str: Implement Debug for CString Make it possible to use a `CString` with the `pr_*` macros directly. That is, instead of: pr_debug!("trying to open {:?}\n", &*filename); we can now write: pr_debug!("trying to open {:?}\n", filename); Signed-off-by: Asahi Lina Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Link: https://lore.kernel.org/r/20230714-cstring-debug-v1-1-4e7c3018dd4f@asahilina.net [ Reworded to use Alice's commit message as discussed. ] Signed-off-by: Miguel Ojeda --- rust/kernel/str.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'rust') diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index c41607b2e4fe..7d848b83add4 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -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`]. #[macro_export] macro_rules! fmt { -- cgit v1.2.3 From dc92ac9f6383a5026d6070a79035ebcc28c59d1b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 24 Nov 2023 23:26:17 +0900 Subject: rust: replace with in rust/exports.c is the right header to include for using EXPORT_SYMBOL_GPL. includes much more bloat. Signed-off-by: Masahiro Yamada Reviewed-by: Martin Rodriguez Reboredo Link: https://lore.kernel.org/r/20231124142617.713096-1-masahiroy@kernel.org Signed-off-by: Miguel Ojeda --- rust/exports.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rust') diff --git a/rust/exports.c b/rust/exports.c index 83e2a7070cae..3803c21d1403 100644 --- a/rust/exports.c +++ b/rust/exports.c @@ -11,7 +11,7 @@ * accidentally exposed. */ -#include +#include #define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym) -- cgit v1.2.3 From bad098d76835c1379e1cf6afc935f8a7e050f83c Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 31 Oct 2023 20:19:44 +0000 Subject: rust: Ignore preserve-most functions Neither bindgen nor Rust know about the preserve-most calling convention, and Clang describes it as unstable. Since we aren't using functions with this calling convention from Rust, blocklist them. These functions are only added to the build when list hardening is enabled, which is likely why others didn't notice this yet. Signed-off-by: Matthew Maurer Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231031201945.1412345-1-mmaurer@google.com [ Used Markdown for consistency with the other comments in the file. ] Signed-off-by: Miguel Ojeda --- rust/bindgen_parameters | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'rust') diff --git a/rust/bindgen_parameters b/rust/bindgen_parameters index 552d9a85925b..a721d466bee4 100644 --- a/rust/bindgen_parameters +++ b/rust/bindgen_parameters @@ -20,3 +20,7 @@ # `seccomp`'s comment gets understood as a doctest --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 -- cgit v1.2.3 From 743766565dc0bdeedf7db419500031c7bdc84033 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 4 Nov 2023 14:56:56 +0000 Subject: rust: bindings: rename const binding using sed Currently, for `const`s that bindgen doesn't recognise, we define a helper constant with const BINDINGS_ = ; in `bindings_helper.h` and then we put pub const : = BINDINGS_; in `bindings/lib.rs`. This is fine since we currently only have 3 constants that are defined this way, but is going to be more annoying when more constants are added since every new constant needs to be defined in two places. This patch changes the way we define constant helpers to const RUST_CONST_HELPER_ = ; and then use `sed` to postprocess Rust code generated by bindgen to remove the distinct prefix, so users of the `bindings` crate can refer to the name directly. Reviewed-by: Benno Lossin Reviewed-by: Andreas Hindborg Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Gary Guo Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20231104145700.2495176-1-gary@garyguo.net [ Reworded for typos. ] Signed-off-by: Miguel Ojeda --- rust/Makefile | 2 ++ rust/bindings/bindings_helper.h | 6 +++--- rust/bindings/lib.rs | 3 --- rust/kernel/allocator.rs | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'rust') diff --git a/rust/Makefile b/rust/Makefile index 543b37f6c77f..2912c5e075cb 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -337,6 +337,8 @@ quiet_cmd_bindgen = BINDGEN $@ $(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \ $(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 \ $(src)/bindgen_parameters FORCE $(call if_changed_dep,bindgen) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 85f013ed4ca4..b5714fb69fe3 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -15,6 +15,6 @@ #include /* `bindgen` gets confused at certain things. */ -const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; -const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; -const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO; +const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; +const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL; +const gfp_t RUST_CONST_HELPER___GFP_ZERO = __GFP_ZERO; diff --git a/rust/bindings/lib.rs b/rust/bindings/lib.rs index 9bcbea04dac3..40ddaee50d8b 100644 --- a/rust/bindings/lib.rs +++ b/rust/bindings/lib.rs @@ -48,6 +48,3 @@ mod bindings_helper { } pub use bindings_raw::*; - -pub const GFP_KERNEL: gfp_t = BINDINGS_GFP_KERNEL; -pub const __GFP_ZERO: gfp_t = BINDINGS___GFP_ZERO; diff --git a/rust/kernel/allocator.rs b/rust/kernel/allocator.rs index a8f3d5be1af1..4b057e837358 100644 --- a/rust/kernel/allocator.rs +++ b/rust/kernel/allocator.rs @@ -21,7 +21,7 @@ unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gf 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 // to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for // more information). -- cgit v1.2.3 From 2dc318ea9681c14c37bad2715097df4380a3c547 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 17 Nov 2023 20:39:59 -0500 Subject: rust: macros: update 'paste!' macro to accept string literals Enable combining identifiers with literals in the 'paste!' macro. This allows combining user-specified strings with affixes to create namespaced identifiers. This sample code: macro_rules! m { ($name:lit) => { paste!(struct [<_some_ $name _struct_>] {}) } } m!("foo_bar"); Would previously cause a compilation error. It will now generate: struct _some_foo_bar_struct_ {} Signed-off-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Vincenzo Palazzo Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Gary Guo Link: https://lore.kernel.org/r/20231118013959.37384-1-tmgross@umich.edu [ Added `:` before example block. ] Signed-off-by: Miguel Ojeda --- rust/macros/lib.rs | 22 ++++++++++++++++++++-- rust/macros/paste.rs | 10 +++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) (limited to 'rust') diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index c42105c2ff96..125f5ea74a16 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -254,8 +254,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a /// single identifier. /// -/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers -/// (literals, lifetimes and documentation strings are not supported). There is a difference in +/// 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 /// supported modifiers as well. /// /// # Example @@ -337,6 +337,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { /// 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 []() -> u32 { $val } +/// } +/// }; +/// } +/// +/// create_numbered_fn!("foo", 100); +/// +/// assert_eq!(some_foo_fn100(), 100) +/// ``` +/// /// [`paste`]: https://docs.rs/paste/ #[proc_macro] pub fn paste(input: TokenStream) -> TokenStream { diff --git a/rust/macros/paste.rs b/rust/macros/paste.rs index 385a78434224..f40d42b35b58 100644 --- a/rust/macros/paste.rs +++ b/rust/macros/paste.rs @@ -9,7 +9,15 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree { loop { match tokens.next() { 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)) => { let mut value = ident.to_string(); if value.starts_with("r#") { -- cgit v1.2.3 From 88c2e1169f5f0c2ccdd0a001e4447a1b0da2b661 Mon Sep 17 00:00:00 2001 From: Benno Lossin Date: Thu, 26 Oct 2023 20:19:33 +0000 Subject: rust: macros: improve `#[vtable]` documentation Traits marked with `#[vtable]` need to provide default implementations for optional functions. The C side represents these with `NULL` in the vtable, so the default functions are never actually called. We do not want to replicate the default behavior from C in Rust, because that is not maintainable. Therefore we should use `build_error` in those default implementations. The error message for that is provided at `kernel::error::VTABLE_DEFAULT_ERROR`. Signed-off-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Andreas Hindborg Reviewed-by: Alice Ryhl Reviewed-by: Finn Behrens Link: https://lore.kernel.org/r/20231026201855.1497680-1-benno.lossin@proton.me [ Wrapped paragraph to 80 as requested and capitalized sentence. ] Signed-off-by: Miguel Ojeda --- rust/kernel/error.rs | 4 ++++ rust/macros/lib.rs | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'rust') diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 032b64543953..376280b6a745 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -335,3 +335,7 @@ where 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."; diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 125f5ea74a16..d18a3e7c9af4 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -87,27 +87,49 @@ pub fn module(ts: TokenStream) -> TokenStream { /// implementation could just return `Error::EINVAL`); Linux typically use C /// `NULL` pointers to represent these functions. /// -/// This attribute is intended to close the gap. Traits can be declared and -/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant -/// will be generated for each method in the trait, indicating if the implementor -/// has overridden a method. +/// This attribute closes that gap. A trait can be annotated with the +/// `#[vtable]` attribute. Implementers of the trait will then also have to +/// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*` +/// associated constant bool for each method in the trait that is set to true if +/// the implementer has overridden the associated method. +/// +/// 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 attribute is not needed if all methods are required. +/// This macro should not be used when all functions are required. /// /// # Examples /// /// ```ignore +/// use kernel::error::VTABLE_DEFAULT_ERROR; /// use kernel::prelude::*; /// /// // Declares a `#[vtable]` trait /// #[vtable] /// pub trait Operations: Send + Sync + Sized { /// fn foo(&self) -> Result<()> { -/// Err(EINVAL) +/// kernel::build_error(VTABLE_DEFAULT_ERROR) /// } /// /// fn bar(&self) -> Result<()> { -/// Err(EINVAL) +/// kernel::build_error(VTABLE_DEFAULT_ERROR) /// } /// } /// @@ -125,6 +147,8 @@ pub fn module(ts: TokenStream) -> TokenStream { /// assert_eq!(::HAS_FOO, true); /// assert_eq!(::HAS_BAR, false); /// ``` +/// +/// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html #[proc_macro_attribute] pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { vtable::vtable(attr, ts) -- cgit v1.2.3 From 71479eee9da8ddb53f3ddb91bc8591d90fb8b142 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 31 Oct 2023 20:10:14 +0000 Subject: rust: Suppress searching builtin sysroot By default, if Rust is passed `--target=foo` rather than a target.json file, it will infer a default sysroot if that component is installed. As the proposed aarch64 support [1] uses `aarch64-unknown-none` rather than a target.json file, this is needed [2] to prevent rustc from being confused between the custom kernel sysroot and the pre-installed one. [ Miguel: Applied Boqun's extra case (for `rusttest`) and reworded to add links to the arm64 patch series discussion. In addition, fixed the `rustdoc` target too (which requires a conditional since `cmd_rustdoc` is also used for host crates like `macros`). ] Signed-off-by: Matthew Maurer Tested-by: Boqun Feng Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/rust-for-linux/20231020155056.3495121-1-Jamie.Cunliffe@arm.com/ [1] Link: https://lore.kernel.org/rust-for-linux/CAGSQo01pOixiPXkW867h4vPUaAjtKtHGKhkV-rpifJvKxAf4Ww@mail.gmail.com/ [2] Link: https://lore.kernel.org/r/20231031201752.1189213-1-mmaurer@google.com Signed-off-by: Miguel Ojeda --- rust/Makefile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'rust') diff --git a/rust/Makefile b/rust/Makefile index 2912c5e075cb..5a3e3140e234 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -78,6 +78,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< $(rustc_target_flags) -L$(objtree)/$(obj) \ --output $(rustdoc_output) \ --crate-name $(subst rustdoc-,,$@) \ + $(if $(rustdoc_host),,--sysroot=/dev/null) \ @$(objtree)/include/generated/rustc_cfg $< # The `html_logo_url` and `html_favicon_url` forms of the `doc` attribute @@ -178,6 +179,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $< --extern build_error --extern macros \ --extern bindings --extern uapi \ --no-run --crate-name kernel -Zunstable-options \ + --sysroot=/dev/null \ --test-builder $(objtree)/scripts/rustdoc_test_builder \ $< $(rustdoc_test_kernel_quiet); \ $(objtree)/scripts/rustdoc_test_gen @@ -404,6 +406,7 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \ --crate-type rlib -L$(objtree)/$(obj) \ --crate-name $(patsubst %.o,%,$(notdir $@)) $< \ + --sysroot=/dev/null \ $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) rust-analyzer: -- cgit v1.2.3 From 80fe9e51510b23472ad0f97175556490549ed714 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 14 Dec 2023 10:29:58 +0100 Subject: rust: upgrade to Rust 1.74.1 This is the next upgrade to the Rust toolchain, from 1.73.0 to 1.74.1 (i.e. the latest) [1]. See the upgrade policy [2] and the comments on the first upgrade in commit 3ed03f4da06e ("rust: upgrade to Rust 1.68.2"). # Unstable features No unstable features (that we use) were stabilized. Therefore, the only unstable features allowed to be used outside the `kernel` crate are still `new_uninit,offset_of`, though other code to be upstreamed may increase the list (e.g. `offset_of` was added recently). Please see [3] for details. # Other improvements Rust 1.74.0 allows to use `#[repr(Rust)]` explicitly [4], which can be useful to be explicit about particular cases that would normally use e.g. the C representation, such as silencing lints like the upcoming additions we requested [5] to the `no_mangle_with_rust_abi` Clippy lint (which in turn triggered the `#[repr(Rust)]` addition). Rust 1.74.0 includes a fix for one of the false negative cases we reported in Clippy's `disallowed_macros` lint [6] that we would like to use in the future. Rust 1.74.1 fixes an ICE that the Apple AGX GPU driver was hitting [7]. # Required changes For this upgrade, no changes were required (i.e. on our side). # `alloc` upgrade and reviewing The vast majority of changes are due to our `alloc` fork being upgraded at once. There are two kinds of changes to be aware of: the ones coming from upstream, which we should follow as closely as possible, and the updates needed in our added fallible APIs to keep them matching the newer infallible APIs coming from upstream. Instead of taking a look at the diff of this patch, an alternative approach is reviewing a diff of the changes between upstream `alloc` and the kernel's. This allows to easily inspect the kernel additions only, especially to check if the fallible methods we already have still match the infallible ones in the new version coming from upstream. Another approach is reviewing the changes introduced in the additions in the kernel fork between the two versions. This is useful to spot potentially unintended changes to our additions. To apply these approaches, one may follow steps similar to the following to generate a pair of patches that show the differences between upstream Rust and the kernel (for the subset of `alloc` we use) before and after applying this patch: # Get the difference with respect to the old version. git -C rust checkout $(linux/scripts/min-tool-version.sh rustc) git -C linux ls-tree -r --name-only HEAD -- rust/alloc | cut -d/ -f3- | grep -Fv README.md | xargs -IPATH cp rust/library/alloc/src/PATH linux/rust/alloc/PATH git -C linux diff --patch-with-stat --summary -R > old.patch git -C linux restore rust/alloc # Apply this patch. git -C linux am rust-upgrade.patch # Get the difference with respect to the new version. git -C rust checkout $(linux/scripts/min-tool-version.sh rustc) git -C linux ls-tree -r --name-only HEAD -- rust/alloc | cut -d/ -f3- | grep -Fv README.md | xargs -IPATH cp rust/library/alloc/src/PATH linux/rust/alloc/PATH git -C linux diff --patch-with-stat --summary -R > new.patch git -C linux restore rust/alloc Now one may check the `new.patch` to take a look at the additions (first approach) or at the difference between those two patches (second approach). For the latter, a side-by-side tool is recommended. Link: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1741-2023-12-07 [1] Link: https://rust-for-linux.com/rust-version-policy [2] Link: https://github.com/Rust-for-Linux/linux/issues/2 [3] Link: https://github.com/rust-lang/rust/pull/114201 [4] Link: https://github.com/rust-lang/rust-clippy/issues/11219 [5] Link: https://github.com/rust-lang/rust-clippy/issues/11431 [6] Link: https://github.com/rust-lang/rust/issues/117976#issuecomment-1822225691 [7] Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Tested-by: David Gow Link: https://lore.kernel.org/r/20231214092958.377061-1-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- rust/alloc/alloc.rs | 32 +++++++++++++------ rust/alloc/lib.rs | 6 ++-- rust/alloc/slice.rs | 2 +- rust/alloc/vec/mod.rs | 87 +++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 112 insertions(+), 15 deletions(-) (limited to 'rust') diff --git a/rust/alloc/alloc.rs b/rust/alloc/alloc.rs index 8cb4a31cf6e5..150e13750ff7 100644 --- a/rust/alloc/alloc.rs +++ b/rust/alloc/alloc.rs @@ -345,18 +345,31 @@ extern "Rust" { 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, -/// 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 -/// and abort the process. -/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`]. +/// This function is guaranteed to diverge (not return normally with a value), but depending on +/// global configuration, it may either panic (resulting in unwinding or aborting as per +/// 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 /// [`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")] #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] #[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 } { panic!("memory allocation of {size} bytes failed") } else { - core::panicking::panic_nounwind_fmt(format_args!( - "memory allocation of {size} bytes failed" - )) + core::panicking::panic_nounwind_fmt( + format_args!("memory allocation of {size} bytes failed"), + /* force_no_backtrace */ false, + ) } } } diff --git a/rust/alloc/lib.rs b/rust/alloc/lib.rs index 73b9ffd845d9..9c7ea73da108 100644 --- a/rust/alloc/lib.rs +++ b/rust/alloc/lib.rs @@ -90,8 +90,8 @@ #![warn(missing_docs)] #![allow(explicit_outlives_requirements)] #![warn(multiple_supertrait_upcastable)] -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] +#![allow(internal_features)] +#![allow(rustdoc::redundant_explicit_links)] // // Library features: // tidy-alphabetical-start @@ -122,6 +122,7 @@ #![feature(const_waker)] #![feature(core_intrinsics)] #![feature(core_panic)] +#![feature(deprecated_suggestion)] #![feature(dispatch_from_dyn)] #![feature(error_generic_member_access)] #![feature(error_in_core)] @@ -145,7 +146,6 @@ #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] #![feature(receiver_trait)] -#![feature(saturating_int_impl)] #![feature(set_ptr_value)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] diff --git a/rust/alloc/slice.rs b/rust/alloc/slice.rs index 6ac463bd3edc..1181836da5f4 100644 --- a/rust/alloc/slice.rs +++ b/rust/alloc/slice.rs @@ -594,7 +594,7 @@ impl [T] { /// ``` #[rustc_allow_incoherent_impl] #[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(&self, sep: Separator) -> >::Output where Self: Join, diff --git a/rust/alloc/vec/mod.rs b/rust/alloc/vec/mod.rs index 209a88cfe598..41ca71805ef0 100644 --- a/rust/alloc/vec/mod.rs +++ b/rust/alloc/vec/mod.rs @@ -1228,8 +1228,8 @@ impl Vec { /// Shortens the vector, keeping the first `len` elements and dropping /// the rest. /// - /// If `len` is greater than the vector's current length, this has no - /// effect. + /// If `len` is greater or equal to the vector's current length, this has + /// no effect. /// /// The [`drain`] method can emulate `truncate`, but causes the excess /// elements to be returned instead of dropped. @@ -1336,6 +1336,15 @@ impl Vec { /// 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`]. /// + /// 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 /// /// ``` @@ -1349,8 +1358,25 @@ impl Vec { /// } /// ``` /// + /// 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_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[inline] pub fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through @@ -1366,6 +1392,15 @@ impl Vec { /// Modifying the vector may cause its buffer to be reallocated, /// 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 /// /// ``` @@ -1383,7 +1418,25 @@ impl Vec { /// } /// 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")] + #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)] #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through @@ -3403,6 +3456,36 @@ impl From<&mut [T]> for Vec { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "1.74.0")] +impl From<&[T; N]> for Vec { + /// Allocate a `Vec` 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 { + Self::from(s.as_slice()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "1.74.0")] +impl From<&mut [T; N]> for Vec { + /// Allocate a `Vec` 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 { + Self::from(s.as_mut_slice()) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_from_array", since = "1.44.0")] impl From<[T; N]> for Vec { -- cgit v1.2.3 From 0a7f5ba73e57eaf7f2e5589d26bbe9bf6754c542 Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Thu, 14 Dec 2023 12:04:21 -0800 Subject: rust: sync: Makes `CondVar::wait()` an uninterruptible wait Currently, `CondVar::wait()` is an interruptible wait, and this is different than `wait_event()` in include/linux/wait.h (which is an uninterruptible wait). To avoid confusion between different APIs on the interruptible/uninterruptible, make `CondVar::wait()` an uninterruptible wait same as `wait_event()`, also rename the old `wait()` to `CondVar::wait_interruptible()`. Spotted-by: Tiago Lam Signed-off-by: Boqun Feng Reviewed-by: Benno Lossin Reviewed-by: Alice Ryhl Reviewed-by: Tiago Lam Link: https://lore.kernel.org/r/20231214200421.690629-1-boqun.feng@gmail.com Signed-off-by: Miguel Ojeda --- rust/kernel/sync/condvar.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'rust') diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index b679b6f6dbeb..8630faa29b78 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -50,7 +50,7 @@ macro_rules! new_condvar { /// fn wait_for_value(e: &Example, v: u32) { /// let mut guard = e.value.lock(); /// while *guard != v { -/// e.value_changed.wait_uninterruptible(&mut guard); +/// e.value_changed.wait(&mut guard); /// } /// } /// @@ -120,28 +120,28 @@ impl CondVar { 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 /// 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. - /// It may also wake up spuriously. + /// [`CondVar::notify_one`] or [`CondVar::notify_all`]. Note that it may also wake up + /// spuriously. + pub fn wait(&self, guard: &mut Guard<'_, T, B>) { + self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard); + } + + /// Releases the lock and waits for a notification in interruptible mode. + /// + /// Similar to [`CondVar::wait`], except that the wait is interruptible. That is, the thread may + /// wake up due to signals. It may also wake up spuriously. /// /// Returns whether there is a signal pending. - #[must_use = "wait returns if a signal is pending, so the caller must check the return value"] - pub fn wait(&self, guard: &mut Guard<'_, T, B>) -> bool { + #[must_use = "wait_interruptible returns if a signal is pending, so the caller must check the return value"] + pub fn wait_interruptible(&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. - /// - /// Similar to [`CondVar::wait`], except that the wait is not interruptible. That is, the - /// thread won't wake up due to signals. It may, however, wake up supirously. - pub fn wait_uninterruptible(&self, guard: &mut Guard<'_, T, B>) { - self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard) - } - /// Calls the kernel function to notify the appropriate number of threads with the given flags. fn notify(&self, count: i32, flags: u32) { // SAFETY: `wait_list` points to valid memory. -- cgit v1.2.3 From bc2e7d5c298a86f2aa759cabe46f66f862fca3b3 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 16 Dec 2023 00:54:28 +0100 Subject: rust: support `srctree`-relative links Some of our links use relative paths in order to point to files in the source tree, e.g.: //! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h) /// [`struct mutex`]: ../../../../include/linux/mutex.h These are problematic because they are hard to maintain and do not support `O=` builds. Instead, provide support for `srctree`-relative links, e.g.: //! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h) /// [`struct mutex`]: srctree/include/linux/mutex.h The links are fixed after `rustdoc` generation to be based on the absolute path to the source tree. Essentially, this is the automatic version of Tomonori's fix [1], suggested by Gary [2]. Suggested-by: Gary Guo Reported-by: FUJITA Tomonori Closes: https://lore.kernel.org/r/20231026.204058.2167744626131849993.fujita.tomonori@gmail.com [1] Fixes: 48fadf440075 ("docs: Move rustdoc output, cross-reference it") Link: https://lore.kernel.org/rust-for-linux/20231026154525.6d14b495@eugeo/ [2] Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20231215235428.243211-1-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- rust/Makefile | 3 ++- rust/kernel/error.rs | 2 +- rust/kernel/ioctl.rs | 2 +- rust/kernel/kunit.rs | 2 +- rust/kernel/print.rs | 8 ++++---- rust/kernel/sync/condvar.rs | 2 +- rust/kernel/sync/lock/mutex.rs | 2 +- rust/kernel/sync/lock/spinlock.rs | 2 +- rust/kernel/task.rs | 2 +- rust/kernel/workqueue.rs | 2 +- rust/macros/lib.rs | 2 +- 11 files changed, 15 insertions(+), 14 deletions(-) (limited to 'rust') diff --git a/rust/Makefile b/rust/Makefile index 5a3e3140e234..9d2a16cc91cb 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -99,7 +99,8 @@ rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ $(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:favicon-[0-9a-f]+\.svg:logo.svg:g' \ - -e 's:::g' + -e 's:::g' \ + -e 's:::g' $(Q)for f in $(rustdoc_output)/static.files/rustdoc-*.css; do \ echo ".logo-container > img { object-fit: contain; }" >> $$f; done diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 376280b6a745..4f0c1edd63b7 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -2,7 +2,7 @@ //! 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; diff --git a/rust/kernel/ioctl.rs b/rust/kernel/ioctl.rs index c49e1a8d3fd0..f1d42ab69972 100644 --- a/rust/kernel/ioctl.rs +++ b/rust/kernel/ioctl.rs @@ -2,7 +2,7 @@ //! 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)] diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs index 722655b2d62d..0ba77276ae7e 100644 --- a/rust/kernel/kunit.rs +++ b/rust/kernel/kunit.rs @@ -2,7 +2,7 @@ //! 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: diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs index f48926e3e9fe..9b13aca832c2 100644 --- a/rust/kernel/print.rs +++ b/rust/kernel/print.rs @@ -2,7 +2,7 @@ //! Printing facilities. //! -//! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h) +//! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h) //! //! Reference: @@ -48,7 +48,7 @@ pub mod format_strings { /// The format string is always the same for a given level, i.e. for a /// 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] { // Ensure the `KERN_*` macros are what we expect. 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 module name must be null-terminated. /// -/// [`_printk`]: ../../../../include/linux/_printk.h +/// [`_printk`]: srctree/include/linux/_printk.h #[doc(hidden)] #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] 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. /// -/// [`_printk`]: ../../../../include/linux/printk.h +/// [`_printk`]: srctree/include/linux/printk.h #[doc(hidden)] #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] pub fn call_printk_cont(args: fmt::Arguments<'_>) { diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index 8630faa29b78..f65e19d5a37c 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -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] pub struct CondVar { #[pin] diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs index 09276fedc091..8c524a3ec45a 100644 --- a/rust/kernel/sync/lock/mutex.rs +++ b/rust/kernel/sync/lock/mutex.rs @@ -84,7 +84,7 @@ macro_rules! new_mutex { /// } /// ``` /// -/// [`struct mutex`]: ../../../../include/linux/mutex.h +/// [`struct mutex`]: srctree/include/linux/mutex.h pub type Mutex = super::Lock; /// A kernel `struct mutex` lock backend. diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs index 91eb2c9e9123..068535ce1b29 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -82,7 +82,7 @@ macro_rules! new_spinlock { /// } /// ``` /// -/// [`spinlock_t`]: ../../../../include/linux/spinlock.h +/// [`spinlock_t`]: srctree/include/linux/spinlock.h pub type SpinLock = super::Lock; /// A kernel `spinlock_t` lock backend. diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index b2299bc7ac1f..9451932d5d86 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -2,7 +2,7 @@ //! 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 core::{marker::PhantomData, ops::Deref, ptr}; diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index b67fb1ba168e..498397877376 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -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 alloc::alloc::AllocError; diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index d18a3e7c9af4..f489f3157383 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -20,7 +20,7 @@ use proc_macro::TokenStream; /// The `type` argument should be a type which implements the [`Module`] /// 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 /// -- cgit v1.2.3