History

Merge tag 'rust-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux

Pull rust updates from Miguel Ojeda: "Toolchain and infrastructure: - Derive 'Zeroable' for all structs and unions generated by 'bindgen' where possible and corresponding cleanups. To do so, add the 'pin-init' crate as a dependency to 'bindings' and 'uapi'. It also includes its first use in the 'cpufreq' module, with more to come in the next cycle. - Add warning to the 'rustdoc' target to detect broken 'srctree/' links and fix existing cases. - Remove support for unused (since v6.16) host '#[test]'s, simplifying the 'rusttest' target. Tests should generally run within KUnit. 'kernel' crate: - Add 'ptr' module with a new 'Alignment' type, which is always a power of two and is used to validate that a given value is a valid alignment and to perform masking and alignment operations: // Checked at build time. assert_eq!(Alignment::new::<16>().as_usize(), 16); // Checked at runtime. assert_eq!(Alignment::new_checked(15), None); assert_eq!(Alignment::of::<u8>().log2(), 0); assert_eq!(0x25u8.align_down(Alignment::new::<0x10>()), 0x20); assert_eq!(0x5u8.align_up(Alignment::new::<0x10>()), Some(0x10)); assert_eq!(u8::MAX.align_up(Alignment::new::<0x10>()), None); It also includes its first use in Nova. - Add 'core::mem::{align,size}_of{,_val}' to the prelude, matching Rust 1.80.0. - Keep going with the steps on our migration to the standard library 'core::ffi::CStr' type (use 'kernel::{fmt, prelude::fmt!}' and use upstream method names). - 'error' module: improve 'Error::from_errno' and 'to_result' documentation, including examples/tests. - 'sync' module: extend 'aref' submodule documentation now that it exists, and more updates to complete the ongoing move of 'ARef' and 'AlwaysRefCounted' to 'sync::aref'. - 'list' module: add an example/test for 'ListLinksSelfPtr' usage. - 'alloc' module: - Implement 'Box::pin_slice()', which constructs a pinned slice of elements. - Provide information about the minimum alignment guarantees of 'Kmalloc', 'Vmalloc' and 'KVmalloc'. - Take minimum alignment guarantees of allocators for 'ForeignOwnable' into account. - Remove the 'allocator_test' (including 'Cmalloc'). - Add doctest for 'Vec::as_slice()'. - Constify various methods. - 'time' module: - Add methods on 'HrTimer' that can only be called with exclusive access to an unarmed timer, or from timer callback context. - Add arithmetic operations to 'Instant' and 'Delta'. - Add a few convenience and access methods to 'HrTimer' and 'Instant'. 'macros' crate: - Reduce collections in 'quote!' macro. And a few other cleanups and improvements" * tag 'rust-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: (58 commits) gpu: nova-core: use Alignment for alignment-related operations rust: add `Alignment` type rust: macros: reduce collections in `quote!` macro rust: acpi: use `core::ffi::CStr` method names rust: of: use `core::ffi::CStr` method names rust: net: use `core::ffi::CStr` method names rust: miscdevice: use `core::ffi::CStr` method names rust: kunit: use `core::ffi::CStr` method names rust: firmware: use `core::ffi::CStr` method names rust: drm: use `core::ffi::CStr` method names rust: cpufreq: use `core::ffi::CStr` method names rust: configfs: use `core::ffi::CStr` method names rust: auxiliary: use `core::ffi::CStr` method names drm/panic: use `core::ffi::CStr` method names rust: device: use `kernel::{fmt,prelude::fmt!}` rust: sync: use `kernel::{fmt,prelude::fmt!}` rust: seq_file: use `kernel::{fmt,prelude::fmt!}` rust: kunit: use `kernel::{fmt,prelude::fmt!}` rust: file: use `kernel::{fmt,prelude::fmt!}` rust: device: use `kernel::{fmt,prelude::fmt!}` ...

Linus Torvalds committed 1 year ago

Commit f4e0ff72 parents ae28ed4 f3f6b3661 files · +1054 −315Browse files

Unified · Split

61 files
  1. Documentation/gpu/nova/core/todo.rst +0 −1
  2. drivers/block/rnull.rs +1 −1
  3. drivers/gpu/drm/drm_panic_qr.rs +1 −1
  4. drivers/gpu/nova-core/fb.rs +3 −3
  5. drivers/gpu/nova-core/gpu.rs +1 −2
  6. drivers/gpu/nova-core/regs/macros.rs +3 −3
  7. drivers/gpu/nova-core/vbios.rs +2 −2
  8. rust/Makefile +15 −14
  9. rust/bindgen_parameters +5 −0
  10. rust/bindings/bindings_helper.h +1 −0
  11. rust/bindings/lib.rs +8 −0
  12. rust/kernel/acpi.rs +2 −5
  13. rust/kernel/alloc.rs +8 −7
  14. rust/kernel/alloc/allocator.rs +8 −0
  15. rust/kernel/alloc/allocator_test.rs +0 −124
  16. rust/kernel/alloc/kbox.rs +87 −5
  17. rust/kernel/alloc/kvec.rs +17 −7
  18. rust/kernel/alloc/kvec/errors.rs +1 −1
  19. rust/kernel/alloc/layout.rs +1 −1
  20. rust/kernel/auxiliary.rs +2 −2
  21. rust/kernel/block/mq.rs +1 −1
  22. rust/kernel/block/mq/gen_disk.rs +2 −2
  23. rust/kernel/block/mq/raw_writer.rs +1 −2
  24. rust/kernel/configfs.rs +2 −2
  25. rust/kernel/cpu.rs +1 −0
  26. rust/kernel/cpufreq.rs +2 −4
  27. rust/kernel/device.rs +3 −3
  28. rust/kernel/device/property.rs +12 −11
  29. rust/kernel/dma.rs +1 −1
  30. rust/kernel/drm/device.rs +3 −3
  31. rust/kernel/drm/driver.rs +1 −1
  32. rust/kernel/drm/file.rs +1 −1
  33. rust/kernel/drm/gem/mod.rs +1 −1
  34. rust/kernel/drm/ioctl.rs +1 −1
  35. rust/kernel/error.rs +59 −7
  36. rust/kernel/firmware.rs +1 −1
  37. rust/kernel/fs/file.rs +3 −2
  38. rust/kernel/kunit.rs +7 −7
  39. rust/kernel/lib.rs +4 −1
  40. rust/kernel/list.rs +120 −0
  41. rust/kernel/miscdevice.rs +1 −1
  42. rust/kernel/net/phy.rs +1 −1
  43. rust/kernel/of.rs +1 −1
  44. rust/kernel/prelude.rs +4 −1
  45. rust/kernel/ptr.rs +228 −0
  46. rust/kernel/seq_file.rs +3 −3
  47. rust/kernel/sync/arc.rs +4 −4
  48. rust/kernel/sync/aref.rs +16 −1
  49. rust/kernel/task.rs +4 −3
  50. rust/kernel/time.rs +162 −1
  51. rust/kernel/time/hrtimer.rs +149 −3
  52. rust/kernel/time/hrtimer/arc.rs +8 −1
  53. rust/kernel/time/hrtimer/pin.rs +8 −1
  54. rust/kernel/time/hrtimer/pin_mut.rs +9 −3
  55. rust/kernel/time/hrtimer/tbox.rs +8 −1
  56. rust/macros/quote.rs +49 −55
  57. rust/uapi/lib.rs +2 −0
  58. samples/rust/rust_configfs.rs +1 −1
  59. samples/rust/rust_dma.rs +1 −1
  60. scripts/generate_rust_analyzer.py +2 −2
  61. scripts/rustdoc_test_gen.rs +1 −1
Documentation/gpu/nova/core/todo.rst+0−1
@@ -147,7 +147,6 @@ Numerical operations [NUMM] · 146 unmodified lines
147Nova uses integer operations that are not part of the standard library (or not147Nova uses integer operations that are not part of the standard library (or not
148implemented in an optimized way for the kernel). These include:148implemented in an optimized way for the kernel). These include:
149 149
150- Aligning up and down to a power of two,
151- The "Find Last Set Bit" (`fls` function of the C part of the kernel)150- The "Find Last Set Bit" (`fls` function of the C part of the kernel)
152 operation.151 operation.
153 152
drivers/block/rnull.rs+1−1
@@ -51,7 +51,7 @@ impl kernel::InPlaceModule for NullBlkModule { · 50 unmodified lines
51 .logical_block_size(4096)?51 .logical_block_size(4096)?
52 .physical_block_size(4096)?52 .physical_block_size(4096)?
53 .rotational(false)53 .rotational(false)
54 .build(format_args!("rnullb{}", 0), tagset)54 .build(fmt!("rnullb{}", 0), tagset)
55 })();55 })();
56 56
57 try_pin_init!(Self {57 try_pin_init!(Self {
drivers/gpu/drm/drm_panic_qr.rs+1−1
@@ -968,7 +968,7 @@ pub unsafe extern "C" fn drm_panic_qr_generate( · 967 unmodified lines
968 // nul-terminated string.968 // nul-terminated string.
969 let url_cstr: &CStr = unsafe { CStr::from_char_ptr(url) };969 let url_cstr: &CStr = unsafe { CStr::from_char_ptr(url) };
970 let segments = &[970 let segments = &[
971 &Segment::Binary(url_cstr.as_bytes()),971 &Segment::Binary(url_cstr.to_bytes()),
972 &Segment::Numeric(&data_slice[0..data_len]),972 &Segment::Numeric(&data_slice[0..data_len]),
973 ];973 ];
974 match EncodedMsg::new(segments, tmp_slice) {974 match EncodedMsg::new(segments, tmp_slice) {
drivers/gpu/nova-core/fb.rs+3−3
@@ -3,6 +3,7 @@ · 2 unmodified lines
3use core::ops::Range;3use core::ops::Range;
4 4
5use kernel::prelude::*;5use kernel::prelude::*;
6use kernel::ptr::{Alignable, Alignment};
6use kernel::sizes::*;7use kernel::sizes::*;
7use kernel::types::ARef;8use kernel::types::ARef;
8use kernel::{dev_warn, device};9use kernel::{dev_warn, device};
@@ -130,10 +131,9 @@ impl FbLayout { · 121 unmodified lines
130 };131 };
131 132
132 let frts = {133 let frts = {
133 const FRTS_DOWN_ALIGN: u64 = SZ_128K as u64;134 const FRTS_DOWN_ALIGN: Alignment = Alignment::new::<SZ_128K>();
134 const FRTS_SIZE: u64 = SZ_1M as u64;135 const FRTS_SIZE: u64 = SZ_1M as u64;
135 // TODO[NUMM]: replace with `align_down` once it lands.136 let frts_base = vga_workspace.start.align_down(FRTS_DOWN_ALIGN) - FRTS_SIZE;
136 let frts_base = (vga_workspace.start & !(FRTS_DOWN_ALIGN - 1)) - FRTS_SIZE;
137 137
138 frts_base..frts_base + FRTS_SIZE138 frts_base..frts_base + FRTS_SIZE
139 };139 };
drivers/gpu/nova-core/gpu.rs+1−2
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2 2
3use kernel::{device, devres::Devres, error::code::*, pci, prelude::*, sync::Arc};3use kernel::{device, devres::Devres, error::code::*, fmt, pci, prelude::*, sync::Arc};
4 4
5use crate::driver::Bar0;5use crate::driver::Bar0;
6use crate::falcon::{gsp::Gsp, sec2::Sec2, Falcon};6use crate::falcon::{gsp::Gsp, sec2::Sec2, Falcon};
@@ -12,7 +12,6 @@ use crate::gfw; · 5 unmodified lines
12use crate::regs;12use crate::regs;
13use crate::util;13use crate::util;
14use crate::vbios::Vbios;14use crate::vbios::Vbios;
15use core::fmt;
16 15
17macro_rules! define_chipset {16macro_rules! define_chipset {
18 ({ $($variant:ident = $value:expr),* $(,)* }) =>17 ({ $($variant:ident = $value:expr),* $(,)* }) =>
drivers/gpu/nova-core/regs/macros.rs+3−3
@@ -149,10 +149,10 @@ macro_rules! register { · 148 unmodified lines
149 149
150 // TODO[REGA]: display the raw hex value, then the value of all the fields. This requires150 // TODO[REGA]: display the raw hex value, then the value of all the fields. This requires
151 // matching the fields, which will complexify the syntax considerably...151 // matching the fields, which will complexify the syntax considerably...
152 impl ::core::fmt::Debug for $name {152 impl ::kernel::fmt::Debug for $name {
153 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {153 fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
154 f.debug_tuple(stringify!($name))154 f.debug_tuple(stringify!($name))
155 .field(&format_args!("0x{0:x}", &self.0))155 .field(&::kernel::prelude::fmt!("0x{0:x}", &self.0))
156 .finish()156 .finish()
157 }157 }
158 }158 }
drivers/gpu/nova-core/vbios.rs+2−2
@@ -10,6 +10,7 @@ use kernel::device; · 9 unmodified lines
10use kernel::error::Result;10use kernel::error::Result;
11use kernel::pci;11use kernel::pci;
12use kernel::prelude::*;12use kernel::prelude::*;
13use kernel::ptr::{Alignable, Alignment};
13 14
14/// The offset of the VBIOS ROM in the BAR0 space.15/// The offset of the VBIOS ROM in the BAR0 space.
15const ROM_OFFSET: usize = 0x300000;16const ROM_OFFSET: usize = 0x300000;
@@ -177,8 +178,7 @@ impl<'a> Iterator for VbiosIterator<'a> { · 161 unmodified lines
177 178
178 // Advance to next image (aligned to 512 bytes).179 // Advance to next image (aligned to 512 bytes).
179 self.current_offset += image_size;180 self.current_offset += image_size;
180 // TODO[NUMM]: replace with `align_up` once it lands.181 self.current_offset = self.current_offset.align_up(Alignment::new::<512>())?;
181 self.current_offset = self.current_offset.next_multiple_of(512);
182 182
183 Some(Ok(full_image))183 Some(Ok(full_image))
184 }184 }
rust/Makefile+15−14
@@ -98,6 +98,12 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< · 97 unmodified lines
98# and then retouch the generated files.98# and then retouch the generated files.
99rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \99rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \
100 rustdoc-kernel rustdoc-pin_init100 rustdoc-kernel rustdoc-pin_init
101 $(Q)grep -Ehro '<a href="srctree/([^"]+)"' $(rustdoc_output) | \
102 cut -d'"' -f2 | cut -d/ -f2- | while read f; do \
103 if [ ! -e "$(srctree)/$$f" ]; then \
104 echo "warning: srctree/ link to $$f does not exist"; \
105 fi \
106 done
101 $(Q)cp $(srctree)/Documentation/images/logo.svg $(rustdoc_output)/static.files/107 $(Q)cp $(srctree)/Documentation/images/logo.svg $(rustdoc_output)/static.files/
102 $(Q)cp $(srctree)/Documentation/images/COPYING-logo $(rustdoc_output)/static.files/108 $(Q)cp $(srctree)/Documentation/images/COPYING-logo $(rustdoc_output)/static.files/
103 $(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \109 $(Q)find $(rustdoc_output) -name '*.html' -type f -print0 | xargs -0 sed -Ei \
@@ -193,12 +199,12 @@ rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \ · 89 unmodified lines
193 $(obj)/bindings.o FORCE199 $(obj)/bindings.o FORCE
194 +$(call if_changed,rustc_test_library)200 +$(call if_changed,rustc_test_library)
195 201
196rusttestlib-bindings: private rustc_target_flags = --extern ffi202rusttestlib-bindings: private rustc_target_flags = --extern ffi --extern pin_init
197rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi FORCE203rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi rusttestlib-pin_init FORCE
198 +$(call if_changed,rustc_test_library)204 +$(call if_changed,rustc_test_library)
199 205
200rusttestlib-uapi: private rustc_target_flags = --extern ffi206rusttestlib-uapi: private rustc_target_flags = --extern ffi --extern pin_init
201rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi FORCE207rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi rusttestlib-pin_init FORCE
202 +$(call if_changed,rustc_test_library)208 +$(call if_changed,rustc_test_library)
203 209
204quiet_cmd_rustdoc_test = RUSTDOC T $<210quiet_cmd_rustdoc_test = RUSTDOC T $<
@@ -248,7 +254,7 @@ quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T $< · 43 unmodified lines
248 $(objtree)/$(obj)/test/$(subst rusttest-,,$@) $(rust_test_quiet) \254 $(objtree)/$(obj)/test/$(subst rusttest-,,$@) $(rust_test_quiet) \
249 $(rustc_test_run_flags)255 $(rustc_test_run_flags)
250 256
251rusttest: rusttest-macros rusttest-kernel257rusttest: rusttest-macros
252 258
253rusttest-macros: private rustc_target_flags = --extern proc_macro \259rusttest-macros: private rustc_target_flags = --extern proc_macro \
254 --extern macros --extern kernel --extern pin_init260 --extern macros --extern kernel --extern pin_init
@@ -258,13 +264,6 @@ rusttest-macros: $(src)/macros/lib.rs \ · 3 unmodified lines
258 +$(call if_changed,rustc_test)264 +$(call if_changed,rustc_test)
259 +$(call if_changed,rustdoc_test)265 +$(call if_changed,rustdoc_test)
260 266
261rusttest-kernel: private rustc_target_flags = --extern ffi --extern pin_init \
262 --extern build_error --extern macros --extern bindings --extern uapi
263rusttest-kernel: $(src)/kernel/lib.rs rusttestlib-ffi rusttestlib-kernel \
264 rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \
265 rusttestlib-uapi rusttestlib-pin_init FORCE
266 +$(call if_changed,rustc_test)
267
268ifdef CONFIG_CC_IS_CLANG267ifdef CONFIG_CC_IS_CLANG
269bindgen_c_flags = $(c_flags)268bindgen_c_flags = $(c_flags)
270else269else
@@ -531,17 +530,19 @@ $(obj)/ffi.o: private skip_gendwarfksyms = 1 · 260 unmodified lines
531$(obj)/ffi.o: $(src)/ffi.rs $(obj)/compiler_builtins.o FORCE530$(obj)/ffi.o: $(src)/ffi.rs $(obj)/compiler_builtins.o FORCE
532 +$(call if_changed_rule,rustc_library)531 +$(call if_changed_rule,rustc_library)
533 532
534$(obj)/bindings.o: private rustc_target_flags = --extern ffi533$(obj)/bindings.o: private rustc_target_flags = --extern ffi --extern pin_init
535$(obj)/bindings.o: $(src)/bindings/lib.rs \534$(obj)/bindings.o: $(src)/bindings/lib.rs \
536 $(obj)/ffi.o \535 $(obj)/ffi.o \
536 $(obj)/pin_init.o \
537 $(obj)/bindings/bindings_generated.rs \537 $(obj)/bindings/bindings_generated.rs \
538 $(obj)/bindings/bindings_helpers_generated.rs FORCE538 $(obj)/bindings/bindings_helpers_generated.rs FORCE
539 +$(call if_changed_rule,rustc_library)539 +$(call if_changed_rule,rustc_library)
540 540
541$(obj)/uapi.o: private rustc_target_flags = --extern ffi541$(obj)/uapi.o: private rustc_target_flags = --extern ffi --extern pin_init
542$(obj)/uapi.o: private skip_gendwarfksyms = 1542$(obj)/uapi.o: private skip_gendwarfksyms = 1
543$(obj)/uapi.o: $(src)/uapi/lib.rs \543$(obj)/uapi.o: $(src)/uapi/lib.rs \
544 $(obj)/ffi.o \544 $(obj)/ffi.o \
545 $(obj)/pin_init.o \
545 $(obj)/uapi/uapi_generated.rs FORCE546 $(obj)/uapi/uapi_generated.rs FORCE
546 +$(call if_changed_rule,rustc_library)547 +$(call if_changed_rule,rustc_library)
547 548
rust/bindgen_parameters+5−0
@@ -34,3 +34,8 @@ · 33 unmodified lines
34# We use const helpers to aid bindgen, to avoid conflicts when constants are34# We use const helpers to aid bindgen, to avoid conflicts when constants are
35# recognized, block generation of the non-helper constants.35# recognized, block generation of the non-helper constants.
36--blocklist-item ARCH_SLAB_MINALIGN36--blocklist-item ARCH_SLAB_MINALIGN
37--blocklist-item ARCH_KMALLOC_MINALIGN
38
39# Structs should implement `Zeroable` when all of their fields do.
40--with-derive-custom-struct .*=MaybeZeroable
41--with-derive-custom-union .*=MaybeZeroable
rust/bindings/bindings_helper.h+1−0
@@ -84,6 +84,7 @@ · 83 unmodified lines
84 84
85/* `bindgen` gets confused at certain things. */85/* `bindgen` gets confused at certain things. */
86const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;86const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
87const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN;
87const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;88const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;
88const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC;89const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC;
89const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;90const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
rust/bindings/lib.rs+8−0
@@ -31,11 +31,19 @@ · 30 unmodified lines
31#[allow(clippy::undocumented_unsafe_blocks)]31#[allow(clippy::undocumented_unsafe_blocks)]
32#[cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]32#[cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]
33mod bindings_raw {33mod bindings_raw {
34 use pin_init::{MaybeZeroable, Zeroable};
35
34 // Manual definition for blocklisted types.36 // Manual definition for blocklisted types.
35 type __kernel_size_t = usize;37 type __kernel_size_t = usize;
36 type __kernel_ssize_t = isize;38 type __kernel_ssize_t = isize;
37 type __kernel_ptrdiff_t = isize;39 type __kernel_ptrdiff_t = isize;
38 40
41 // `bindgen` doesn't automatically do this, see
42 // <https://github.com/rust-lang/rust-bindgen/issues/3196>
43 //
44 // SAFETY: `__BindgenBitfieldUnit<Storage>` is a newtype around `Storage`.
45 unsafe impl<Storage> Zeroable for __BindgenBitfieldUnit<Storage> where Storage: Zeroable {}
46
39 // Use glob import here to expose all helpers.47 // Use glob import here to expose all helpers.
40 // Symbols defined within the module will take precedence to the glob import.48 // Symbols defined within the module will take precedence to the glob import.
41 pub use super::bindings_helper::*;49 pub use super::bindings_helper::*;
rust/kernel/acpi.rs+2−5
@@ -37,11 +37,8 @@ impl DeviceId { · 36 unmodified lines
37 /// Create a new device id from an ACPI 'id' string.37 /// Create a new device id from an ACPI 'id' string.
38 #[inline(always)]38 #[inline(always)]
39 pub const fn new(id: &'static CStr) -> Self {39 pub const fn new(id: &'static CStr) -> Self {
40 build_assert!(40 let src = id.to_bytes_with_nul();
41 id.len_with_nul() <= Self::ACPI_ID_LEN,41 build_assert!(src.len() <= Self::ACPI_ID_LEN, "ID exceeds 16 bytes");
42 "ID exceeds 16 bytes"
43 );
44 let src = id.as_bytes_with_nul();
45 // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`.42 // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`.
46 // SAFETY: FFI type is valid to be zero-initialized.43 // SAFETY: FFI type is valid to be zero-initialized.
47 let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() };44 let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() };
rust/kernel/alloc.rs+8−7
@@ -2,18 +2,11 @@ · 1 unmodified line
2 2
3//! Implementation of the kernel's memory allocation infrastructure.3//! Implementation of the kernel's memory allocation infrastructure.
4 4
5#[cfg(not(any(test, testlib)))]
6pub mod allocator;5pub mod allocator;
7pub mod kbox;6pub mod kbox;
8pub mod kvec;7pub mod kvec;
9pub mod layout;8pub mod layout;
10 9
11#[cfg(any(test, testlib))]
12pub mod allocator_test;
13
14#[cfg(any(test, testlib))]
15pub use self::allocator_test as allocator;
16
17pub use self::kbox::Box;10pub use self::kbox::Box;
18pub use self::kbox::KBox;11pub use self::kbox::KBox;
19pub use self::kbox::KVBox;12pub use self::kbox::KVBox;
@@ -137,6 +130,14 @@ pub mod flags { · 117 unmodified lines
137/// - Implementers must ensure that all trait functions abide by the guarantees documented in the130/// - Implementers must ensure that all trait functions abide by the guarantees documented in the
138/// `# Guarantees` sections.131/// `# Guarantees` sections.
139pub unsafe trait Allocator {132pub unsafe trait Allocator {
133 /// The minimum alignment satisfied by all allocations from this allocator.
134 ///
135 /// # Guarantees
136 ///
137 /// Any pointer allocated by this allocator is guaranteed to be aligned to `MIN_ALIGN` even if
138 /// the requested layout has a smaller alignment.
139 const MIN_ALIGN: usize;
140
140 /// Allocate memory based on `layout` and `flags`.141 /// Allocate memory based on `layout` and `flags`.
141 ///142 ///
142 /// On success, returns a buffer represented as `NonNull<[u8]>` that satisfies the layout143 /// On success, returns a buffer represented as `NonNull<[u8]>` that satisfies the layout
rust/kernel/alloc/allocator.rs+8−0
@@ -17,6 +17,8 @@ use crate::alloc::{AllocError, Allocator}; · 16 unmodified lines
17use crate::bindings;17use crate::bindings;
18use crate::pr_warn;18use crate::pr_warn;
19 19
20const ARCH_KMALLOC_MINALIGN: usize = bindings::ARCH_KMALLOC_MINALIGN;
21
20/// The contiguous kernel allocator.22/// The contiguous kernel allocator.
21///23///
22/// `Kmalloc` is typically used for physically contiguous allocations up to page size, but also24/// `Kmalloc` is typically used for physically contiguous allocations up to page size, but also
@@ -128,6 +130,8 @@ impl Kmalloc { · 105 unmodified lines
128// - passing a pointer to a valid memory allocation is OK,130// - passing a pointer to a valid memory allocation is OK,
129// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.131// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.
130unsafe impl Allocator for Kmalloc {132unsafe impl Allocator for Kmalloc {
133 const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN;
134
131 #[inline]135 #[inline]
132 unsafe fn realloc(136 unsafe fn realloc(
133 ptr: Option<NonNull<u8>>,137 ptr: Option<NonNull<u8>>,
@@ -147,6 +151,8 @@ unsafe impl Allocator for Kmalloc { · 13 unmodified lines
147// - passing a pointer to a valid memory allocation is OK,151// - passing a pointer to a valid memory allocation is OK,
148// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.152// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.
149unsafe impl Allocator for Vmalloc {153unsafe impl Allocator for Vmalloc {
154 const MIN_ALIGN: usize = kernel::page::PAGE_SIZE;
155
150 #[inline]156 #[inline]
151 unsafe fn realloc(157 unsafe fn realloc(
152 ptr: Option<NonNull<u8>>,158 ptr: Option<NonNull<u8>>,
@@ -171,6 +177,8 @@ unsafe impl Allocator for Vmalloc { · 18 unmodified lines
171// - passing a pointer to a valid memory allocation is OK,177// - passing a pointer to a valid memory allocation is OK,
172// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.178// - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.
173unsafe impl Allocator for KVmalloc {179unsafe impl Allocator for KVmalloc {
180 const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN;
181
174 #[inline]182 #[inline]
175 unsafe fn realloc(183 unsafe fn realloc(
176 ptr: Option<NonNull<u8>>,184 ptr: Option<NonNull<u8>>,
rust/kernel/alloc/allocator_test.rs+0−124
@@ -1,124 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2
3//! So far the kernel's `Box` and `Vec` types can't be used by userspace test cases, since all users
4//! of those types (e.g. `CString`) use kernel allocators for instantiation.
5//!
6//! In order to allow userspace test cases to make use of such types as well, implement the
7//! `Cmalloc` allocator within the `allocator_test` module and type alias all kernel allocators to
8//! `Cmalloc`. The `Cmalloc` allocator uses libc's `realloc()` function as allocator backend.
9
10#![allow(missing_docs)]
11
12use super::{flags::*, AllocError, Allocator, Flags};
13use core::alloc::Layout;
14use core::cmp;
15use core::ptr;
16use core::ptr::NonNull;
17
18/// The userspace allocator based on libc.
19pub struct Cmalloc;
20
21pub type Kmalloc = Cmalloc;
22pub type Vmalloc = Kmalloc;
23pub type KVmalloc = Kmalloc;
24
25impl Cmalloc {
26 /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of
27 /// `layout`.
28 pub fn aligned_layout(layout: Layout) -> Layout {
29 // Note that `layout.size()` (after padding) is guaranteed to be a multiple of
30 // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return
31 // a properly aligned object (see comments in `kmalloc()` for more information).
32 layout.pad_to_align()
33 }
34}
35
36extern "C" {
37 #[link_name = "aligned_alloc"]
38 fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void;
39
40 #[link_name = "free"]
41 fn libc_free(ptr: *mut crate::ffi::c_void);
42}
43
44// SAFETY:
45// - memory remains valid until it is explicitly freed,
46// - passing a pointer to a valid memory allocation created by this `Allocator` is always OK,
47// - `realloc` provides the guarantees as provided in the `# Guarantees` section.
48unsafe impl Allocator for Cmalloc {
49 unsafe fn realloc(
50 ptr: Option<NonNull<u8>>,
51 layout: Layout,
52 old_layout: Layout,
53 flags: Flags,
54 ) -> Result<NonNull<[u8]>, AllocError> {
55 let src = match ptr {
56 Some(src) => {
57 if old_layout.size() == 0 {
58 ptr::null_mut()
59 } else {
60 src.as_ptr()
61 }
62 }
63 None => ptr::null_mut(),
64 };
65
66 if layout.size() == 0 {
67 // SAFETY: `src` is either NULL or was previously allocated with this `Allocator`
68 unsafe { libc_free(src.cast()) };
69
70 return Ok(NonNull::slice_from_raw_parts(
71 crate::alloc::dangling_from_layout(layout),
72 0,
73 ));
74 }
75
76 // ISO C (ISO/IEC 9899:2011) defines `aligned_alloc`:
77 //
78 // > The value of alignment shall be a valid alignment supported by the implementation
79 // [...].
80 //
81 // As an example of the "supported by the implementation" requirement, POSIX.1-2001 (IEEE
82 // 1003.1-2001) defines `posix_memalign`:
83 //
84 // > The value of alignment shall be a power of two multiple of sizeof (void *).
85 //
86 // and POSIX-based implementations of `aligned_alloc` inherit this requirement. At the time
87 // of writing, this is known to be the case on macOS (but not in glibc).
88 //
89 // Satisfy the stricter requirement to avoid spurious test failures on some platforms.
90 let min_align = core::mem::size_of::<*const crate::ffi::c_void>();
91 let layout = layout.align_to(min_align).map_err(|_| AllocError)?;
92 let layout = layout.pad_to_align();
93
94 // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or
95 // exceeds the given size and alignment requirements.
96 let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) }.cast::<u8>();
97 let dst = NonNull::new(dst).ok_or(AllocError)?;
98
99 if flags.contains(__GFP_ZERO) {
100 // SAFETY: The preceding calls to `libc_aligned_alloc` and `NonNull::new`
101 // guarantee that `dst` points to memory of at least `layout.size()` bytes.
102 unsafe { dst.as_ptr().write_bytes(0, layout.size()) };
103 }
104
105 if !src.is_null() {
106 // SAFETY:
107 // - `src` has previously been allocated with this `Allocator`; `dst` has just been
108 // newly allocated, hence the memory regions do not overlap.
109 // - both` src` and `dst` are properly aligned and valid for reads and writes
110 unsafe {
111 ptr::copy_nonoverlapping(
112 src,
113 dst.as_ptr(),
114 cmp::min(layout.size(), old_layout.size()),
115 )
116 };
117 }
118
119 // SAFETY: `src` is either NULL or was previously allocated with this `Allocator`
120 unsafe { libc_free(src.cast()) };
121
122 Ok(NonNull::slice_from_raw_parts(dst, layout.size()))
123 }
124}
rust/kernel/alloc/kbox.rs+87−5
@@ -7,7 +7,6 @@ use super::allocator::{KVmalloc, Kmalloc, Vmalloc}; · 6 unmodified lines
7use super::{AllocError, Allocator, Flags};7use super::{AllocError, Allocator, Flags};
8use core::alloc::Layout;8use core::alloc::Layout;
9use core::borrow::{Borrow, BorrowMut};9use core::borrow::{Borrow, BorrowMut};
10use core::fmt;
11use core::marker::PhantomData;10use core::marker::PhantomData;
12use core::mem::ManuallyDrop;11use core::mem::ManuallyDrop;
13use core::mem::MaybeUninit;12use core::mem::MaybeUninit;
@@ -17,6 +16,7 @@ use core::ptr::NonNull; · 3 unmodified lines
17use core::result::Result;16use core::result::Result;
18 17
19use crate::ffi::c_void;18use crate::ffi::c_void;
19use crate::fmt;
20use crate::init::InPlaceInit;20use crate::init::InPlaceInit;
21use crate::types::ForeignOwnable;21use crate::types::ForeignOwnable;
22use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};22use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
@@ -290,6 +290,83 @@ where · 267 unmodified lines
290 Ok(Self::new(x, flags)?.into())290 Ok(Self::new(x, flags)?.into())
291 }291 }
292 292
293 /// Construct a pinned slice of elements `Pin<Box<[T], A>>`.
294 ///
295 /// This is a convenient means for creation of e.g. slices of structrures containing spinlocks
296 /// or mutexes.
297 ///
298 /// # Examples
299 ///
300 /// ```
301 /// use kernel::sync::{new_spinlock, SpinLock};
302 ///
303 /// struct Inner {
304 /// a: u32,
305 /// b: u32,
306 /// }
307 ///
308 /// #[pin_data]
309 /// struct Example {
310 /// c: u32,
311 /// #[pin]
312 /// d: SpinLock<Inner>,
313 /// }
314 ///
315 /// impl Example {
316 /// fn new() -> impl PinInit<Self, Error> {
317 /// try_pin_init!(Self {
318 /// c: 10,
319 /// d <- new_spinlock!(Inner { a: 20, b: 30 }),
320 /// })
321 /// }
322 /// }
323 ///
324 /// // Allocate a boxed slice of 10 `Example`s.
325 /// let s = KBox::pin_slice(
326 /// | _i | Example::new(),
327 /// 10,
328 /// GFP_KERNEL
329 /// )?;
330 ///
331 /// assert_eq!(s[5].c, 10);
332 /// assert_eq!(s[3].d.lock().a, 20);
333 /// # Ok::<(), Error>(())
334 /// ```
335 pub fn pin_slice<Func, Item, E>(
336 mut init: Func,
337 len: usize,
338 flags: Flags,
339 ) -> Result<Pin<Box<[T], A>>, E>
340 where
341 Func: FnMut(usize) -> Item,
342 Item: PinInit<T, E>,
343 E: From<AllocError>,
344 {
345 let mut buffer = super::Vec::<T, A>::with_capacity(len, flags)?;
346 for i in 0..len {
347 let ptr = buffer.spare_capacity_mut().as_mut_ptr().cast();
348 // SAFETY:
349 // - `ptr` is a valid pointer to uninitialized memory.
350 // - `ptr` is not used if an error is returned.
351 // - `ptr` won't be moved until it is dropped, i.e. it is pinned.
352 unsafe { init(i).__pinned_init(ptr)? };
353
354 // SAFETY:
355 // - `i + 1 <= len`, hence we don't exceed the capacity, due to the call to
356 // `with_capacity()` above.
357 // - The new value at index buffer.len() + 1 is the only element being added here, and
358 // it has been initialized above by `init(i).__pinned_init(ptr)`.
359 unsafe { buffer.inc_len(1) };
360 }
361
362 let (ptr, _, _) = buffer.into_raw_parts();
363 let slice = core::ptr::slice_from_raw_parts_mut(ptr, len);
364
365 // SAFETY: `slice` points to an allocation allocated with `A` (`buffer`) and holds a valid
366 // `[T]`.
367 Ok(Pin::from(unsafe { Box::from_raw(slice) }))
368 }
369
293 /// Convert a [`Box<T,A>`] to a [`Pin<Box<T,A>>`]. If `T` does not implement370 /// Convert a [`Box<T,A>`] to a [`Pin<Box<T,A>>`]. If `T` does not implement
294 /// [`Unpin`], then `x` will be pinned in memory and can't be moved.371 /// [`Unpin`], then `x` will be pinned in memory and can't be moved.
295 pub fn into_pin(this: Self) -> Pin<Self> {372 pub fn into_pin(this: Self) -> Pin<Self> {
@@ -401,12 +478,17 @@ where · 105 unmodified lines
401}478}
402 479
403// SAFETY: The pointer returned by `into_foreign` comes from a well aligned480// SAFETY: The pointer returned by `into_foreign` comes from a well aligned
404// pointer to `T`.481// pointer to `T` allocated by `A`.
405unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>482unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>
406where483where
407 A: Allocator,484 A: Allocator,
408{485{
409 const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();486 const FOREIGN_ALIGN: usize = if core::mem::align_of::<T>() < A::MIN_ALIGN {
487 A::MIN_ALIGN
488 } else {
489 core::mem::align_of::<T>()
490 };
491
410 type Borrowed<'a> = &'a T;492 type Borrowed<'a> = &'a T;
411 type BorrowedMut<'a> = &'a mut T;493 type BorrowedMut<'a> = &'a mut T;
412 494
@@ -435,12 +517,12 @@ where · 22 unmodified lines
435}517}
436 518
437// SAFETY: The pointer returned by `into_foreign` comes from a well aligned519// SAFETY: The pointer returned by `into_foreign` comes from a well aligned
438// pointer to `T`.520// pointer to `T` allocated by `A`.
439unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>521unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
440where522where
441 A: Allocator,523 A: Allocator,
442{524{
443 const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();525 const FOREIGN_ALIGN: usize = <Box<T, A> as ForeignOwnable>::FOREIGN_ALIGN;
444 type Borrowed<'a> = Pin<&'a T>;526 type Borrowed<'a> = Pin<&'a T>;
445 type BorrowedMut<'a> = Pin<&'a mut T>;527 type BorrowedMut<'a> = Pin<&'a mut T>;
446 528
rust/kernel/alloc/kvec.rs+17−7
@@ -7,9 +7,9 @@ use super::{ · 6 unmodified lines
7 layout::ArrayLayout,7 layout::ArrayLayout,
8 AllocError, Allocator, Box, Flags,8 AllocError, Allocator, Box, Flags,
9};9};
10use crate::fmt;
10use core::{11use core::{
11 borrow::{Borrow, BorrowMut},12 borrow::{Borrow, BorrowMut},
12 fmt,
13 marker::PhantomData,13 marker::PhantomData,
14 mem::{ManuallyDrop, MaybeUninit},14 mem::{ManuallyDrop, MaybeUninit},
15 ops::Deref,15 ops::Deref,
@@ -175,7 +175,7 @@ where · 159 unmodified lines
175 175
176 /// Returns the number of elements that can be stored within the vector without allocating176 /// Returns the number of elements that can be stored within the vector without allocating
177 /// additional memory.177 /// additional memory.
178 pub fn capacity(&self) -> usize {178 pub const fn capacity(&self) -> usize {
179 if const { Self::is_zst() } {179 if const { Self::is_zst() } {
180 usize::MAX180 usize::MAX
181 } else {181 } else {
@@ -185,7 +185,7 @@ where · 3 unmodified lines
185 185
186 /// Returns the number of elements stored within the vector.186 /// Returns the number of elements stored within the vector.
187 #[inline]187 #[inline]
188 pub fn len(&self) -> usize {188 pub const fn len(&self) -> usize {
189 self.len189 self.len
190 }190 }
191 191
@@ -196,7 +196,7 @@ where · 4 unmodified lines
196 /// - `additional` must be less than or equal to `self.capacity - self.len`.196 /// - `additional` must be less than or equal to `self.capacity - self.len`.
197 /// - All elements within the interval [`self.len`,`self.len + additional`) must be initialized.197 /// - All elements within the interval [`self.len`,`self.len + additional`) must be initialized.
198 #[inline]198 #[inline]
199 pub unsafe fn inc_len(&mut self, additional: usize) {199 pub const unsafe fn inc_len(&mut self, additional: usize) {
200 // Guaranteed by the type invariant to never underflow.200 // Guaranteed by the type invariant to never underflow.
201 debug_assert!(additional <= self.capacity() - self.len());201 debug_assert!(additional <= self.capacity() - self.len());
202 // INVARIANT: By the safety requirements of this method this represents the exact number of202 // INVARIANT: By the safety requirements of this method this represents the exact number of
@@ -224,6 +224,16 @@ where · 21 unmodified lines
224 }224 }
225 225
226 /// Returns a slice of the entire vector.226 /// Returns a slice of the entire vector.
227 ///
228 /// # Examples
229 ///
230 /// ```
231 /// let mut v = KVec::new();
232 /// v.push(1, GFP_KERNEL)?;
233 /// v.push(2, GFP_KERNEL)?;
234 /// assert_eq!(v.as_slice(), &[1, 2]);
235 /// # Ok::<(), Error>(())
236 /// ```
227 #[inline]237 #[inline]
228 pub fn as_slice(&self) -> &[T] {238 pub fn as_slice(&self) -> &[T] {
229 self239 self
@@ -245,7 +255,7 @@ where · 15 unmodified lines
245 /// Returns a raw pointer to the vector's backing buffer, or, if `T` is a ZST, a dangling raw255 /// Returns a raw pointer to the vector's backing buffer, or, if `T` is a ZST, a dangling raw
246 /// pointer.256 /// pointer.
247 #[inline]257 #[inline]
248 pub fn as_ptr(&self) -> *const T {258 pub const fn as_ptr(&self) -> *const T {
249 self.ptr.as_ptr()259 self.ptr.as_ptr()
250 }260 }
251 261
@@ -261,7 +271,7 @@ where · 9 unmodified lines
261 /// assert!(!v.is_empty());271 /// assert!(!v.is_empty());
262 /// ```272 /// ```
263 #[inline]273 #[inline]
264 pub fn is_empty(&self) -> bool {274 pub const fn is_empty(&self) -> bool {
265 self.len() == 0275 self.len() == 0
266 }276 }
267 277
@@ -1294,7 +1304,7 @@ impl<'vec, T> Drop for DrainAll<'vec, T> { · 1026 unmodified lines
1294 }1304 }
1295}1305}
1296 1306
1297#[macros::kunit_tests(rust_kvec_kunit)]1307#[macros::kunit_tests(rust_kvec)]
1298mod tests {1308mod tests {
1299 use super::*;1309 use super::*;
1300 use crate::prelude::*;1310 use crate::prelude::*;
rust/kernel/alloc/kvec/errors.rs+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3//! Errors for the [`Vec`] type.3//! Errors for the [`Vec`] type.
4 4
5use core::fmt::{self, Debug, Formatter};5use kernel::fmt::{self, Debug, Formatter};
6use kernel::prelude::*;6use kernel::prelude::*;
7 7
8/// Error type for [`Vec::push_within_capacity`].8/// Error type for [`Vec::push_within_capacity`].
rust/kernel/alloc/layout.rs+1−1
@@ -80,7 +80,7 @@ impl<T> ArrayLayout<T> { · 79 unmodified lines
80 /// # Safety80 /// # Safety
81 ///81 ///
82 /// `len` must be a value, for which `len * size_of::<T>() <= isize::MAX` is true.82 /// `len` must be a value, for which `len * size_of::<T>() <= isize::MAX` is true.
83 pub unsafe fn new_unchecked(len: usize) -> Self {83 pub const unsafe fn new_unchecked(len: usize) -> Self {
84 // INVARIANT: By the safety requirements of this function84 // INVARIANT: By the safety requirements of this function
85 // `len * size_of::<T>() <= isize::MAX`.85 // `len * size_of::<T>() <= isize::MAX`.
86 Self {86 Self {
rust/kernel/auxiliary.rs+2−2
@@ -105,8 +105,8 @@ pub struct DeviceId(bindings::auxiliary_device_id); · 104 unmodified lines
105impl DeviceId {105impl DeviceId {
106 /// Create a new [`DeviceId`] from name.106 /// Create a new [`DeviceId`] from name.
107 pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self {107 pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self {
108 let name = name.as_bytes_with_nul();108 let name = name.to_bytes_with_nul();
109 let modname = modname.as_bytes_with_nul();109 let modname = modname.to_bytes_with_nul();
110 110
111 // TODO: Replace with `bindings::auxiliary_device_id::default()` once stabilized for111 // TODO: Replace with `bindings::auxiliary_device_id::default()` once stabilized for
112 // `const`.112 // `const`.
rust/kernel/block/mq.rs+1−1
@@ -82,7 +82,7 @@ · 81 unmodified lines
82//! Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?;82//! Arc::pin_init(TagSet::new(1, 256, 1), flags::GFP_KERNEL)?;
83//! let mut disk = gen_disk::GenDiskBuilder::new()83//! let mut disk = gen_disk::GenDiskBuilder::new()
84//! .capacity_sectors(4096)84//! .capacity_sectors(4096)
85//! .build(format_args!("myblk"), tagset)?;85//! .build(fmt!("myblk"), tagset)?;
86//!86//!
87//! # Ok::<(), kernel::error::Error>(())87//! # Ok::<(), kernel::error::Error>(())
88//! ```88//! ```
rust/kernel/block/mq/gen_disk.rs+2−2
@@ -3,12 +3,12 @@ · 2 unmodified lines
3//! Generic disk abstraction.3//! Generic disk abstraction.
4//!4//!
5//! C header: [`include/linux/blkdev.h`](srctree/include/linux/blkdev.h)5//! C header: [`include/linux/blkdev.h`](srctree/include/linux/blkdev.h)
6//! C header: [`include/linux/blk_mq.h`](srctree/include/linux/blk_mq.h)6//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h)
7 7
8use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet};8use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet};
9use crate::fmt::{self, Write};
9use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc};10use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc};
10use crate::{error, static_lock_class};11use crate::{error, static_lock_class};
11use core::fmt::{self, Write};
12 12
13/// A builder for [`GenDisk`].13/// A builder for [`GenDisk`].
14///14///
rust/kernel/block/mq/raw_writer.rs+1−2
@@ -1,8 +1,7 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2 2
3use core::fmt::{self, Write};
4
5use crate::error::Result;3use crate::error::Result;
4use crate::fmt::{self, Write};
6use crate::prelude::EINVAL;5use crate::prelude::EINVAL;
7 6
8/// A mutable reference to a byte buffer where a string can be written into.7/// A mutable reference to a byte buffer where a string can be written into.
rust/kernel/configfs.rs+2−2
@@ -263,7 +263,7 @@ impl<Data> Group<Data> { · 262 unmodified lines
263 try_pin_init!(Self {263 try_pin_init!(Self {
264 group <- pin_init::init_zeroed().chain(|v: &mut Opaque<bindings::config_group>| {264 group <- pin_init::init_zeroed().chain(|v: &mut Opaque<bindings::config_group>| {
265 let place = v.get();265 let place = v.get();
266 let name = name.as_bytes_with_nul().as_ptr();266 let name = name.to_bytes_with_nul().as_ptr();
267 // SAFETY: It is safe to initialize a group once it has been zeroed.267 // SAFETY: It is safe to initialize a group once it has been zeroed.
268 unsafe {268 unsafe {
269 bindings::config_group_init_type_name(place, name.cast(), item_type.as_ptr())269 bindings::config_group_init_type_name(place, name.cast(), item_type.as_ptr())
@@ -613,7 +613,7 @@ where · 343 unmodified lines
613 pub const fn new(name: &'static CStr) -> Self {613 pub const fn new(name: &'static CStr) -> Self {
614 Self {614 Self {
615 attribute: Opaque::new(bindings::configfs_attribute {615 attribute: Opaque::new(bindings::configfs_attribute {
616 ca_name: name.as_char_ptr(),616 ca_name: crate::str::as_char_ptr_in_const_context(name),
617 ca_owner: core::ptr::null_mut(),617 ca_owner: core::ptr::null_mut(),
618 ca_mode: 0o660,618 ca_mode: 0o660,
619 show: Some(Self::show),619 show: Some(Self::show),
rust/kernel/cpu.rs+1−0
@@ -109,6 +109,7 @@ impl CpuId { · 108 unmodified lines
109 /// unexpectedly due to preemption or CPU migration. It should only be109 /// unexpectedly due to preemption or CPU migration. It should only be
110 /// used when the context ensures that the task remains on the same CPU110 /// used when the context ensures that the task remains on the same CPU
111 /// or the users could use a stale (yet valid) CPU ID.111 /// or the users could use a stale (yet valid) CPU ID.
112 #[inline]
112 pub fn current() -> Self {113 pub fn current() -> Self {
113 // SAFETY: raw_smp_processor_id() always returns a valid CPU ID.114 // SAFETY: raw_smp_processor_id() always returns a valid CPU ID.
114 unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) }115 unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) }
rust/kernel/cpufreq.rs+2−4
@@ -27,7 +27,6 @@ use crate::clk::Clk; · 26 unmodified lines
27use core::{27use core::{
28 cell::UnsafeCell,28 cell::UnsafeCell,
29 marker::PhantomData,29 marker::PhantomData,
30 mem::MaybeUninit,
31 ops::{Deref, DerefMut},30 ops::{Deref, DerefMut},
32 pin::Pin,31 pin::Pin,
33 ptr,32 ptr,
@@ -1013,12 +1012,11 @@ impl<T: Driver> Registration<T> { · 979 unmodified lines
1013 } else {1012 } else {
1014 None1013 None
1015 },1014 },
1016 // SAFETY: All zeros is a valid value for `bindings::cpufreq_driver`.1015 ..pin_init::zeroed()
1017 ..unsafe { MaybeUninit::zeroed().assume_init() }
1018 };1016 };
1019 1017
1020 const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {1018 const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
1021 let src = name.as_bytes_with_nul();1019 let src = name.to_bytes_with_nul();
1022 let mut dst = [0; CPUFREQ_NAME_LEN];1020 let mut dst = [0; CPUFREQ_NAME_LEN];
1023 1021
1024 build_assert!(src.len() <= CPUFREQ_NAME_LEN);1022 build_assert!(src.len() <= CPUFREQ_NAME_LEN);
rust/kernel/device.rs+3−3
@@ -5,10 +5,10 @@ · 4 unmodified lines
5//! C header: [`include/linux/device.h`](srctree/include/linux/device.h)5//! C header: [`include/linux/device.h`](srctree/include/linux/device.h)
6 6
7use crate::{7use crate::{
8 bindings,8 bindings, fmt,
9 types::{ARef, ForeignOwnable, Opaque},9 types::{ARef, ForeignOwnable, Opaque},
10};10};
11use core::{fmt, marker::PhantomData, ptr};11use core::{marker::PhantomData, ptr};
12 12
13#[cfg(CONFIG_PRINTK)]13#[cfg(CONFIG_PRINTK)]
14use crate::c_str;14use crate::c_str;
@@ -596,7 +596,7 @@ macro_rules! impl_device_context_into_aref { · 581 unmodified lines
596macro_rules! dev_printk {596macro_rules! dev_printk {
597 ($method:ident, $dev:expr, $($f:tt)*) => {597 ($method:ident, $dev:expr, $($f:tt)*) => {
598 {598 {
599 ($dev).$method(::core::format_args!($($f)*));599 ($dev).$method($crate::prelude::fmt!($($f)*));
600 }600 }
601 }601 }
602}602}
rust/kernel/device/property.rs+12−11
@@ -11,6 +11,7 @@ use crate::{ · 10 unmodified lines
11 alloc::KVec,11 alloc::KVec,
12 bindings,12 bindings,
13 error::{to_result, Result},13 error::{to_result, Result},
14 fmt,
14 prelude::*,15 prelude::*,
15 str::{CStr, CString},16 str::{CStr, CString},
16 types::{ARef, Opaque},17 types::{ARef, Opaque},
@@ -68,16 +69,16 @@ impl FwNode { · 51 unmodified lines
68 unsafe { bindings::is_of_node(self.as_raw()) }69 unsafe { bindings::is_of_node(self.as_raw()) }
69 }70 }
70 71
71 /// Returns an object that implements [`Display`](core::fmt::Display) for72 /// Returns an object that implements [`Display`](fmt::Display) for
72 /// printing the name of a node.73 /// printing the name of a node.
73 ///74 ///
74 /// This is an alternative to the default `Display` implementation, which75 /// This is an alternative to the default `Display` implementation, which
75 /// prints the full path.76 /// prints the full path.
76 pub fn display_name(&self) -> impl core::fmt::Display + '_ {77 pub fn display_name(&self) -> impl fmt::Display + '_ {
77 struct FwNodeDisplayName<'a>(&'a FwNode);78 struct FwNodeDisplayName<'a>(&'a FwNode);
78 79
79 impl core::fmt::Display for FwNodeDisplayName<'_> {80 impl fmt::Display for FwNodeDisplayName<'_> {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 // SAFETY: `self` is valid by its type invariant.82 // SAFETY: `self` is valid by its type invariant.
82 let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) };83 let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) };
83 if name.is_null() {84 if name.is_null() {
@@ -87,7 +88,7 @@ impl FwNode { · 3 unmodified lines
87 // - `fwnode_get_name` returns null or a valid C string.88 // - `fwnode_get_name` returns null or a valid C string.
88 // - `name` was checked to be non-null.89 // - `name` was checked to be non-null.
89 let name = unsafe { CStr::from_char_ptr(name) };90 let name = unsafe { CStr::from_char_ptr(name) };
90 write!(f, "{name}")91 fmt::Display::fmt(name, f)
91 }92 }
92 }93 }
93 94
@@ -351,8 +352,8 @@ impl FwNodeReferenceArgs { · 257 unmodified lines
351 }352 }
352}353}
353 354
354impl core::fmt::Debug for FwNodeReferenceArgs {355impl fmt::Debug for FwNodeReferenceArgs {
355 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {356 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356 write!(f, "{:?}", self.as_slice())357 write!(f, "{:?}", self.as_slice())
357 }358 }
358}359}
@@ -377,8 +378,8 @@ enum Node<'a> { · 18 unmodified lines
377 Owned(ARef<FwNode>),378 Owned(ARef<FwNode>),
378}379}
379 380
380impl core::fmt::Display for FwNode {381impl fmt::Display for FwNode {
381 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
382 // The logic here is the same as the one in lib/vsprintf.c383 // The logic here is the same as the one in lib/vsprintf.c
383 // (fwnode_full_name_string).384 // (fwnode_full_name_string).
384 385
@@ -413,9 +414,9 @@ impl core::fmt::Display for FwNode { · 28 unmodified lines
413 // SAFETY: `fwnode_get_name_prefix` returns null or a414 // SAFETY: `fwnode_get_name_prefix` returns null or a
414 // valid C string.415 // valid C string.
415 let prefix = unsafe { CStr::from_char_ptr(prefix) };416 let prefix = unsafe { CStr::from_char_ptr(prefix) };
416 write!(f, "{prefix}")?;417 fmt::Display::fmt(prefix, f)?;
417 }418 }
418 write!(f, "{}", fwnode.display_name())?;419 fmt::Display::fmt(&fwnode.display_name(), f)?;
419 }420 }
420 421
421 Ok(())422 Ok(())
rust/kernel/dma.rs+1−1
@@ -9,8 +9,8 @@ use crate::{ · 8 unmodified lines
9 device::{Bound, Core},9 device::{Bound, Core},
10 error::{to_result, Result},10 error::{to_result, Result},
11 prelude::*,11 prelude::*,
12 sync::aref::ARef,
12 transmute::{AsBytes, FromBytes},13 transmute::{AsBytes, FromBytes},
13 types::ARef,
14};14};
15 15
16/// Trait to be implemented by DMA capable bus devices.16/// Trait to be implemented by DMA capable bus devices.
rust/kernel/drm/device.rs+3−3
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3//! DRM device.3//! DRM device.
4//!4//!
5//! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h)5//! C header: [`include/drm/drm_device.h`](srctree/include/drm/drm_device.h)
6 6
7use crate::{7use crate::{
8 alloc::allocator::Kmalloc,8 alloc::allocator::Kmalloc,
@@ -82,8 +82,8 @@ impl<T: drm::Driver> Device<T> { · 73 unmodified lines
82 major: T::INFO.major,82 major: T::INFO.major,
83 minor: T::INFO.minor,83 minor: T::INFO.minor,
84 patchlevel: T::INFO.patchlevel,84 patchlevel: T::INFO.patchlevel,
85 name: T::INFO.name.as_char_ptr().cast_mut(),85 name: crate::str::as_char_ptr_in_const_context(T::INFO.name).cast_mut(),
86 desc: T::INFO.desc.as_char_ptr().cast_mut(),86 desc: crate::str::as_char_ptr_in_const_context(T::INFO.desc).cast_mut(),
87 87
88 driver_features: drm::driver::FEAT_GEM,88 driver_features: drm::driver::FEAT_GEM,
89 ioctls: T::IOCTLS.as_ptr(),89 ioctls: T::IOCTLS.as_ptr(),
rust/kernel/drm/driver.rs+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3//! DRM driver core.3//! DRM driver core.
4//!4//!
5//! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h)5//! C header: [`include/drm/drm_drv.h`](srctree/include/drm/drm_drv.h)
6 6
7use crate::{7use crate::{
8 bindings, device, devres, drm,8 bindings, device, devres, drm,
rust/kernel/drm/file.rs+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3//! DRM File objects.3//! DRM File objects.
4//!4//!
5//! C header: [`include/linux/drm/drm_file.h`](srctree/include/linux/drm/drm_file.h)5//! C header: [`include/drm/drm_file.h`](srctree/include/drm/drm_file.h)
6 6
7use crate::{bindings, drm, error::Result, prelude::*, types::Opaque};7use crate::{bindings, drm, error::Result, prelude::*, types::Opaque};
8use core::marker::PhantomData;8use core::marker::PhantomData;
rust/kernel/drm/gem/mod.rs+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3//! DRM GEM API3//! DRM GEM API
4//!4//!
5//! C header: [`include/linux/drm/drm_gem.h`](srctree/include/linux/drm/drm_gem.h)5//! C header: [`include/drm/drm_gem.h`](srctree/include/drm/drm_gem.h)
6 6
7use crate::{7use crate::{
8 alloc::flags::*,8 alloc::flags::*,
rust/kernel/drm/ioctl.rs+1−1
@@ -2,7 +2,7 @@ · 1 unmodified line
2 2
3//! DRM IOCTL definitions.3//! DRM IOCTL definitions.
4//!4//!
5//! C header: [`include/linux/drm/drm_ioctl.h`](srctree/include/linux/drm/drm_ioctl.h)5//! C header: [`include/drm/drm_ioctl.h`](srctree/include/drm/drm_ioctl.h)
6 6
7use crate::ioctl;7use crate::ioctl;
8 8
rust/kernel/error.rs+59−7
@@ -2,7 +2,9 @@ · 1 unmodified line
2 2
3//! Kernel errors.3//! Kernel errors.
4//!4//!
5//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)5//! C header: [`include/uapi/asm-generic/errno-base.h`](srctree/include/uapi/asm-generic/errno-base.h)\
6//! C header: [`include/uapi/asm-generic/errno.h`](srctree/include/uapi/asm-generic/errno.h)\
7//! C header: [`include/linux/errno.h`](srctree/include/linux/errno.h)
6 8
7use crate::{9use crate::{
8 alloc::{layout::LayoutError, AllocError},10 alloc::{layout::LayoutError, AllocError},
@@ -101,8 +103,23 @@ pub struct Error(NonZeroI32); · 92 unmodified lines
101impl Error {103impl Error {
102 /// Creates an [`Error`] from a kernel error code.104 /// Creates an [`Error`] from a kernel error code.
103 ///105 ///
104 /// It is a bug to pass an out-of-range `errno`. `EINVAL` would106 /// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`).
105 /// be returned in such a case.107 ///
108 /// It is a bug to pass an out-of-range `errno`. [`code::EINVAL`] is returned in such a case.
109 ///
110 /// # Examples
111 ///
112 /// ```
113 /// assert_eq!(Error::from_errno(-1), EPERM);
114 /// assert_eq!(Error::from_errno(-2), ENOENT);
115 /// ```
116 ///
117 /// The following calls are considered a bug:
118 ///
119 /// ```
120 /// assert_eq!(Error::from_errno(0), EINVAL);
121 /// assert_eq!(Error::from_errno(-1000000), EINVAL);
122 /// ```
106 pub fn from_errno(errno: crate::ffi::c_int) -> Error {123 pub fn from_errno(errno: crate::ffi::c_int) -> Error {
107 if let Some(error) = Self::try_from_errno(errno) {124 if let Some(error) = Self::try_from_errno(errno) {
108 error125 error
@@ -158,7 +175,7 @@ impl Error { · 49 unmodified lines
158 }175 }
159 176
160 /// Returns a string representing the error, if one exists.177 /// Returns a string representing the error, if one exists.
161 #[cfg(not(any(test, testlib)))]178 #[cfg(not(testlib))]
162 pub fn name(&self) -> Option<&'static CStr> {179 pub fn name(&self) -> Option<&'static CStr> {
163 // SAFETY: Just an FFI call, there are no extra safety requirements.180 // SAFETY: Just an FFI call, there are no extra safety requirements.
164 let ptr = unsafe { bindings::errname(-self.0.get()) };181 let ptr = unsafe { bindings::errname(-self.0.get()) };
@@ -175,7 +192,7 @@ impl Error { · 10 unmodified lines
175 /// When `testlib` is configured, this always returns `None` to avoid the dependency on a192 /// When `testlib` is configured, this always returns `None` to avoid the dependency on a
176 /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still193 /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still
177 /// run in userspace.194 /// run in userspace.
178 #[cfg(any(test, testlib))]195 #[cfg(testlib)]
179 pub fn name(&self) -> Option<&'static CStr> {196 pub fn name(&self) -> Option<&'static CStr> {
180 None197 None
181 }198 }
@@ -375,8 +392,43 @@ impl From<core::convert::Infallible> for Error { · 193 unmodified lines
375/// [Rust documentation]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html392/// [Rust documentation]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html
376pub type Result<T = (), E = Error> = core::result::Result<T, E>;393pub type Result<T = (), E = Error> = core::result::Result<T, E>;
377 394
378/// Converts an integer as returned by a C kernel function to an error if it's negative, and395/// Converts an integer as returned by a C kernel function to a [`Result`].
379/// `Ok(())` otherwise.396///
397/// If the integer is negative, an [`Err`] with an [`Error`] as given by [`Error::from_errno`] is
398/// returned. This means the integer must be `>= -MAX_ERRNO`.
399///
400/// Otherwise, it returns [`Ok`].
401///
402/// It is a bug to pass an out-of-range negative integer. `Err(EINVAL)` is returned in such a case.
403///
404/// # Examples
405///
406/// This function may be used to easily perform early returns with the [`?`] operator when working
407/// with C APIs within Rust abstractions:
408///
409/// ```
410/// # use kernel::error::to_result;
411/// # mod bindings {
412/// # #![expect(clippy::missing_safety_doc)]
413/// # use kernel::prelude::*;
414/// # pub(super) unsafe fn f1() -> c_int { 0 }
415/// # pub(super) unsafe fn f2() -> c_int { EINVAL.to_errno() }
416/// # }
417/// fn f() -> Result {
418/// // SAFETY: ...
419/// to_result(unsafe { bindings::f1() })?;
420///
421/// // SAFETY: ...
422/// to_result(unsafe { bindings::f2() })?;
423///
424/// // ...
425///
426/// Ok(())
427/// }
428/// # assert_eq!(f(), Err(EINVAL));
429/// ```
430///
431/// [`?`]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator
380pub fn to_result(err: crate::ffi::c_int) -> Result {432pub fn to_result(err: crate::ffi::c_int) -> Result {
381 if err < 0 {433 if err < 0 {
382 Err(Error::from_errno(err))434 Err(Error::from_errno(err))
rust/kernel/firmware.rs+1−1
@@ -291,7 +291,7 @@ impl<const N: usize> ModInfoBuilder<N> { · 290 unmodified lines
291 let module_name = this.module_name;291 let module_name = this.module_name;
292 292
293 if !this.module_name.is_empty() {293 if !this.module_name.is_empty() {
294 this = this.push_internal(module_name.as_bytes_with_nul());294 this = this.push_internal(module_name.to_bytes_with_nul());
295 295
296 if N != 0 {296 if N != 0 {
297 // Re-use the space taken by the NULL terminator and swap it with the '.' separator.297 // Re-use the space taken by the NULL terminator and swap it with the '.' separator.
rust/kernel/fs/file.rs+3−2
@@ -11,6 +11,7 @@ use crate::{ · 10 unmodified lines
11 bindings,11 bindings,
12 cred::Credential,12 cred::Credential,
13 error::{code::*, to_result, Error, Result},13 error::{code::*, to_result, Error, Result},
14 fmt,
14 sync::aref::{ARef, AlwaysRefCounted},15 sync::aref::{ARef, AlwaysRefCounted},
15 types::{NotThreadSafe, Opaque},16 types::{NotThreadSafe, Opaque},
16};17};
@@ -460,8 +461,8 @@ impl From<BadFdError> for Error { · 443 unmodified lines
460 }461 }
461}462}
462 463
463impl core::fmt::Debug for BadFdError {464impl fmt::Debug for BadFdError {
464 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {465 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 f.pad("EBADF")466 f.pad("EBADF")
466 }467 }
467}468}
rust/kernel/kunit.rs+7−7
@@ -6,8 +6,8 @@ · 5 unmodified lines
6//!6//!
7//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>7//! Reference: <https://docs.kernel.org/dev-tools/kunit/index.html>
8 8
9use crate::fmt;
9use crate::prelude::*;10use crate::prelude::*;
10use core::fmt;
11 11
12#[cfg(CONFIG_PRINTK)]12#[cfg(CONFIG_PRINTK)]
13use crate::c_str;13use crate::c_str;
@@ -74,14 +74,14 @@ macro_rules! kunit_assert { · 60 unmodified lines
74 // mistake (it is hidden to prevent that).74 // mistake (it is hidden to prevent that).
75 //75 //
76 // This mimics KUnit's failed assertion format.76 // This mimics KUnit's failed assertion format.
77 $crate::kunit::err(format_args!(77 $crate::kunit::err($crate::prelude::fmt!(
78 " # {}: ASSERTION FAILED at {FILE}:{LINE}\n",78 " # {}: ASSERTION FAILED at {FILE}:{LINE}\n",
79 $name79 $name
80 ));80 ));
81 $crate::kunit::err(format_args!(81 $crate::kunit::err($crate::prelude::fmt!(
82 " Expected {CONDITION} to be true, but is false\n"82 " Expected {CONDITION} to be true, but is false\n"
83 ));83 ));
84 $crate::kunit::err(format_args!(84 $crate::kunit::err($crate::prelude::fmt!(
85 " Failure not reported to KUnit since this is a non-KUnit task\n"85 " Failure not reported to KUnit since this is a non-KUnit task\n"
86 ));86 ));
87 break 'out;87 break 'out;
@@ -102,12 +102,12 @@ macro_rules! kunit_assert { · 14 unmodified lines
102 unsafe impl Sync for UnaryAssert {}102 unsafe impl Sync for UnaryAssert {}
103 103
104 static LOCATION: Location = Location($crate::bindings::kunit_loc {104 static LOCATION: Location = Location($crate::bindings::kunit_loc {
105 file: FILE.as_char_ptr(),105 file: $crate::str::as_char_ptr_in_const_context(FILE),
106 line: LINE,106 line: LINE,
107 });107 });
108 static ASSERTION: UnaryAssert = UnaryAssert($crate::bindings::kunit_unary_assert {108 static ASSERTION: UnaryAssert = UnaryAssert($crate::bindings::kunit_unary_assert {
109 assert: $crate::bindings::kunit_assert {},109 assert: $crate::bindings::kunit_assert {},
110 condition: CONDITION.as_char_ptr(),110 condition: $crate::str::as_char_ptr_in_const_context(CONDITION),
111 expected_true: true,111 expected_true: true,
112 });112 });
113 113
@@ -202,7 +202,7 @@ pub const fn kunit_case( · 88 unmodified lines
202) -> kernel::bindings::kunit_case {202) -> kernel::bindings::kunit_case {
203 kernel::bindings::kunit_case {203 kernel::bindings::kunit_case {
204 run_case: Some(run_case),204 run_case: Some(run_case),
205 name: name.as_char_ptr(),205 name: kernel::str::as_char_ptr_in_const_context(name),
206 attr: kernel::bindings::kunit_attributes {206 attr: kernel::bindings::kunit_attributes {
207 speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,207 speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
208 },208 },
rust/kernel/lib.rs+4−1
@@ -17,6 +17,7 @@ · 16 unmodified lines
17// the unstable features in use.17// the unstable features in use.
18//18//
19// Stable since Rust 1.79.0.19// Stable since Rust 1.79.0.
20#![feature(generic_nonzero)]
20#![feature(inline_const)]21#![feature(inline_const)]
21//22//
22// Stable since Rust 1.81.0.23// Stable since Rust 1.81.0.
@@ -28,6 +29,7 @@ · 5 unmodified lines
28// Stable since Rust 1.83.0.29// Stable since Rust 1.83.0.
29#![feature(const_maybe_uninit_as_mut_ptr)]30#![feature(const_maybe_uninit_as_mut_ptr)]
30#![feature(const_mut_refs)]31#![feature(const_mut_refs)]
32#![feature(const_option)]
31#![feature(const_ptr_write)]33#![feature(const_ptr_write)]
32#![feature(const_refs_to_cell)]34#![feature(const_refs_to_cell)]
33//35//
@@ -110,6 +112,7 @@ pub mod pid_namespace; · 76 unmodified lines
110pub mod platform;112pub mod platform;
111pub mod prelude;113pub mod prelude;
112pub mod print;114pub mod print;
115pub mod ptr;
113pub mod rbtree;116pub mod rbtree;
114pub mod regulator;117pub mod regulator;
115pub mod revocable;118pub mod revocable;
@@ -206,7 +209,7 @@ impl ThisModule { · 90 unmodified lines
206 }209 }
207}210}
208 211
209#[cfg(not(any(testlib, test)))]212#[cfg(not(testlib))]
210#[panic_handler]213#[panic_handler]
211fn panic(info: &core::panic::PanicInfo<'_>) -> ! {214fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
212 pr_emerg!("{}\n", info);215 pr_emerg!("{}\n", info);
rust/kernel/list.rs+120−0
@@ -38,6 +38,8 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField}; · 37 unmodified lines
38///38///
39/// # Examples39/// # Examples
40///40///
41/// Use [`ListLinks`] as the type of the intrusive field.
42///
41/// ```43/// ```
42/// use kernel::list::*;44/// use kernel::list::*;
43///45///
@@ -140,6 +142,124 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField}; · 96 unmodified lines
140/// }142/// }
141/// # Result::<(), Error>::Ok(())143/// # Result::<(), Error>::Ok(())
142/// ```144/// ```
145///
146/// Use [`ListLinksSelfPtr`] as the type of the intrusive field. This allows a list of trait object
147/// type.
148///
149/// ```
150/// use kernel::list::*;
151///
152/// trait Foo {
153/// fn foo(&self) -> (&'static str, i32);
154/// }
155///
156/// #[pin_data]
157/// struct DTWrap<T: ?Sized> {
158/// #[pin]
159/// links: ListLinksSelfPtr<DTWrap<dyn Foo>>,
160/// value: T,
161/// }
162///
163/// impl<T> DTWrap<T> {
164/// fn new(value: T) -> Result<ListArc<Self>> {
165/// ListArc::pin_init(try_pin_init!(Self {
166/// value,
167/// links <- ListLinksSelfPtr::new(),
168/// }), GFP_KERNEL)
169/// }
170/// }
171///
172/// impl_list_arc_safe! {
173/// impl{T: ?Sized} ListArcSafe<0> for DTWrap<T> { untracked; }
174/// }
175/// impl_list_item! {
176/// impl ListItem<0> for DTWrap<dyn Foo> { using ListLinksSelfPtr { self.links }; }
177/// }
178///
179/// // Create a new empty list.
180/// let mut list = List::<DTWrap<dyn Foo>>::new();
181/// {
182/// assert!(list.is_empty());
183/// }
184///
185/// struct A(i32);
186/// // `A` returns the inner value for `foo`.
187/// impl Foo for A { fn foo(&self) -> (&'static str, i32) { ("a", self.0) } }
188///
189/// struct B;
190/// // `B` always returns 42.
191/// impl Foo for B { fn foo(&self) -> (&'static str, i32) { ("b", 42) } }
192///
193/// // Insert 3 element using `push_back()`.
194/// list.push_back(DTWrap::new(A(15))?);
195/// list.push_back(DTWrap::new(A(32))?);
196/// list.push_back(DTWrap::new(B)?);
197///
198/// // Iterate over the list to verify the nodes were inserted correctly.
199/// // [A(15), A(32), B]
200/// {
201/// let mut iter = list.iter();
202/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 15));
203/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 32));
204/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42));
205/// assert!(iter.next().is_none());
206///
207/// // Verify the length of the list.
208/// assert_eq!(list.iter().count(), 3);
209/// }
210///
211/// // Pop the items from the list using `pop_back()` and verify the content.
212/// {
213/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("b", 42));
214/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32));
215/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15));
216/// }
217///
218/// // Insert 3 elements using `push_front()`.
219/// list.push_front(DTWrap::new(A(15))?);
220/// list.push_front(DTWrap::new(A(32))?);
221/// list.push_front(DTWrap::new(B)?);
222///
223/// // Iterate over the list to verify the nodes were inserted correctly.
224/// // [B, A(32), A(15)]
225/// {
226/// let mut iter = list.iter();
227/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42));
228/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 32));
229/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 15));
230/// assert!(iter.next().is_none());
231///
232/// // Verify the length of the list.
233/// assert_eq!(list.iter().count(), 3);
234/// }
235///
236/// // Pop the items from the list using `pop_front()` and verify the content.
237/// {
238/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15));
239/// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32));
240/// }
241///
242/// // Push `list2` to `list` through `push_all_back()`.
243/// // list: [B]
244/// // list2: [B, A(25)]
245/// {
246/// let mut list2 = List::<DTWrap<dyn Foo>>::new();
247/// list2.push_back(DTWrap::new(B)?);
248/// list2.push_back(DTWrap::new(A(25))?);
249///
250/// list.push_all_back(&mut list2);
251///
252/// // list: [B, B, A(25)]
253/// // list2: []
254/// let mut iter = list.iter();
255/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42));
256/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42));
257/// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 25));
258/// assert!(iter.next().is_none());
259/// assert!(list2.is_empty());
260/// }
261/// # Result::<(), Error>::Ok(())
262/// ```
143pub struct List<T: ?Sized + ListItem<ID>, const ID: u64 = 0> {263pub struct List<T: ?Sized + ListItem<ID>, const ID: u64 = 0> {
144 first: *mut ListLinksFields,264 first: *mut ListLinksFields,
145 _ty: PhantomData<ListArc<T, ID>>,265 _ty: PhantomData<ListArc<T, ID>>,
rust/kernel/miscdevice.rs+1−1
@@ -34,7 +34,7 @@ impl MiscDeviceOptions { · 33 unmodified lines
34 // SAFETY: All zeros is valid for this C type.34 // SAFETY: All zeros is valid for this C type.
35 let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };35 let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };
36 result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int;36 result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int;
37 result.name = self.name.as_char_ptr();37 result.name = crate::str::as_char_ptr_in_const_context(self.name);
38 result.fops = MiscdeviceVTable::<T>::build();38 result.fops = MiscdeviceVTable::<T>::build();
39 result39 result
40 }40 }
rust/kernel/net/phy.rs+1−1
@@ -497,7 +497,7 @@ unsafe impl Sync for DriverVTable {} · 496 unmodified lines
497pub const fn create_phy_driver<T: Driver>() -> DriverVTable {497pub const fn create_phy_driver<T: Driver>() -> DriverVTable {
498 // INVARIANT: All the fields of `struct phy_driver` are initialized properly.498 // INVARIANT: All the fields of `struct phy_driver` are initialized properly.
499 DriverVTable(Opaque::new(bindings::phy_driver {499 DriverVTable(Opaque::new(bindings::phy_driver {
500 name: T::NAME.as_char_ptr().cast_mut(),500 name: crate::str::as_char_ptr_in_const_context(T::NAME).cast_mut(),
501 flags: T::FLAGS,501 flags: T::FLAGS,
502 phy_id: T::PHY_DEVICE_ID.id(),502 phy_id: T::PHY_DEVICE_ID.id(),
503 phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(),503 phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(),
rust/kernel/of.rs+1−1
@@ -34,7 +34,7 @@ unsafe impl RawDeviceIdIndex for DeviceId { · 33 unmodified lines
34impl DeviceId {34impl DeviceId {
35 /// Create a new device id from an OF 'compatible' string.35 /// Create a new device id from an OF 'compatible' string.
36 pub const fn new(compatible: &'static CStr) -> Self {36 pub const fn new(compatible: &'static CStr) -> Self {
37 let src = compatible.as_bytes_with_nul();37 let src = compatible.to_bytes_with_nul();
38 // Replace with `bindings::of_device_id::default()` once stabilized for `const`.38 // Replace with `bindings::of_device_id::default()` once stabilized for `const`.
39 // SAFETY: FFI type is valid to be zero-initialized.39 // SAFETY: FFI type is valid to be zero-initialized.
40 let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() };40 let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() };
rust/kernel/prelude.rs+4−1
@@ -12,7 +12,10 @@ · 11 unmodified lines
12//! ```12//! ```
13 13
14#[doc(no_inline)]14#[doc(no_inline)]
15pub use core::pin::Pin;15pub use core::{
16 mem::{align_of, align_of_val, size_of, size_of_val},
17 pin::Pin,
18};
16 19
17pub use ::ffi::{20pub use ::ffi::{
18 c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,21 c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,
rust/kernel/ptr.rs+228−0
@@ -0,0 +1,228 @@
1// SPDX-License-Identifier: GPL-2.0
2
3//! Types and functions to work with pointers and addresses.
4
5use core::fmt::Debug;
6use core::mem::align_of;
7use core::num::NonZero;
8
9use crate::build_assert;
10
11/// Type representing an alignment, which is always a power of two.
12///
13/// It is used to validate that a given value is a valid alignment, and to perform masking and
14/// alignment operations.
15///
16/// This is a temporary substitute for the [`Alignment`] nightly type from the standard library,
17/// and to be eventually replaced by it.
18///
19/// [`Alignment`]: https://github.com/rust-lang/rust/issues/102070
20///
21/// # Invariants
22///
23/// An alignment is always a power of two.
24#[repr(transparent)]
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
26pub struct Alignment(NonZero<usize>);
27
28impl Alignment {
29 /// Validates that `ALIGN` is a power of two at build-time, and returns an [`Alignment`] of the
30 /// same value.
31 ///
32 /// A build error is triggered if `ALIGN` is not a power of two.
33 ///
34 /// # Examples
35 ///
36 /// ```
37 /// use kernel::ptr::Alignment;
38 ///
39 /// let v = Alignment::new::<16>();
40 /// assert_eq!(v.as_usize(), 16);
41 /// ```
42 #[inline(always)]
43 pub const fn new<const ALIGN: usize>() -> Self {
44 build_assert!(
45 ALIGN.is_power_of_two(),
46 "Provided alignment is not a power of two."
47 );
48
49 // INVARIANT: `align` is a power of two.
50 // SAFETY: `align` is a power of two, and thus non-zero.
51 Self(unsafe { NonZero::new_unchecked(ALIGN) })
52 }
53
54 /// Validates that `align` is a power of two at runtime, and returns an
55 /// [`Alignment`] of the same value.
56 ///
57 /// Returns [`None`] if `align` is not a power of two.
58 ///
59 /// # Examples
60 ///
61 /// ```
62 /// use kernel::ptr::Alignment;
63 ///
64 /// assert_eq!(Alignment::new_checked(16), Some(Alignment::new::<16>()));
65 /// assert_eq!(Alignment::new_checked(15), None);
66 /// assert_eq!(Alignment::new_checked(1), Some(Alignment::new::<1>()));
67 /// assert_eq!(Alignment::new_checked(0), None);
68 /// ```
69 #[inline(always)]
70 pub const fn new_checked(align: usize) -> Option<Self> {
71 if align.is_power_of_two() {
72 // INVARIANT: `align` is a power of two.
73 // SAFETY: `align` is a power of two, and thus non-zero.
74 Some(Self(unsafe { NonZero::new_unchecked(align) }))
75 } else {
76 None
77 }
78 }
79
80 /// Returns the alignment of `T`.
81 ///
82 /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
83 #[inline(always)]
84 pub const fn of<T>() -> Self {
85 #![allow(clippy::incompatible_msrv)]
86 // This cannot panic since alignments are always powers of two.
87 //
88 // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature.
89 const { Alignment::new_checked(align_of::<T>()).unwrap() }
90 }
91
92 /// Returns this alignment as a [`usize`].
93 ///
94 /// It is guaranteed to be a power of two.
95 ///
96 /// # Examples
97 ///
98 /// ```
99 /// use kernel::ptr::Alignment;
100 ///
101 /// assert_eq!(Alignment::new::<16>().as_usize(), 16);
102 /// ```
103 #[inline(always)]
104 pub const fn as_usize(self) -> usize {
105 self.as_nonzero().get()
106 }
107
108 /// Returns this alignment as a [`NonZero`].
109 ///
110 /// It is guaranteed to be a power of two.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use kernel::ptr::Alignment;
116 ///
117 /// assert_eq!(Alignment::new::<16>().as_nonzero().get(), 16);
118 /// ```
119 #[inline(always)]
120 pub const fn as_nonzero(self) -> NonZero<usize> {
121 // Allow the compiler to know that the value is indeed a power of two. This can help
122 // optimize some operations down the line, like e.g. replacing divisions by bit shifts.
123 if !self.0.is_power_of_two() {
124 // SAFETY: Per the invariants, `self.0` is always a power of two so this block will
125 // never be reached.
126 unsafe { core::hint::unreachable_unchecked() }
127 }
128 self.0
129 }
130
131 /// Returns the base-2 logarithm of the alignment.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use kernel::ptr::Alignment;
137 ///
138 /// assert_eq!(Alignment::of::<u8>().log2(), 0);
139 /// assert_eq!(Alignment::new::<16>().log2(), 4);
140 /// ```
141 #[inline(always)]
142 pub const fn log2(self) -> u32 {
143 self.0.ilog2()
144 }
145
146 /// Returns the mask for this alignment.
147 ///
148 /// This is equivalent to `!(self.as_usize() - 1)`.
149 ///
150 /// # Examples
151 ///
152 /// ```
153 /// use kernel::ptr::Alignment;
154 ///
155 /// assert_eq!(Alignment::new::<0x10>().mask(), !0xf);
156 /// ```
157 #[inline(always)]
158 pub const fn mask(self) -> usize {
159 // No underflow can occur as the alignment is guaranteed to be a power of two, and thus is
160 // non-zero.
161 !(self.as_usize() - 1)
162 }
163}
164
165/// Trait for items that can be aligned against an [`Alignment`].
166pub trait Alignable: Sized {
167 /// Aligns `self` down to `alignment`.
168 ///
169 /// # Examples
170 ///
171 /// ```
172 /// use kernel::ptr::{Alignable, Alignment};
173 ///
174 /// assert_eq!(0x2f_usize.align_down(Alignment::new::<0x10>()), 0x20);
175 /// assert_eq!(0x30usize.align_down(Alignment::new::<0x10>()), 0x30);
176 /// assert_eq!(0xf0u8.align_down(Alignment::new::<0x1000>()), 0x0);
177 /// ```
178 fn align_down(self, alignment: Alignment) -> Self;
179
180 /// Aligns `self` up to `alignment`, returning `None` if aligning would result in an overflow.
181 ///
182 /// # Examples
183 ///
184 /// ```
185 /// use kernel::ptr::{Alignable, Alignment};
186 ///
187 /// assert_eq!(0x4fusize.align_up(Alignment::new::<0x10>()), Some(0x50));
188 /// assert_eq!(0x40usize.align_up(Alignment::new::<0x10>()), Some(0x40));
189 /// assert_eq!(0x0usize.align_up(Alignment::new::<0x10>()), Some(0x0));
190 /// assert_eq!(u8::MAX.align_up(Alignment::new::<0x10>()), None);
191 /// assert_eq!(0x10u8.align_up(Alignment::new::<0x100>()), None);
192 /// assert_eq!(0x0u8.align_up(Alignment::new::<0x100>()), Some(0x0));
193 /// ```
194 fn align_up(self, alignment: Alignment) -> Option<Self>;
195}
196
197/// Implement [`Alignable`] for unsigned integer types.
198macro_rules! impl_alignable_uint {
199 ($($t:ty),*) => {
200 $(
201 impl Alignable for $t {
202 #[inline(always)]
203 fn align_down(self, alignment: Alignment) -> Self {
204 // The operands of `&` need to be of the same type so convert the alignment to
205 // `Self`. This means we need to compute the mask ourselves.
206 ::core::num::NonZero::<Self>::try_from(alignment.as_nonzero())
207 .map(|align| self & !(align.get() - 1))
208 // An alignment larger than `Self` always aligns down to `0`.
209 .unwrap_or(0)
210 }
211
212 #[inline(always)]
213 fn align_up(self, alignment: Alignment) -> Option<Self> {
214 let aligned_down = self.align_down(alignment);
215 if self == aligned_down {
216 Some(aligned_down)
217 } else {
218 Self::try_from(alignment.as_usize())
219 .ok()
220 .and_then(|align| aligned_down.checked_add(align))
221 }
222 }
223 }
224 )*
225 };
226}
227
228impl_alignable_uint!(u8, u16, u32, u64, usize);
rust/kernel/seq_file.rs+3−3
@@ -4,7 +4,7 @@ · 3 unmodified lines
4//!4//!
5//! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.h)5//! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.h)
6 6
7use crate::{bindings, c_str, types::NotThreadSafe, types::Opaque};7use crate::{bindings, c_str, fmt, types::NotThreadSafe, types::Opaque};
8 8
9/// A utility for generating the contents of a seq file.9/// A utility for generating the contents of a seq file.
10#[repr(transparent)]10#[repr(transparent)]
@@ -31,7 +31,7 @@ impl SeqFile { · 20 unmodified lines
31 31
32 /// Used by the [`seq_print`] macro.32 /// Used by the [`seq_print`] macro.
33 #[inline]33 #[inline]
34 pub fn call_printf(&self, args: core::fmt::Arguments<'_>) {34 pub fn call_printf(&self, args: fmt::Arguments<'_>) {
35 // SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`.35 // SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`.
36 unsafe {36 unsafe {
37 bindings::seq_printf(37 bindings::seq_printf(
@@ -47,7 +47,7 @@ impl SeqFile { · 9 unmodified lines
47#[macro_export]47#[macro_export]
48macro_rules! seq_print {48macro_rules! seq_print {
49 ($m:expr, $($arg:tt)+) => (49 ($m:expr, $($arg:tt)+) => (
50 $m.call_printf(format_args!($($arg)+))50 $m.call_printf($crate::prelude::fmt!($($arg)+))
51 );51 );
52}52}
53pub use seq_print;53pub use seq_print;
rust/kernel/sync/arc.rs+4−4
@@ -19,6 +19,7 @@ · 18 unmodified lines
19use crate::{19use crate::{
20 alloc::{AllocError, Flags, KBox},20 alloc::{AllocError, Flags, KBox},
21 ffi::c_void,21 ffi::c_void,
22 fmt,
22 init::InPlaceInit,23 init::InPlaceInit,
23 sync::Refcount,24 sync::Refcount,
24 try_init,25 try_init,
@@ -27,7 +28,6 @@ use crate::{ · 2 unmodified lines
27use core::{28use core::{
28 alloc::Layout,29 alloc::Layout,
29 borrow::{Borrow, BorrowMut},30 borrow::{Borrow, BorrowMut},
30 fmt,
31 marker::PhantomData,31 marker::PhantomData,
32 mem::{ManuallyDrop, MaybeUninit},32 mem::{ManuallyDrop, MaybeUninit},
33 ops::{Deref, DerefMut},33 ops::{Deref, DerefMut},
@@ -367,10 +367,10 @@ impl<T: ?Sized> Arc<T> { · 333 unmodified lines
367 }367 }
368}368}
369 369
370// SAFETY: The pointer returned by `into_foreign` comes from a well aligned370// SAFETY: The pointer returned by `into_foreign` was originally allocated as an
371// pointer to `ArcInner<T>`.371// `KBox<ArcInner<T>>`, so that type is what determines the alignment.
372unsafe impl<T: 'static> ForeignOwnable for Arc<T> {372unsafe impl<T: 'static> ForeignOwnable for Arc<T> {
373 const FOREIGN_ALIGN: usize = core::mem::align_of::<ArcInner<T>>();373 const FOREIGN_ALIGN: usize = <KBox<ArcInner<T>> as ForeignOwnable>::FOREIGN_ALIGN;
374 374
375 type Borrowed<'a> = ArcBorrow<'a, T>;375 type Borrowed<'a> = ArcBorrow<'a, T>;
376 type BorrowedMut<'a> = Self::Borrowed<'a>;376 type BorrowedMut<'a> = Self::Borrowed<'a>;
rust/kernel/sync/aref.rs+16−1
@@ -1,6 +1,21 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2 2
3//! Internal reference counting support.3//! Internal reference counting support.
4//!
5//! Many C types already have their own reference counting mechanism (e.g. by storing a
6//! `refcount_t`). This module provides support for directly using their internal reference count
7//! from Rust; instead of making users have to use an additional Rust-reference count in the form of
8//! [`Arc`].
9//!
10//! The smart pointer [`ARef<T>`] acts similarly to [`Arc<T>`] in that it holds a refcount on the
11//! underlying object, but this refcount is internal to the object. It essentially is a Rust
12//! implementation of the `get_` and `put_` pattern used in C for reference counting.
13//!
14//! To make use of [`ARef<MyType>`], `MyType` needs to implement [`AlwaysRefCounted`]. It is a trait
15//! for accessing the internal reference count of an object of the `MyType` type.
16//!
17//! [`Arc`]: crate::sync::Arc
18//! [`Arc<T>`]: crate::sync::Arc
4 19
5use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};20use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
6 21
@@ -97,7 +112,7 @@ impl<T: AlwaysRefCounted> ARef<T> { · 90 unmodified lines
97 ///112 ///
98 /// ```113 /// ```
99 /// use core::ptr::NonNull;114 /// use core::ptr::NonNull;
100 /// use kernel::types::{ARef, AlwaysRefCounted};115 /// use kernel::sync::aref::{ARef, AlwaysRefCounted};
101 ///116 ///
102 /// struct Empty {}117 /// struct Empty {}
103 ///118 ///
rust/kernel/task.rs+4−3
@@ -9,7 +9,8 @@ use crate::{ · 8 unmodified lines
9 ffi::{c_int, c_long, c_uint},9 ffi::{c_int, c_long, c_uint},
10 mm::MmWithUser,10 mm::MmWithUser,
11 pid_namespace::PidNamespace,11 pid_namespace::PidNamespace,
12 types::{ARef, NotThreadSafe, Opaque},12 sync::aref::ARef,
13 types::{NotThreadSafe, Opaque},
13};14};
14use core::{15use core::{
15 cmp::{Eq, PartialEq},16 cmp::{Eq, PartialEq},
@@ -76,7 +77,7 @@ macro_rules! current { · 60 unmodified lines
76/// incremented when creating `State` and decremented when it is dropped:77/// incremented when creating `State` and decremented when it is dropped:
77///78///
78/// ```79/// ```
79/// use kernel::{task::Task, types::ARef};80/// use kernel::{task::Task, sync::aref::ARef};
80///81///
81/// struct State {82/// struct State {
82/// creator: ARef<Task>,83/// creator: ARef<Task>,
@@ -347,7 +348,7 @@ impl CurrentTask { · 264 unmodified lines
347}348}
348 349
349// SAFETY: The type invariants guarantee that `Task` is always refcounted.350// SAFETY: The type invariants guarantee that `Task` is always refcounted.
350unsafe impl crate::types::AlwaysRefCounted for Task {351unsafe impl crate::sync::aref::AlwaysRefCounted for Task {
351 #[inline]352 #[inline]
352 fn inc_ref(&self) {353 fn inc_ref(&self) {
353 // SAFETY: The existence of a shared reference means that the refcount is nonzero.354 // SAFETY: The existence of a shared reference means that the refcount is nonzero.
rust/kernel/time.rs+162−1
@@ -25,6 +25,7 @@ · 24 unmodified lines
25//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).25//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
26 26
27use core::marker::PhantomData;27use core::marker::PhantomData;
28use core::ops;
28 29
29pub mod delay;30pub mod delay;
30pub mod hrtimer;31pub mod hrtimer;
@@ -200,9 +201,31 @@ impl<C: ClockSource> Instant<C> { · 169 unmodified lines
200 pub(crate) fn as_nanos(&self) -> i64 {201 pub(crate) fn as_nanos(&self) -> i64 {
201 self.inner202 self.inner
202 }203 }
204
205 /// Create an [`Instant`] from a `ktime_t` without checking if it is non-negative.
206 ///
207 /// # Panics
208 ///
209 /// On debug builds, this function will panic if `ktime` is not in the range from 0 to
210 /// `KTIME_MAX`.
211 ///
212 /// # Safety
213 ///
214 /// The caller promises that `ktime` is in the range from 0 to `KTIME_MAX`.
215 #[inline]
216 pub(crate) unsafe fn from_ktime(ktime: bindings::ktime_t) -> Self {
217 debug_assert!(ktime >= 0);
218
219 // INVARIANT: Our safety contract ensures that `ktime` is in the range from 0 to
220 // `KTIME_MAX`.
221 Self {
222 inner: ktime,
223 _c: PhantomData,
224 }
225 }
203}226}
204 227
205impl<C: ClockSource> core::ops::Sub for Instant<C> {228impl<C: ClockSource> ops::Sub for Instant<C> {
206 type Output = Delta;229 type Output = Delta;
207 230
208 // By the type invariant, it never overflows.231 // By the type invariant, it never overflows.
@@ -214,6 +237,46 @@ impl<C: ClockSource> core::ops::Sub for Instant<C> { · 5 unmodified lines
214 }237 }
215}238}
216 239
240impl<T: ClockSource> ops::Add<Delta> for Instant<T> {
241 type Output = Self;
242
243 #[inline]
244 fn add(self, rhs: Delta) -> Self::Output {
245 // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow
246 // (e.g. go above `KTIME_MAX`)
247 let res = self.inner + rhs.nanos;
248
249 // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0
250 #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]
251 assert!(res >= 0);
252
253 Self {
254 inner: res,
255 _c: PhantomData,
256 }
257 }
258}
259
260impl<T: ClockSource> ops::Sub<Delta> for Instant<T> {
261 type Output = Self;
262
263 #[inline]
264 fn sub(self, rhs: Delta) -> Self::Output {
265 // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow
266 // (e.g. go above `KTIME_MAX`)
267 let res = self.inner - rhs.nanos;
268
269 // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0
270 #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]
271 assert!(res >= 0);
272
273 Self {
274 inner: res,
275 _c: PhantomData,
276 }
277 }
278}
279
217/// A span of time.280/// A span of time.
218///281///
219/// This struct represents a span of time, with its value stored as nanoseconds.282/// This struct represents a span of time, with its value stored as nanoseconds.
@@ -224,6 +287,78 @@ pub struct Delta { · 4 unmodified lines
224 nanos: i64,287 nanos: i64,
225}288}
226 289
290impl ops::Add for Delta {
291 type Output = Self;
292
293 #[inline]
294 fn add(self, rhs: Self) -> Self {
295 Self {
296 nanos: self.nanos + rhs.nanos,
297 }
298 }
299}
300
301impl ops::AddAssign for Delta {
302 #[inline]
303 fn add_assign(&mut self, rhs: Self) {
304 self.nanos += rhs.nanos;
305 }
306}
307
308impl ops::Sub for Delta {
309 type Output = Self;
310
311 #[inline]
312 fn sub(self, rhs: Self) -> Self::Output {
313 Self {
314 nanos: self.nanos - rhs.nanos,
315 }
316 }
317}
318
319impl ops::SubAssign for Delta {
320 #[inline]
321 fn sub_assign(&mut self, rhs: Self) {
322 self.nanos -= rhs.nanos;
323 }
324}
325
326impl ops::Mul<i64> for Delta {
327 type Output = Self;
328
329 #[inline]
330 fn mul(self, rhs: i64) -> Self::Output {
331 Self {
332 nanos: self.nanos * rhs,
333 }
334 }
335}
336
337impl ops::MulAssign<i64> for Delta {
338 #[inline]
339 fn mul_assign(&mut self, rhs: i64) {
340 self.nanos *= rhs;
341 }
342}
343
344impl ops::Div for Delta {
345 type Output = i64;
346
347 #[inline]
348 fn div(self, rhs: Self) -> Self::Output {
349 #[cfg(CONFIG_64BIT)]
350 {
351 self.nanos / rhs.nanos
352 }
353
354 #[cfg(not(CONFIG_64BIT))]
355 {
356 // SAFETY: This function is always safe to call regardless of the input values
357 unsafe { bindings::div64_s64(self.nanos, rhs.nanos) }
358 }
359 }
360}
361
227impl Delta {362impl Delta {
228 /// A span of time equal to zero.363 /// A span of time equal to zero.
229 pub const ZERO: Self = Self { nanos: 0 };364 pub const ZERO: Self = Self { nanos: 0 };
@@ -312,4 +447,30 @@ impl Delta { · 82 unmodified lines
312 bindings::ktime_to_ms(self.as_nanos())447 bindings::ktime_to_ms(self.as_nanos())
313 }448 }
314 }449 }
450
451 /// Return `self % dividend` where `dividend` is in nanoseconds.
452 ///
453 /// The kernel doesn't have any emulation for `s64 % s64` on 32 bit platforms, so this is
454 /// limited to 32 bit dividends.
455 #[inline]
456 pub fn rem_nanos(self, dividend: i32) -> Self {
457 #[cfg(CONFIG_64BIT)]
458 {
459 Self {
460 nanos: self.as_nanos() % i64::from(dividend),
461 }
462 }
463
464 #[cfg(not(CONFIG_64BIT))]
465 {
466 let mut rem = 0;
467
468 // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it.
469 unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) };
470
471 Self {
472 nanos: i64::from(rem),
473 }
474 }
475 }
315}476}
rust/kernel/time/hrtimer.rs+149−3
@@ -69,9 +69,14 @@ · 68 unmodified lines
69 69
70use super::{ClockSource, Delta, Instant};70use super::{ClockSource, Delta, Instant};
71use crate::{prelude::*, types::Opaque};71use crate::{prelude::*, types::Opaque};
72use core::marker::PhantomData;72use core::{marker::PhantomData, ptr::NonNull};
73use pin_init::PinInit;73use pin_init::PinInit;
74 74
75/// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`].
76///
77/// Where `C` is the [`ClockSource`] of the [`HrTimer`].
78pub type HrTimerInstant<T> = Instant<<<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock>;
79
75/// A timer backed by a C `struct hrtimer`.80/// A timer backed by a C `struct hrtimer`.
76///81///
77/// # Invariants82/// # Invariants
@@ -163,6 +168,84 @@ impl<T> HrTimer<T> { · 85 unmodified lines
163 // handled on the C side.168 // handled on the C side.
164 unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }169 unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }
165 }170 }
171
172 /// Forward the timer expiry for a given timer pointer.
173 ///
174 /// # Safety
175 ///
176 /// - `self_ptr` must point to a valid `Self`.
177 /// - The caller must either have exclusive access to the data pointed at by `self_ptr`, or be
178 /// within the context of the timer callback.
179 #[inline]
180 unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Delta) -> u64
181 where
182 T: HasHrTimer<T>,
183 {
184 // SAFETY:
185 // * The C API requirements for this function are fulfilled by our safety contract.
186 // * `self_ptr` is guaranteed to point to a valid `Self` via our safety contract
187 unsafe {
188 bindings::hrtimer_forward(Self::raw_get(self_ptr), now.as_nanos(), interval.as_nanos())
189 }
190 }
191
192 /// Conditionally forward the timer.
193 ///
194 /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
195 /// expired at or before `now`, this function forwards the timer by `interval` until the timer
196 /// expires after `now` and then returns the number of times the timer was forwarded by
197 /// `interval`.
198 ///
199 /// This function is mainly useful for timer types which can provide exclusive access to the
200 /// timer when the timer is not running. For forwarding the timer from within the timer callback
201 /// context, see [`HrTimerCallbackContext::forward()`].
202 ///
203 /// Returns the number of overruns that occurred as a result of the timer expiry change.
204 pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) -> u64
205 where
206 T: HasHrTimer<T>,
207 {
208 // SAFETY: `raw_forward` does not move `Self`
209 let this = unsafe { self.get_unchecked_mut() };
210
211 // SAFETY: By existence of `Pin<&mut Self>`, the pointer passed to `raw_forward` points to a
212 // valid `Self` that we have exclusive access to.
213 unsafe { Self::raw_forward(this, now, interval) }
214 }
215
216 /// Conditionally forward the timer.
217 ///
218 /// This is a variant of [`forward()`](Self::forward) that uses an interval after the current
219 /// time of the base clock for the [`HrTimer`].
220 pub fn forward_now(self: Pin<&mut Self>, interval: Delta) -> u64
221 where
222 T: HasHrTimer<T>,
223 {
224 self.forward(HrTimerInstant::<T>::now(), interval)
225 }
226
227 /// Return the time expiry for this [`HrTimer`].
228 ///
229 /// This value should only be used as a snapshot, as the actual expiry time could change after
230 /// this function is called.
231 pub fn expires(&self) -> HrTimerInstant<T>
232 where
233 T: HasHrTimer<T>,
234 {
235 // SAFETY: `self` is an immutable reference and thus always points to a valid `HrTimer`.
236 let c_timer_ptr = unsafe { HrTimer::raw_get(self) };
237
238 // SAFETY:
239 // - Timers cannot have negative ktime_t values as their expiration time.
240 // - There's no actual locking here, a racy read is fine and expected
241 unsafe {
242 Instant::from_ktime(
243 // This `read_volatile` is intended to correspond to a READ_ONCE call.
244 // FIXME(read_once): Replace with `read_once` when available on the Rust side.
245 core::ptr::read_volatile(&raw const ((*c_timer_ptr).node.expires)),
246 )
247 }
248 }
166}249}
167 250
168/// Implemented by pointer types that point to structs that contain a [`HrTimer`].251/// Implemented by pointer types that point to structs that contain a [`HrTimer`].
@@ -300,9 +383,13 @@ pub trait HrTimerCallback { · 131 unmodified lines
300 type Pointer<'a>: RawHrTimerCallback;383 type Pointer<'a>: RawHrTimerCallback;
301 384
302 /// Called by the timer logic when the timer fires.385 /// Called by the timer logic when the timer fires.
303 fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart386 fn run(
387 this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>,
388 ctx: HrTimerCallbackContext<'_, Self>,
389 ) -> HrTimerRestart
304 where390 where
305 Self: Sized;391 Self: Sized,
392 Self: HasHrTimer<Self>;
306}393}
307 394
308/// A handle representing a potentially running timer.395/// A handle representing a potentially running timer.
@@ -324,6 +411,8 @@ pub unsafe trait HrTimerHandle { · 15 unmodified lines
324 /// Note that the timer might be started by a concurrent start operation. If411 /// Note that the timer might be started by a concurrent start operation. If
325 /// so, the timer might not be in the **stopped** state when this function412 /// so, the timer might not be in the **stopped** state when this function
326 /// returns.413 /// returns.
414 ///
415 /// Returns `true` if the timer was running.
327 fn cancel(&mut self) -> bool;416 fn cancel(&mut self) -> bool;
328}417}
329 418
@@ -585,6 +674,63 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> { · 255 unmodified lines
585 type Expires = Delta;674 type Expires = Delta;
586}675}
587 676
677/// Privileged smart-pointer for a [`HrTimer`] callback context.
678///
679/// Many [`HrTimer`] methods can only be called in two situations:
680///
681/// * When the caller has exclusive access to the `HrTimer` and the `HrTimer` is guaranteed not to
682/// be running.
683/// * From within the context of an `HrTimer`'s callback method.
684///
685/// This type provides access to said methods from within a timer callback context.
686///
687/// # Invariants
688///
689/// * The existence of this type means the caller is currently within the callback for an
690/// [`HrTimer`].
691/// * `self.0` always points to a live instance of [`HrTimer<T>`].
692pub struct HrTimerCallbackContext<'a, T: HasHrTimer<T>>(NonNull<HrTimer<T>>, PhantomData<&'a ()>);
693
694impl<'a, T: HasHrTimer<T>> HrTimerCallbackContext<'a, T> {
695 /// Create a new [`HrTimerCallbackContext`].
696 ///
697 /// # Safety
698 ///
699 /// This function relies on the caller being within the context of a timer callback, so it must
700 /// not be used anywhere except for within implementations of [`RawHrTimerCallback::run`]. The
701 /// caller promises that `timer` points to a valid initialized instance of
702 /// [`bindings::hrtimer`].
703 ///
704 /// The returned `Self` must not outlive the function context of [`RawHrTimerCallback::run`]
705 /// where this function is called.
706 pub(crate) unsafe fn from_raw(timer: *mut HrTimer<T>) -> Self {
707 // SAFETY: The caller guarantees `timer` is a valid pointer to an initialized
708 // `bindings::hrtimer`
709 // INVARIANT: Our safety contract ensures that we're within the context of a timer callback
710 // and that `timer` points to a live instance of `HrTimer<T>`.
711 Self(unsafe { NonNull::new_unchecked(timer) }, PhantomData)
712 }
713
714 /// Conditionally forward the timer.
715 ///
716 /// This function is identical to [`HrTimer::forward()`] except that it may only be used from
717 /// within the context of a [`HrTimer`] callback.
718 pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64 {
719 // SAFETY:
720 // - We are guaranteed to be within the context of a timer callback by our type invariants
721 // - By our type invariants, `self.0` always points to a valid `HrTimer<T>`
722 unsafe { HrTimer::<T>::raw_forward(self.0.as_ptr(), now, interval) }
723 }
724
725 /// Conditionally forward the timer.
726 ///
727 /// This is a variant of [`HrTimerCallbackContext::forward()`] that uses an interval after the
728 /// current time of the base clock for the [`HrTimer`].
729 pub fn forward_now(&mut self, duration: Delta) -> u64 {
730 self.forward(HrTimerInstant::<T>::now(), duration)
731 }
732}
733
588/// Use to implement the [`HasHrTimer<T>`] trait.734/// Use to implement the [`HasHrTimer<T>`] trait.
589///735///
590/// See [`module`] documentation for an example.736/// See [`module`] documentation for an example.
rust/kernel/time/hrtimer/arc.rs+8−1
@@ -3,6 +3,7 @@ · 2 unmodified lines
3use super::HasHrTimer;3use super::HasHrTimer;
4use super::HrTimer;4use super::HrTimer;
5use super::HrTimerCallback;5use super::HrTimerCallback;
6use super::HrTimerCallbackContext;
6use super::HrTimerHandle;7use super::HrTimerHandle;
7use super::HrTimerMode;8use super::HrTimerMode;
8use super::HrTimerPointer;9use super::HrTimerPointer;
@@ -99,6 +100,12 @@ where · 90 unmodified lines
99 // allocation from other `Arc` clones.100 // allocation from other `Arc` clones.
100 let receiver = unsafe { ArcBorrow::from_raw(data_ptr) };101 let receiver = unsafe { ArcBorrow::from_raw(data_ptr) };
101 102
102 T::run(receiver).into_c()103 // SAFETY:
104 // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
105 // it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
106 // - We are within `RawHrTimerCallback::run`
107 let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
108
109 T::run(receiver, context).into_c()
103 }110 }
104}111}
rust/kernel/time/hrtimer/pin.rs+8−1
@@ -3,6 +3,7 @@ · 2 unmodified lines
3use super::HasHrTimer;3use super::HasHrTimer;
4use super::HrTimer;4use super::HrTimer;
5use super::HrTimerCallback;5use super::HrTimerCallback;
6use super::HrTimerCallbackContext;
6use super::HrTimerHandle;7use super::HrTimerHandle;
7use super::HrTimerMode;8use super::HrTimerMode;
8use super::RawHrTimerCallback;9use super::RawHrTimerCallback;
@@ -103,6 +104,12 @@ where · 94 unmodified lines
103 // here.104 // here.
104 let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };105 let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };
105 106
106 T::run(receiver_pin).into_c()107 // SAFETY:
108 // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
109 // it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
110 // - We are within `RawHrTimerCallback::run`
111 let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
112
113 T::run(receiver_pin, context).into_c()
107 }114 }
108}115}
rust/kernel/time/hrtimer/pin_mut.rs+9−3
@@ -1,8 +1,8 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2 2
3use super::{3use super::{
4 HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, HrTimerMode, RawHrTimerCallback,4 HasHrTimer, HrTimer, HrTimerCallback, HrTimerCallbackContext, HrTimerHandle, HrTimerMode,
5 UnsafeHrTimerPointer,5 RawHrTimerCallback, UnsafeHrTimerPointer,
6};6};
7use core::{marker::PhantomData, pin::Pin, ptr::NonNull};7use core::{marker::PhantomData, pin::Pin, ptr::NonNull};
8 8
@@ -107,6 +107,12 @@ where · 98 unmodified lines
107 // here.107 // here.
108 let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };108 let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };
109 109
110 T::run(receiver_pin).into_c()110 // SAFETY:
111 // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
112 // it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
113 // - We are within `RawHrTimerCallback::run`
114 let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
115
116 T::run(receiver_pin, context).into_c()
111 }117 }
112}118}
rust/kernel/time/hrtimer/tbox.rs+8−1
@@ -3,6 +3,7 @@ · 2 unmodified lines
3use super::HasHrTimer;3use super::HasHrTimer;
4use super::HrTimer;4use super::HrTimer;
5use super::HrTimerCallback;5use super::HrTimerCallback;
6use super::HrTimerCallbackContext;
6use super::HrTimerHandle;7use super::HrTimerHandle;
7use super::HrTimerMode;8use super::HrTimerMode;
8use super::HrTimerPointer;9use super::HrTimerPointer;
@@ -119,6 +120,12 @@ where · 110 unmodified lines
119 // `data_ptr` exist.120 // `data_ptr` exist.
120 let data_mut_ref = unsafe { Pin::new_unchecked(&mut *data_ptr) };121 let data_mut_ref = unsafe { Pin::new_unchecked(&mut *data_ptr) };
121 122
122 T::run(data_mut_ref).into_c()123 // SAFETY:
124 // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
125 // it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
126 // - We are within `RawHrTimerCallback::run`
127 let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
128
129 T::run(data_mut_ref, context).into_c()
123 }130 }
124}131}
rust/macros/quote.rs+49−55
@@ -2,7 +2,6 @@ · 1 unmodified line
2 2
3use proc_macro::{TokenStream, TokenTree};3use proc_macro::{TokenStream, TokenTree};
4 4
5#[allow(dead_code)]
6pub(crate) trait ToTokens {5pub(crate) trait ToTokens {
7 fn to_tokens(&self, tokens: &mut TokenStream);6 fn to_tokens(&self, tokens: &mut TokenStream);
8}7}
@@ -47,121 +46,116 @@ impl ToTokens for TokenStream { · 38 unmodified lines
47/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.46/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
48macro_rules! quote_spanned {47macro_rules! quote_spanned {
49 ($span:expr => $($tt:tt)*) => {{48 ($span:expr => $($tt:tt)*) => {{
50 let mut tokens: ::std::vec::Vec<::proc_macro::TokenTree>;49 let mut tokens = ::proc_macro::TokenStream::new();
51 #[allow(clippy::vec_init_then_push)]
52 {50 {
53 tokens = ::std::vec::Vec::new();
54 let span = $span;51 let span = $span;
55 quote_spanned!(@proc tokens span $($tt)*);52 quote_spanned!(@proc tokens span $($tt)*);
56 }53 }
57 ::proc_macro::TokenStream::from_iter(tokens)54 tokens
58 }};55 }};
59 (@proc $v:ident $span:ident) => {};56 (@proc $v:ident $span:ident) => {};
60 (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {57 (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {
61 let mut ts = ::proc_macro::TokenStream::new();58 $crate::quote::ToTokens::to_tokens(&$id, &mut $v);
62 $crate::quote::ToTokens::to_tokens(&$id, &mut ts);
63 $v.extend(ts);
64 quote_spanned!(@proc $v $span $($tt)*);59 quote_spanned!(@proc $v $span $($tt)*);
65 };60 };
66 (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {61 (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {
67 for token in $id {62 for token in $id {
68 let mut ts = ::proc_macro::TokenStream::new();63 $crate::quote::ToTokens::to_tokens(&token, &mut $v);
69 $crate::quote::ToTokens::to_tokens(&token, &mut ts);
70 $v.extend(ts);
71 }64 }
72 quote_spanned!(@proc $v $span $($tt)*);65 quote_spanned!(@proc $v $span $($tt)*);
73 };66 };
74 (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {67 (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
75 #[allow(unused_mut)]68 #[allow(unused_mut)]
76 let mut tokens = ::std::vec::Vec::<::proc_macro::TokenTree>::new();69 let mut tokens = ::proc_macro::TokenStream::new();
77 quote_spanned!(@proc tokens $span $($inner)*);70 quote_spanned!(@proc tokens $span $($inner)*);
78 $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(71 $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
79 ::proc_macro::Delimiter::Parenthesis,72 ::proc_macro::Delimiter::Parenthesis,
80 ::proc_macro::TokenStream::from_iter(tokens)73 tokens,
81 )));74 ))]);
82 quote_spanned!(@proc $v $span $($tt)*);75 quote_spanned!(@proc $v $span $($tt)*);
83 };76 };
84 (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {77 (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {
85 let mut tokens = ::std::vec::Vec::new();78 let mut tokens = ::proc_macro::TokenStream::new();
86 quote_spanned!(@proc tokens $span $($inner)*);79 quote_spanned!(@proc tokens $span $($inner)*);
87 $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(80 $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
88 ::proc_macro::Delimiter::Bracket,81 ::proc_macro::Delimiter::Bracket,
89 ::proc_macro::TokenStream::from_iter(tokens)82 tokens,
90 )));83 ))]);
91 quote_spanned!(@proc $v $span $($tt)*);84 quote_spanned!(@proc $v $span $($tt)*);
92 };85 };
93 (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {86 (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {
94 let mut tokens = ::std::vec::Vec::new();87 let mut tokens = ::proc_macro::TokenStream::new();
95 quote_spanned!(@proc tokens $span $($inner)*);88 quote_spanned!(@proc tokens $span $($inner)*);
96 $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(89 $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
97 ::proc_macro::Delimiter::Brace,90 ::proc_macro::Delimiter::Brace,
98 ::proc_macro::TokenStream::from_iter(tokens)91 tokens,
99 )));92 ))]);
100 quote_spanned!(@proc $v $span $($tt)*);93 quote_spanned!(@proc $v $span $($tt)*);
101 };94 };
102 (@proc $v:ident $span:ident :: $($tt:tt)*) => {95 (@proc $v:ident $span:ident :: $($tt:tt)*) => {
103 $v.push(::proc_macro::TokenTree::Punct(96 $v.extend([::proc_macro::Spacing::Joint, ::proc_macro::Spacing::Alone].map(|spacing| {
104 ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint)97 ::proc_macro::TokenTree::Punct(::proc_macro::Punct::new(':', spacing))
105 ));98 }));
106 $v.push(::proc_macro::TokenTree::Punct(
107 ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
108 ));
109 quote_spanned!(@proc $v $span $($tt)*);99 quote_spanned!(@proc $v $span $($tt)*);
110 };100 };
111 (@proc $v:ident $span:ident : $($tt:tt)*) => {101 (@proc $v:ident $span:ident : $($tt:tt)*) => {
112 $v.push(::proc_macro::TokenTree::Punct(102 $v.extend([::proc_macro::TokenTree::Punct(
113 ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)103 ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone),
114 ));104 )]);
115 quote_spanned!(@proc $v $span $($tt)*);105 quote_spanned!(@proc $v $span $($tt)*);
116 };106 };
117 (@proc $v:ident $span:ident , $($tt:tt)*) => {107 (@proc $v:ident $span:ident , $($tt:tt)*) => {
118 $v.push(::proc_macro::TokenTree::Punct(108 $v.extend([::proc_macro::TokenTree::Punct(
119 ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone)109 ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone),
120 ));110 )]);
121 quote_spanned!(@proc $v $span $($tt)*);111 quote_spanned!(@proc $v $span $($tt)*);
122 };112 };
123 (@proc $v:ident $span:ident @ $($tt:tt)*) => {113 (@proc $v:ident $span:ident @ $($tt:tt)*) => {
124 $v.push(::proc_macro::TokenTree::Punct(114 $v.extend([::proc_macro::TokenTree::Punct(
125 ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone)115 ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone),
126 ));116 )]);
127 quote_spanned!(@proc $v $span $($tt)*);117 quote_spanned!(@proc $v $span $($tt)*);
128 };118 };
129 (@proc $v:ident $span:ident ! $($tt:tt)*) => {119 (@proc $v:ident $span:ident ! $($tt:tt)*) => {
130 $v.push(::proc_macro::TokenTree::Punct(120 $v.extend([::proc_macro::TokenTree::Punct(
131 ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone)121 ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone),
132 ));122 )]);
133 quote_spanned!(@proc $v $span $($tt)*);123 quote_spanned!(@proc $v $span $($tt)*);
134 };124 };
135 (@proc $v:ident $span:ident ; $($tt:tt)*) => {125 (@proc $v:ident $span:ident ; $($tt:tt)*) => {
136 $v.push(::proc_macro::TokenTree::Punct(126 $v.extend([::proc_macro::TokenTree::Punct(
137 ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone)127 ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone),
138 ));128 )]);
139 quote_spanned!(@proc $v $span $($tt)*);129 quote_spanned!(@proc $v $span $($tt)*);
140 };130 };
141 (@proc $v:ident $span:ident + $($tt:tt)*) => {131 (@proc $v:ident $span:ident + $($tt:tt)*) => {
142 $v.push(::proc_macro::TokenTree::Punct(132 $v.extend([::proc_macro::TokenTree::Punct(
143 ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone)133 ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone),
144 ));134 )]);
145 quote_spanned!(@proc $v $span $($tt)*);135 quote_spanned!(@proc $v $span $($tt)*);
146 };136 };
147 (@proc $v:ident $span:ident = $($tt:tt)*) => {137 (@proc $v:ident $span:ident = $($tt:tt)*) => {
148 $v.push(::proc_macro::TokenTree::Punct(138 $v.extend([::proc_macro::TokenTree::Punct(
149 ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone)139 ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone),
150 ));140 )]);
151 quote_spanned!(@proc $v $span $($tt)*);141 quote_spanned!(@proc $v $span $($tt)*);
152 };142 };
153 (@proc $v:ident $span:ident # $($tt:tt)*) => {143 (@proc $v:ident $span:ident # $($tt:tt)*) => {
154 $v.push(::proc_macro::TokenTree::Punct(144 $v.extend([::proc_macro::TokenTree::Punct(
155 ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone)145 ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone),
156 ));146 )]);
157 quote_spanned!(@proc $v $span $($tt)*);147 quote_spanned!(@proc $v $span $($tt)*);
158 };148 };
159 (@proc $v:ident $span:ident _ $($tt:tt)*) => {149 (@proc $v:ident $span:ident _ $($tt:tt)*) => {
160 $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new("_", $span)));150 $v.extend([::proc_macro::TokenTree::Ident(
151 ::proc_macro::Ident::new("_", $span),
152 )]);
161 quote_spanned!(@proc $v $span $($tt)*);153 quote_spanned!(@proc $v $span $($tt)*);
162 };154 };
163 (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {155 (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
164 $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(stringify!($id), $span)));156 $v.extend([::proc_macro::TokenTree::Ident(
157 ::proc_macro::Ident::new(stringify!($id), $span),
158 )]);
165 quote_spanned!(@proc $v $span $($tt)*);159 quote_spanned!(@proc $v $span $($tt)*);
166 };160 };
167}161}
rust/uapi/lib.rs+2−0
@@ -34,4 +34,6 @@ type __kernel_size_t = usize; · 33 unmodified lines
34type __kernel_ssize_t = isize;34type __kernel_ssize_t = isize;
35type __kernel_ptrdiff_t = isize;35type __kernel_ptrdiff_t = isize;
36 36
37use pin_init::MaybeZeroable;
38
37include!(concat!(env!("OBJTREE"), "/rust/uapi/uapi_generated.rs"));39include!(concat!(env!("OBJTREE"), "/rust/uapi/uapi_generated.rs"));
samples/rust/rust_configfs.rs+1−1
@@ -94,7 +94,7 @@ impl configfs::AttributeOperations<0> for Configuration { · 93 unmodified lines
94 94
95 fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {95 fn show(container: &Configuration, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
96 pr_info!("Show message\n");96 pr_info!("Show message\n");
97 let data = container.message;97 let data = container.message.to_bytes();
98 page[0..data.len()].copy_from_slice(data);98 page[0..data.len()].copy_from_slice(data);
99 Ok(data.len())99 Ok(data.len())
100 }100 }
samples/rust/rust_dma.rs+1−1
@@ -10,7 +10,7 @@ use kernel::{ · 9 unmodified lines
10 dma::{CoherentAllocation, Device, DmaMask},10 dma::{CoherentAllocation, Device, DmaMask},
11 pci,11 pci,
12 prelude::*,12 prelude::*,
13 types::ARef,13 sync::aref::ARef,
14};14};
15 15
16struct DmaSampleDriver {16struct DmaSampleDriver {
scripts/generate_rust_analyzer.py+2−2
@@ -139,8 +139,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · 138 unmodified lines
139 "exclude_dirs": [],139 "exclude_dirs": [],
140 }140 }
141 141
142 append_crate_with_generated("bindings", ["core", "ffi"])142 append_crate_with_generated("bindings", ["core", "ffi", "pin_init"])
143 append_crate_with_generated("uapi", ["core", "ffi"])143 append_crate_with_generated("uapi", ["core", "ffi", "pin_init"])
144 append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])144 append_crate_with_generated("kernel", ["core", "macros", "build_error", "pin_init", "ffi", "bindings", "uapi"])
145 145
146 def is_root_crate(build_file, target):146 def is_root_crate(build_file, target):
scripts/rustdoc_test_gen.rs+1−1
@@ -202,7 +202,7 @@ pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{ · 201 unmodified lines
202 // This follows the syntax for declaring test metadata in the proposed KTAP v2 spec, which may202 // This follows the syntax for declaring test metadata in the proposed KTAP v2 spec, which may
203 // be used for the proposed KUnit test attributes API. Thus hopefully this will make migration203 // be used for the proposed KUnit test attributes API. Thus hopefully this will make migration
204 // easier later on.204 // easier later on.
205 ::kernel::kunit::info(format_args!(" # {kunit_name}.location: {real_path}:{line}\n"));205 ::kernel::kunit::info(fmt!(" # {kunit_name}.location: {real_path}:{line}\n"));
206 206
207 /// The anchor where the test code body starts.207 /// The anchor where the test code body starts.
208 #[allow(unused)]208 #[allow(unused)]