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!}` ...
Unified · Split
| @@ -147,7 +147,6 @@ Numerical operations [NUMM] · 146 unmodified lines | |||
| 147 | Nova uses integer operations that are not part of the standard library (or not | 147 | Nova uses integer operations that are not part of the standard library (or not |
| 148 | implemented in an optimized way for the kernel). These include: | 148 | implemented 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 | ||
| @@ -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 { |
| @@ -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) { |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | use core::ops::Range; | 3 | use core::ops::Range; |
| 4 | 4 | ||
| 5 | use kernel::prelude::*; | 5 | use kernel::prelude::*; |
| 6 | use kernel::ptr::{Alignable, Alignment}; | ||
| 6 | use kernel::sizes::*; | 7 | use kernel::sizes::*; |
| 7 | use kernel::types::ARef; | 8 | use kernel::types::ARef; |
| 8 | use kernel::{dev_warn, device}; | 9 | use 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_SIZE | 138 | frts_base..frts_base + FRTS_SIZE |
| 139 | }; | 139 | }; |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | use kernel::{device, devres::Devres, error::code::*, pci, prelude::*, sync::Arc}; | 3 | use kernel::{device, devres::Devres, error::code::*, fmt, pci, prelude::*, sync::Arc}; |
| 4 | 4 | ||
| 5 | use crate::driver::Bar0; | 5 | use crate::driver::Bar0; |
| 6 | use crate::falcon::{gsp::Gsp, sec2::Sec2, Falcon}; | 6 | use crate::falcon::{gsp::Gsp, sec2::Sec2, Falcon}; |
| @@ -12,7 +12,6 @@ use crate::gfw; · 5 unmodified lines | |||
| 12 | use crate::regs; | 12 | use crate::regs; |
| 13 | use crate::util; | 13 | use crate::util; |
| 14 | use crate::vbios::Vbios; | 14 | use crate::vbios::Vbios; |
| 15 | use core::fmt; | ||
| 16 | 15 | ||
| 17 | macro_rules! define_chipset { | 16 | macro_rules! define_chipset { |
| 18 | ({ $($variant:ident = $value:expr),* $(,)* }) => | 17 | ({ $($variant:ident = $value:expr),* $(,)* }) => |
| @@ -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 requires | 150 | // 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 | } |
| @@ -10,6 +10,7 @@ use kernel::device; · 9 unmodified lines | |||
| 10 | use kernel::error::Result; | 10 | use kernel::error::Result; |
| 11 | use kernel::pci; | 11 | use kernel::pci; |
| 12 | use kernel::prelude::*; | 12 | use kernel::prelude::*; |
| 13 | use 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. |
| 15 | const ROM_OFFSET: usize = 0x300000; | 16 | const 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 | } |
| @@ -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. |
| 99 | rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ | 99 | rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ |
| 100 | rustdoc-kernel rustdoc-pin_init | 100 | 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 FORCE | 199 | $(obj)/bindings.o FORCE |
| 194 | +$(call if_changed,rustc_test_library) | 200 | +$(call if_changed,rustc_test_library) |
| 195 | 201 | ||
| 196 | rusttestlib-bindings: private rustc_target_flags = --extern ffi | 202 | rusttestlib-bindings: private rustc_target_flags = --extern ffi --extern pin_init |
| 197 | rusttestlib-bindings: $(src)/bindings/lib.rs rusttestlib-ffi FORCE | 203 | rusttestlib-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 | ||
| 200 | rusttestlib-uapi: private rustc_target_flags = --extern ffi | 206 | rusttestlib-uapi: private rustc_target_flags = --extern ffi --extern pin_init |
| 201 | rusttestlib-uapi: $(src)/uapi/lib.rs rusttestlib-ffi FORCE | 207 | rusttestlib-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 | ||
| 204 | quiet_cmd_rustdoc_test = RUSTDOC T $< | 210 | quiet_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 | ||
| 251 | rusttest: rusttest-macros rusttest-kernel | 257 | rusttest: rusttest-macros |
| 252 | 258 | ||
| 253 | rusttest-macros: private rustc_target_flags = --extern proc_macro \ | 259 | rusttest-macros: private rustc_target_flags = --extern proc_macro \ |
| 254 | --extern macros --extern kernel --extern pin_init | 260 | --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 | ||
| 261 | rusttest-kernel: private rustc_target_flags = --extern ffi --extern pin_init \ | ||
| 262 | --extern build_error --extern macros --extern bindings --extern uapi | ||
| 263 | rusttest-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 | |||
| 268 | ifdef CONFIG_CC_IS_CLANG | 267 | ifdef CONFIG_CC_IS_CLANG |
| 269 | bindgen_c_flags = $(c_flags) | 268 | bindgen_c_flags = $(c_flags) |
| 270 | else | 269 | else |
| @@ -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 FORCE | 530 | $(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 ffi | 533 | $(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 FORCE | 538 | $(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 ffi | 541 | $(obj)/uapi.o: private rustc_target_flags = --extern ffi --extern pin_init |
| 542 | $(obj)/uapi.o: private skip_gendwarfksyms = 1 | 542 | $(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 FORCE | 546 | $(obj)/uapi/uapi_generated.rs FORCE |
| 546 | +$(call if_changed_rule,rustc_library) | 547 | +$(call if_changed_rule,rustc_library) |
| 547 | 548 | ||
| @@ -34,3 +34,8 @@ · 33 unmodified lines | |||
| 34 | # We use const helpers to aid bindgen, to avoid conflicts when constants are | 34 | # 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_MINALIGN | 36 | --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 | ||
| @@ -84,6 +84,7 @@ · 83 unmodified lines | |||
| 84 | 84 | ||
| 85 | /* `bindgen` gets confused at certain things. */ | 85 | /* `bindgen` gets confused at certain things. */ |
| 86 | const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; | 86 | const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; |
| 87 | const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN; | ||
| 87 | const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE; | 88 | const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE; |
| 88 | const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC; | 89 | const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC; |
| 89 | const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL; | 90 | const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL; |
| @@ -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))] |
| 33 | mod bindings_raw { | 33 | mod 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::*; |
| @@ -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() }; |
| @@ -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)))] | ||
| 6 | pub mod allocator; | 5 | pub mod allocator; |
| 7 | pub mod kbox; | 6 | pub mod kbox; |
| 8 | pub mod kvec; | 7 | pub mod kvec; |
| 9 | pub mod layout; | 8 | pub mod layout; |
| 10 | 9 | ||
| 11 | #[cfg(any(test, testlib))] | ||
| 12 | pub mod allocator_test; | ||
| 13 | |||
| 14 | #[cfg(any(test, testlib))] | ||
| 15 | pub use self::allocator_test as allocator; | ||
| 16 | |||
| 17 | pub use self::kbox::Box; | 10 | pub use self::kbox::Box; |
| 18 | pub use self::kbox::KBox; | 11 | pub use self::kbox::KBox; |
| 19 | pub use self::kbox::KVBox; | 12 | pub 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 the | 130 | /// - Implementers must ensure that all trait functions abide by the guarantees documented in the |
| 138 | /// `# Guarantees` sections. | 131 | /// `# Guarantees` sections. |
| 139 | pub unsafe trait Allocator { | 132 | pub 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 layout | 143 | /// On success, returns a buffer represented as `NonNull<[u8]>` that satisfies the layout |
| @@ -17,6 +17,8 @@ use crate::alloc::{AllocError, Allocator}; · 16 unmodified lines | |||
| 17 | use crate::bindings; | 17 | use crate::bindings; |
| 18 | use crate::pr_warn; | 18 | use crate::pr_warn; |
| 19 | 19 | ||
| 20 | const 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 also | 24 | /// `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. |
| 130 | unsafe impl Allocator for Kmalloc { | 132 | unsafe 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. |
| 149 | unsafe impl Allocator for Vmalloc { | 153 | unsafe 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. |
| 173 | unsafe impl Allocator for KVmalloc { | 179 | unsafe 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>>, |
| @@ -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 | |||
| 12 | use super::{flags::*, AllocError, Allocator, Flags}; | ||
| 13 | use core::alloc::Layout; | ||
| 14 | use core::cmp; | ||
| 15 | use core::ptr; | ||
| 16 | use core::ptr::NonNull; | ||
| 17 | |||
| 18 | /// The userspace allocator based on libc. | ||
| 19 | pub struct Cmalloc; | ||
| 20 | |||
| 21 | pub type Kmalloc = Cmalloc; | ||
| 22 | pub type Vmalloc = Kmalloc; | ||
| 23 | pub type KVmalloc = Kmalloc; | ||
| 24 | |||
| 25 | impl 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 | |||
| 36 | extern "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. | ||
| 48 | unsafe 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 | } | ||
| @@ -7,7 +7,6 @@ use super::allocator::{KVmalloc, Kmalloc, Vmalloc}; · 6 unmodified lines | |||
| 7 | use super::{AllocError, Allocator, Flags}; | 7 | use super::{AllocError, Allocator, Flags}; |
| 8 | use core::alloc::Layout; | 8 | use core::alloc::Layout; |
| 9 | use core::borrow::{Borrow, BorrowMut}; | 9 | use core::borrow::{Borrow, BorrowMut}; |
| 10 | use core::fmt; | ||
| 11 | use core::marker::PhantomData; | 10 | use core::marker::PhantomData; |
| 12 | use core::mem::ManuallyDrop; | 11 | use core::mem::ManuallyDrop; |
| 13 | use core::mem::MaybeUninit; | 12 | use core::mem::MaybeUninit; |
| @@ -17,6 +16,7 @@ use core::ptr::NonNull; · 3 unmodified lines | |||
| 17 | use core::result::Result; | 16 | use core::result::Result; |
| 18 | 17 | ||
| 19 | use crate::ffi::c_void; | 18 | use crate::ffi::c_void; |
| 19 | use crate::fmt; | ||
| 20 | use crate::init::InPlaceInit; | 20 | use crate::init::InPlaceInit; |
| 21 | use crate::types::ForeignOwnable; | 21 | use crate::types::ForeignOwnable; |
| 22 | use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption}; | 22 | use 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 implement | 370 | /// 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 aligned | 480 | // SAFETY: The pointer returned by `into_foreign` comes from a well aligned |
| 404 | // pointer to `T`. | 481 | // pointer to `T` allocated by `A`. |
| 405 | unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A> | 482 | unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A> |
| 406 | where | 483 | where |
| 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 aligned | 519 | // SAFETY: The pointer returned by `into_foreign` comes from a well aligned |
| 438 | // pointer to `T`. | 520 | // pointer to `T` allocated by `A`. |
| 439 | unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>> | 521 | unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>> |
| 440 | where | 522 | where |
| 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 | ||
| @@ -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 | }; |
| 10 | use crate::fmt; | ||
| 10 | use core::{ | 11 | use 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 allocating | 176 | /// 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::MAX | 180 | 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.len | 189 | 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 of | 202 | // 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 | self | 239 | 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 raw | 255 | /// 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() == 0 | 275 | 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)] |
| 1298 | mod tests { | 1308 | mod tests { |
| 1299 | use super::*; | 1309 | use super::*; |
| 1300 | use crate::prelude::*; | 1310 | use crate::prelude::*; |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | //! Errors for the [`Vec`] type. | 3 | //! Errors for the [`Vec`] type. |
| 4 | 4 | ||
| 5 | use core::fmt::{self, Debug, Formatter}; | 5 | use kernel::fmt::{self, Debug, Formatter}; |
| 6 | use kernel::prelude::*; | 6 | use kernel::prelude::*; |
| 7 | 7 | ||
| 8 | /// Error type for [`Vec::push_within_capacity`]. | 8 | /// Error type for [`Vec::push_within_capacity`]. |
| @@ -80,7 +80,7 @@ impl<T> ArrayLayout<T> { · 79 unmodified lines | |||
| 80 | /// # Safety | 80 | /// # 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 function | 84 | // 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 { |
| @@ -105,8 +105,8 @@ pub struct DeviceId(bindings::auxiliary_device_id); · 104 unmodified lines | |||
| 105 | impl DeviceId { | 105 | impl 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 for | 111 | // TODO: Replace with `bindings::auxiliary_device_id::default()` once stabilized for |
| 112 | // `const`. | 112 | // `const`. |
| @@ -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 | //! ``` |
| @@ -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 | ||
| 8 | use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet}; | 8 | use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet}; |
| 9 | use crate::fmt::{self, Write}; | ||
| 9 | use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc}; | 10 | use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc}; |
| 10 | use crate::{error, static_lock_class}; | 11 | use crate::{error, static_lock_class}; |
| 11 | use core::fmt::{self, Write}; | ||
| 12 | 12 | ||
| 13 | /// A builder for [`GenDisk`]. | 13 | /// A builder for [`GenDisk`]. |
| 14 | /// | 14 | /// |
| @@ -1,8 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | use core::fmt::{self, Write}; | ||
| 4 | |||
| 5 | use crate::error::Result; | 3 | use crate::error::Result; |
| 4 | use crate::fmt::{self, Write}; | ||
| 6 | use crate::prelude::EINVAL; | 5 | use 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. |
| @@ -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), |
| @@ -109,6 +109,7 @@ impl CpuId { · 108 unmodified lines | |||
| 109 | /// unexpectedly due to preemption or CPU migration. It should only be | 109 | /// unexpectedly due to preemption or CPU migration. It should only be |
| 110 | /// used when the context ensures that the task remains on the same CPU | 110 | /// 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()) } |
| @@ -27,7 +27,6 @@ use crate::clk::Clk; · 26 unmodified lines | |||
| 27 | use core::{ | 27 | use 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 | None | 1013 | 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); |
| @@ -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 | ||
| 7 | use crate::{ | 7 | use crate::{ |
| 8 | bindings, | 8 | bindings, fmt, |
| 9 | types::{ARef, ForeignOwnable, Opaque}, | 9 | types::{ARef, ForeignOwnable, Opaque}, |
| 10 | }; | 10 | }; |
| 11 | use core::{fmt, marker::PhantomData, ptr}; | 11 | use core::{marker::PhantomData, ptr}; |
| 12 | 12 | ||
| 13 | #[cfg(CONFIG_PRINTK)] | 13 | #[cfg(CONFIG_PRINTK)] |
| 14 | use crate::c_str; | 14 | use crate::c_str; |
| @@ -596,7 +596,7 @@ macro_rules! impl_device_context_into_aref { · 581 unmodified lines | |||
| 596 | macro_rules! dev_printk { | 596 | macro_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 | } |
| @@ -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) for | 72 | /// 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, which | 75 | /// 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 | ||
| 354 | impl core::fmt::Debug for FwNodeReferenceArgs { | 355 | impl 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 | ||
| 380 | impl core::fmt::Display for FwNode { | 381 | impl 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.c | 383 | // 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 a | 414 | // 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(()) |
| @@ -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. |
| @@ -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 | ||
| 7 | use crate::{ | 7 | use 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(), |
| @@ -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 | ||
| 7 | use crate::{ | 7 | use crate::{ |
| 8 | bindings, device, devres, drm, | 8 | bindings, device, devres, drm, |
| @@ -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 | ||
| 7 | use crate::{bindings, drm, error::Result, prelude::*, types::Opaque}; | 7 | use crate::{bindings, drm, error::Result, prelude::*, types::Opaque}; |
| 8 | use core::marker::PhantomData; | 8 | use core::marker::PhantomData; |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | //! DRM GEM API | 3 | //! 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 | ||
| 7 | use crate::{ | 7 | use crate::{ |
| 8 | alloc::flags::*, | 8 | alloc::flags::*, |
| @@ -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 | ||
| 7 | use crate::ioctl; | 7 | use crate::ioctl; |
| 8 | 8 | ||
| @@ -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 | ||
| 7 | use crate::{ | 9 | use crate::{ |
| 8 | alloc::{layout::LayoutError, AllocError}, | 10 | alloc::{layout::LayoutError, AllocError}, |
| @@ -101,8 +103,23 @@ pub struct Error(NonZeroI32); · 92 unmodified lines | |||
| 101 | impl Error { | 103 | impl 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` would | 106 | /// `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 | error | 125 | 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 a | 192 | /// 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 still | 193 | /// 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 | None | 197 | 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.html | 392 | /// [Rust documentation]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html |
| 376 | pub type Result<T = (), E = Error> = core::result::Result<T, E>; | 393 | pub 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, and | 395 | /// 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 | ||
| 380 | pub fn to_result(err: crate::ffi::c_int) -> Result { | 432 | pub 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)) |
| @@ -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. |
| @@ -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 | ||
| 463 | impl core::fmt::Debug for BadFdError { | 464 | impl 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 | } |
| @@ -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 | ||
| 9 | use crate::fmt; | ||
| 9 | use crate::prelude::*; | 10 | use crate::prelude::*; |
| 10 | use core::fmt; | ||
| 11 | 11 | ||
| 12 | #[cfg(CONFIG_PRINTK)] | 12 | #[cfg(CONFIG_PRINTK)] |
| 13 | use crate::c_str; | 13 | use 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 | $name | 79 | $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 | }, |
| @@ -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 | |||
| 110 | pub mod platform; | 112 | pub mod platform; |
| 111 | pub mod prelude; | 113 | pub mod prelude; |
| 112 | pub mod print; | 114 | pub mod print; |
| 115 | pub mod ptr; | ||
| 113 | pub mod rbtree; | 116 | pub mod rbtree; |
| 114 | pub mod regulator; | 117 | pub mod regulator; |
| 115 | pub mod revocable; | 118 | pub 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] |
| 211 | fn panic(info: &core::panic::PanicInfo<'_>) -> ! { | 214 | fn panic(info: &core::panic::PanicInfo<'_>) -> ! { |
| 212 | pr_emerg!("{}\n", info); | 215 | pr_emerg!("{}\n", info); |
| @@ -38,6 +38,8 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField}; · 37 unmodified lines | |||
| 38 | /// | 38 | /// |
| 39 | /// # Examples | 39 | /// # 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 | /// ``` | ||
| 143 | pub struct List<T: ?Sized + ListItem<ID>, const ID: u64 = 0> { | 263 | pub 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>>, |
| @@ -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 | result | 39 | result |
| 40 | } | 40 | } |
| @@ -497,7 +497,7 @@ unsafe impl Sync for DriverVTable {} · 496 unmodified lines | |||
| 497 | pub const fn create_phy_driver<T: Driver>() -> DriverVTable { | 497 | pub 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(), |
| @@ -34,7 +34,7 @@ unsafe impl RawDeviceIdIndex for DeviceId { · 33 unmodified lines | |||
| 34 | impl DeviceId { | 34 | impl 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() }; |
| @@ -12,7 +12,10 @@ · 11 unmodified lines | |||
| 12 | //! ``` | 12 | //! ``` |
| 13 | 13 | ||
| 14 | #[doc(no_inline)] | 14 | #[doc(no_inline)] |
| 15 | pub use core::pin::Pin; | 15 | pub use core::{ |
| 16 | mem::{align_of, align_of_val, size_of, size_of_val}, | ||
| 17 | pin::Pin, | ||
| 18 | }; | ||
| 16 | 19 | ||
| 17 | pub use ::ffi::{ | 20 | pub 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, |
| @@ -0,0 +1,228 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | //! Types and functions to work with pointers and addresses. | ||
| 4 | |||
| 5 | use core::fmt::Debug; | ||
| 6 | use core::mem::align_of; | ||
| 7 | use core::num::NonZero; | ||
| 8 | |||
| 9 | use 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)] | ||
| 26 | pub struct Alignment(NonZero<usize>); | ||
| 27 | |||
| 28 | impl 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`]. | ||
| 166 | pub 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. | ||
| 198 | macro_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 | |||
| 228 | impl_alignable_uint!(u8, u16, u32, u64, usize); | ||
| @@ -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 | ||
| 7 | use crate::{bindings, c_str, types::NotThreadSafe, types::Opaque}; | 7 | use 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] |
| 48 | macro_rules! seq_print { | 48 | macro_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 | } |
| 53 | pub use seq_print; | 53 | pub use seq_print; |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | use crate::{ | 19 | use 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 | |||
| 27 | use core::{ | 28 | use 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 aligned | 370 | // 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. |
| 372 | unsafe impl<T: 'static> ForeignOwnable for Arc<T> { | 372 | unsafe 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>; |
| @@ -1,6 +1,21 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // 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 | ||
| 5 | use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull}; | 20 | use 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 | /// |
| @@ -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 | }; |
| 14 | use core::{ | 15 | use 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. |
| 350 | unsafe impl crate::types::AlwaysRefCounted for Task { | 351 | unsafe 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. |
| @@ -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 | ||
| 27 | use core::marker::PhantomData; | 27 | use core::marker::PhantomData; |
| 28 | use core::ops; | ||
| 28 | 29 | ||
| 29 | pub mod delay; | 30 | pub mod delay; |
| 30 | pub mod hrtimer; | 31 | pub 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.inner | 202 | 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 | ||
| 205 | impl<C: ClockSource> core::ops::Sub for Instant<C> { | 228 | impl<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 | ||
| 240 | impl<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 | |||
| 260 | impl<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 | ||
| 290 | impl 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 | |||
| 301 | impl ops::AddAssign for Delta { | ||
| 302 | #[inline] | ||
| 303 | fn add_assign(&mut self, rhs: Self) { | ||
| 304 | self.nanos += rhs.nanos; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | impl 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 | |||
| 319 | impl ops::SubAssign for Delta { | ||
| 320 | #[inline] | ||
| 321 | fn sub_assign(&mut self, rhs: Self) { | ||
| 322 | self.nanos -= rhs.nanos; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | |||
| 326 | impl 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 | |||
| 337 | impl ops::MulAssign<i64> for Delta { | ||
| 338 | #[inline] | ||
| 339 | fn mul_assign(&mut self, rhs: i64) { | ||
| 340 | self.nanos *= rhs; | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | impl 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 | |||
| 227 | impl Delta { | 362 | impl 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 | } |
| @@ -69,9 +69,14 @@ · 68 unmodified lines | |||
| 69 | 69 | ||
| 70 | use super::{ClockSource, Delta, Instant}; | 70 | use super::{ClockSource, Delta, Instant}; |
| 71 | use crate::{prelude::*, types::Opaque}; | 71 | use crate::{prelude::*, types::Opaque}; |
| 72 | use core::marker::PhantomData; | 72 | use core::{marker::PhantomData, ptr::NonNull}; |
| 73 | use pin_init::PinInit; | 73 | use 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`]. | ||
| 78 | pub 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 | /// # Invariants | 82 | /// # 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<'_>) -> HrTimerRestart | 386 | fn run( |
| 387 | this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>, | ||
| 388 | ctx: HrTimerCallbackContext<'_, Self>, | ||
| 389 | ) -> HrTimerRestart | ||
| 304 | where | 390 | 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. If | 411 | /// 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 function | 412 | /// 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>`]. | ||
| 692 | pub struct HrTimerCallbackContext<'a, T: HasHrTimer<T>>(NonNull<HrTimer<T>>, PhantomData<&'a ()>); | ||
| 693 | |||
| 694 | impl<'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. |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | use super::HasHrTimer; | 3 | use super::HasHrTimer; |
| 4 | use super::HrTimer; | 4 | use super::HrTimer; |
| 5 | use super::HrTimerCallback; | 5 | use super::HrTimerCallback; |
| 6 | use super::HrTimerCallbackContext; | ||
| 6 | use super::HrTimerHandle; | 7 | use super::HrTimerHandle; |
| 7 | use super::HrTimerMode; | 8 | use super::HrTimerMode; |
| 8 | use super::HrTimerPointer; | 9 | use 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 | } |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | use super::HasHrTimer; | 3 | use super::HasHrTimer; |
| 4 | use super::HrTimer; | 4 | use super::HrTimer; |
| 5 | use super::HrTimerCallback; | 5 | use super::HrTimerCallback; |
| 6 | use super::HrTimerCallbackContext; | ||
| 6 | use super::HrTimerHandle; | 7 | use super::HrTimerHandle; |
| 7 | use super::HrTimerMode; | 8 | use super::HrTimerMode; |
| 8 | use super::RawHrTimerCallback; | 9 | use 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 | } |
| @@ -1,8 +1,8 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | use super::{ | 3 | use super::{ |
| 4 | HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, HrTimerMode, RawHrTimerCallback, | 4 | HasHrTimer, HrTimer, HrTimerCallback, HrTimerCallbackContext, HrTimerHandle, HrTimerMode, |
| 5 | UnsafeHrTimerPointer, | 5 | RawHrTimerCallback, UnsafeHrTimerPointer, |
| 6 | }; | 6 | }; |
| 7 | use core::{marker::PhantomData, pin::Pin, ptr::NonNull}; | 7 | use 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 | } |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | use super::HasHrTimer; | 3 | use super::HasHrTimer; |
| 4 | use super::HrTimer; | 4 | use super::HrTimer; |
| 5 | use super::HrTimerCallback; | 5 | use super::HrTimerCallback; |
| 6 | use super::HrTimerCallbackContext; | ||
| 6 | use super::HrTimerHandle; | 7 | use super::HrTimerHandle; |
| 7 | use super::HrTimerMode; | 8 | use super::HrTimerMode; |
| 8 | use super::HrTimerPointer; | 9 | use 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 | } |
| @@ -2,7 +2,6 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | use proc_macro::{TokenStream, TokenTree}; | 3 | use proc_macro::{TokenStream, TokenTree}; |
| 4 | 4 | ||
| 5 | #[allow(dead_code)] | ||
| 6 | pub(crate) trait ToTokens { | 5 | pub(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. |
| 48 | macro_rules! quote_spanned { | 47 | macro_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 | } |
| @@ -34,4 +34,6 @@ type __kernel_size_t = usize; · 33 unmodified lines | |||
| 34 | type __kernel_ssize_t = isize; | 34 | type __kernel_ssize_t = isize; |
| 35 | type __kernel_ptrdiff_t = isize; | 35 | type __kernel_ptrdiff_t = isize; |
| 36 | 36 | ||
| 37 | use pin_init::MaybeZeroable; | ||
| 38 | |||
| 37 | include!(concat!(env!("OBJTREE"), "/rust/uapi/uapi_generated.rs")); | 39 | include!(concat!(env!("OBJTREE"), "/rust/uapi/uapi_generated.rs")); |
| @@ -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 | } |
| @@ -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 | ||
| 16 | struct DmaSampleDriver { | 16 | struct DmaSampleDriver { |
| @@ -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): |
| @@ -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 may | 202 | // 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 migration | 203 | // 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)] |