summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/cpufreq.rs60
-rw-r--r--rust/kernel/cpumask.rs13
-rw-r--r--rust/kernel/drm/device.rs12
-rw-r--r--rust/kernel/drm/driver.rs1
-rw-r--r--rust/kernel/firmware.rs2
-rw-r--r--rust/kernel/init.rs8
-rw-r--r--rust/kernel/kunit.rs2
-rw-r--r--rust/kernel/lib.rs3
-rw-r--r--rust/kernel/opp.rs8
-rw-r--r--rust/kernel/sync/poll.rs68
10 files changed, 78 insertions, 99 deletions
diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs
index 11b03e9d7e89..d6a14239f4ba 100644
--- a/rust/kernel/cpufreq.rs
+++ b/rust/kernel/cpufreq.rs
@@ -1061,7 +1061,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1094,7 +1094,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1109,9 +1109,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn offline_callback(
- ptr: *mut bindings::cpufreq_policy,
- ) -> kernel::ffi::c_int {
+ unsafe extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1126,9 +1124,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn suspend_callback(
- ptr: *mut bindings::cpufreq_policy,
- ) -> kernel::ffi::c_int {
+ unsafe extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1143,7 +1139,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int {
+ unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1171,9 +1167,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn verify_callback(
- ptr: *mut bindings::cpufreq_policy_data,
- ) -> kernel::ffi::c_int {
+ unsafe extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1188,9 +1182,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn setpolicy_callback(
- ptr: *mut bindings::cpufreq_policy,
- ) -> kernel::ffi::c_int {
+ unsafe extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1207,9 +1199,9 @@ impl<T: Driver> Registration<T> {
/// - The pointer arguments must be valid pointers.
unsafe extern "C" fn target_callback(
ptr: *mut bindings::cpufreq_policy,
- target_freq: u32,
- relation: u32,
- ) -> kernel::ffi::c_int {
+ target_freq: c_uint,
+ relation: c_uint,
+ ) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1226,8 +1218,8 @@ impl<T: Driver> Registration<T> {
/// - The pointer arguments must be valid pointers.
unsafe extern "C" fn target_index_callback(
ptr: *mut bindings::cpufreq_policy,
- index: u32,
- ) -> kernel::ffi::c_int {
+ index: c_uint,
+ ) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1249,8 +1241,8 @@ impl<T: Driver> Registration<T> {
/// - The pointer arguments must be valid pointers.
unsafe extern "C" fn fast_switch_callback(
ptr: *mut bindings::cpufreq_policy,
- target_freq: u32,
- ) -> kernel::ffi::c_uint {
+ target_freq: c_uint,
+ ) -> c_uint {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
let policy = unsafe { Policy::from_raw_mut(ptr) };
@@ -1263,10 +1255,10 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
unsafe extern "C" fn adjust_perf_callback(
- cpu: u32,
- min_perf: usize,
- target_perf: usize,
- capacity: usize,
+ cpu: c_uint,
+ min_perf: c_ulong,
+ target_perf: c_ulong,
+ capacity: c_ulong,
) {
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
@@ -1284,8 +1276,8 @@ impl<T: Driver> Registration<T> {
/// - The pointer arguments must be valid pointers.
unsafe extern "C" fn get_intermediate_callback(
ptr: *mut bindings::cpufreq_policy,
- index: u32,
- ) -> kernel::ffi::c_uint {
+ index: c_uint,
+ ) -> c_uint {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
let policy = unsafe { Policy::from_raw_mut(ptr) };
@@ -1305,8 +1297,8 @@ impl<T: Driver> Registration<T> {
/// - The pointer arguments must be valid pointers.
unsafe extern "C" fn target_intermediate_callback(
ptr: *mut bindings::cpufreq_policy,
- index: u32,
- ) -> kernel::ffi::c_int {
+ index: c_uint,
+ ) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
@@ -1325,7 +1317,7 @@ impl<T: Driver> Registration<T> {
/// # Safety
///
/// - This function may only be called from the cpufreq C infrastructure.
- unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint {
+ unsafe extern "C" fn get_callback(cpu: c_uint) -> c_uint {
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
@@ -1351,7 +1343,7 @@ impl<T: Driver> Registration<T> {
///
/// - This function may only be called from the cpufreq C infrastructure.
/// - The pointer arguments must be valid pointers.
- unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int {
+ unsafe extern "C" fn bios_limit_callback(cpu: c_int, limit: *mut c_uint) -> c_int {
// SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) };
@@ -1371,8 +1363,8 @@ impl<T: Driver> Registration<T> {
/// - The pointer arguments must be valid pointers.
unsafe extern "C" fn set_boost_callback(
ptr: *mut bindings::cpufreq_policy,
- state: i32,
- ) -> kernel::ffi::c_int {
+ state: c_int,
+ ) -> c_int {
from_result(|| {
// SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
// lifetime of `policy`.
diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs
index 19c607709b5f..e07f8ff5e3fd 100644
--- a/rust/kernel/cpumask.rs
+++ b/rust/kernel/cpumask.rs
@@ -14,9 +14,6 @@ use crate::{
#[cfg(CONFIG_CPUMASK_OFFSTACK)]
use core::ptr::{self, NonNull};
-#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
-use core::mem::MaybeUninit;
-
use core::ops::{Deref, DerefMut};
/// A CPU Mask.
@@ -239,10 +236,7 @@ impl CpumaskVar {
},
#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
- // SAFETY: FFI type is valid to be zero-initialized.
- //
- // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.
- mask: unsafe { core::mem::zeroed() },
+ mask: Cpumask(Opaque::zeroed()),
})
}
@@ -266,10 +260,7 @@ impl CpumaskVar {
NonNull::new(ptr.cast()).ok_or(AllocError)?
},
#[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
- // SAFETY: Guaranteed by the safety requirements of the function.
- //
- // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.
- mask: unsafe { MaybeUninit::uninit().assume_init() },
+ mask: Cpumask(Opaque::uninit()),
})
}
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 624d7a4c83ea..14c1aa402951 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -66,7 +66,7 @@ impl<T: drm::Driver> Device<T> {
open: Some(drm::File::<T::File>::open_callback),
postclose: Some(drm::File::<T::File>::postclose_callback),
unload: None,
- release: None,
+ release: Some(Self::release),
master_set: None,
master_drop: None,
debugfs_init: None,
@@ -162,6 +162,16 @@ impl<T: drm::Driver> Device<T> {
// SAFETY: `ptr` is valid by the safety requirements of this function.
unsafe { &*ptr.cast() }
}
+
+ extern "C" fn release(ptr: *mut bindings::drm_device) {
+ // SAFETY: `ptr` is a valid pointer to a `struct drm_device` and embedded in `Self`.
+ let this = unsafe { Self::from_drm_device(ptr) };
+
+ // SAFETY:
+ // - When `release` runs it is guaranteed that there is no further access to `this`.
+ // - `this` is valid for dropping.
+ unsafe { core::ptr::drop_in_place(this) };
+ }
}
impl<T: drm::Driver> Deref for Device<T> {
diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
index acb638086131..af93d46d03d3 100644
--- a/rust/kernel/drm/driver.rs
+++ b/rust/kernel/drm/driver.rs
@@ -10,7 +10,6 @@ use crate::{
drm,
error::{to_result, Result},
prelude::*,
- str::CStr,
types::ARef,
};
use macros::vtable;
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index 2494c96e105f..4fe621f35716 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -202,7 +202,7 @@ macro_rules! module_firmware {
};
#[link_section = ".modinfo"]
- #[used]
+ #[used(compiler)]
static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX)
.build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build();
};
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
index 8d228c237954..21ef202ab0db 100644
--- a/rust/kernel/init.rs
+++ b/rust/kernel/init.rs
@@ -231,14 +231,14 @@ macro_rules! try_init {
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}) => {
- ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
$($fields)*
}? $crate::error::Error)
};
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}? $err:ty) => {
- ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? {
$($fields)*
}? $err)
};
@@ -291,14 +291,14 @@ macro_rules! try_pin_init {
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}) => {
- ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
$($fields)*
}? $crate::error::Error)
};
($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
$($fields:tt)*
}? $err:ty) => {
- ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
+ ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? {
$($fields)*
}? $err)
};
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 4b8cdcb21e77..b9e65905e121 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -302,7 +302,7 @@ macro_rules! kunit_unsafe_test_suite {
is_init: false,
};
- #[used]
+ #[used(compiler)]
#[allow(unused_unsafe)]
#[cfg_attr(not(target_os = "macos"), link_section = ".kunit_test_suites")]
static mut KUNIT_TEST_SUITE_ENTRY: *const ::kernel::bindings::kunit_suite =
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6b4774b2b1c3..e13d6ed88fa6 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -34,6 +34,9 @@
// Expected to become stable.
#![feature(arbitrary_self_types)]
//
+// To be determined.
+#![feature(used_with_arg)]
+//
// `feature(derive_coerce_pointee)` is expected to become stable. Before Rust
// 1.84.0, it did not exist, so enable the predecessor features.
#![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))]
diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index a566fc3e7dcb..846583da9a2f 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -514,9 +514,9 @@ impl<T: ConfigOps + Default> Config<T> {
dev: *mut bindings::device,
opp_table: *mut bindings::opp_table,
opp: *mut bindings::dev_pm_opp,
- _data: *mut kernel::ffi::c_void,
+ _data: *mut c_void,
scaling_down: bool,
- ) -> kernel::ffi::c_int {
+ ) -> c_int {
from_result(|| {
// SAFETY: 'dev' is guaranteed by the C code to be valid.
let dev = unsafe { Device::get_device(dev) };
@@ -540,8 +540,8 @@ impl<T: ConfigOps + Default> Config<T> {
old_opp: *mut bindings::dev_pm_opp,
new_opp: *mut bindings::dev_pm_opp,
regulators: *mut *mut bindings::regulator,
- count: kernel::ffi::c_uint,
- ) -> kernel::ffi::c_int {
+ count: c_uint,
+ ) -> c_int {
from_result(|| {
// SAFETY: 'dev' is guaranteed by the C code to be valid.
let dev = unsafe { Device::get_device(dev) };
diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs
index d7e6e59e124b..69f1368a2151 100644
--- a/rust/kernel/sync/poll.rs
+++ b/rust/kernel/sync/poll.rs
@@ -9,9 +9,8 @@ use crate::{
fs::File,
prelude::*,
sync::{CondVar, LockClassKey},
- types::Opaque,
};
-use core::ops::Deref;
+use core::{marker::PhantomData, ops::Deref};
/// Creates a [`PollCondVar`] initialiser with the given name and a newly-created lock class.
#[macro_export]
@@ -23,58 +22,43 @@ macro_rules! new_poll_condvar {
};
}
-/// Wraps the kernel's `struct poll_table`.
+/// Wraps the kernel's `poll_table`.
///
/// # Invariants
///
-/// This struct contains a valid `struct poll_table`.
-///
-/// For a `struct poll_table` to be valid, its `_qproc` function must follow the safety
-/// requirements of `_qproc` functions:
-///
-/// * The `_qproc` function is given permission to enqueue a waiter to the provided `poll_table`
-/// during the call. Once the waiter is removed and an rcu grace period has passed, it must no
-/// longer access the `wait_queue_head`.
+/// The pointer must be null or reference a valid `poll_table`.
#[repr(transparent)]
-pub struct PollTable(Opaque<bindings::poll_table>);
+pub struct PollTable<'a> {
+ table: *mut bindings::poll_table,
+ _lifetime: PhantomData<&'a bindings::poll_table>,
+}
-impl PollTable {
- /// Creates a reference to a [`PollTable`] from a valid pointer.
+impl<'a> PollTable<'a> {
+ /// Creates a [`PollTable`] from a valid pointer.
///
/// # Safety
///
- /// The caller must ensure that for the duration of `'a`, the pointer will point at a valid poll
- /// table (as defined in the type invariants).
- ///
- /// The caller must also ensure that the `poll_table` is only accessed via the returned
- /// reference for the duration of `'a`.
- pub unsafe fn from_ptr<'a>(ptr: *mut bindings::poll_table) -> &'a mut PollTable {
- // SAFETY: The safety requirements guarantee the validity of the dereference, while the
- // `PollTable` type being transparent makes the cast ok.
- unsafe { &mut *ptr.cast() }
- }
-
- fn get_qproc(&self) -> bindings::poll_queue_proc {
- let ptr = self.0.get();
- // SAFETY: The `ptr` is valid because it originates from a reference, and the `_qproc`
- // field is not modified concurrently with this call since we have an immutable reference.
- unsafe { (*ptr)._qproc }
+ /// The pointer must be null or reference a valid `poll_table` for the duration of `'a`.
+ pub unsafe fn from_raw(table: *mut bindings::poll_table) -> Self {
+ // INVARIANTS: The safety requirements are the same as the struct invariants.
+ PollTable {
+ table,
+ _lifetime: PhantomData,
+ }
}
/// Register this [`PollTable`] with the provided [`PollCondVar`], so that it can be notified
/// using the condition variable.
- pub fn register_wait(&mut self, file: &File, cv: &PollCondVar) {
- if let Some(qproc) = self.get_qproc() {
- // SAFETY: The pointers to `file` and `self` need to be valid for the duration of this
- // call to `qproc`, which they are because they are references.
- //
- // The `cv.wait_queue_head` pointer must be valid until an rcu grace period after the
- // waiter is removed. The `PollCondVar` is pinned, so before `cv.wait_queue_head` can
- // be destroyed, the destructor must run. That destructor first removes all waiters,
- // and then waits for an rcu grace period. Therefore, `cv.wait_queue_head` is valid for
- // long enough.
- unsafe { qproc(file.as_ptr() as _, cv.wait_queue_head.get(), self.0.get()) };
- }
+ pub fn register_wait(&self, file: &File, cv: &PollCondVar) {
+ // SAFETY:
+ // * `file.as_ptr()` references a valid file for the duration of this call.
+ // * `self.table` is null or references a valid poll_table for the duration of this call.
+ // * Since `PollCondVar` is pinned, its destructor is guaranteed to run before the memory
+ // containing `cv.wait_queue_head` is invalidated. Since the destructor clears all
+ // waiters and then waits for an rcu grace period, it's guaranteed that
+ // `cv.wait_queue_head` remains valid for at least an rcu grace period after the removal
+ // of the last waiter.
+ unsafe { bindings::poll_wait(file.as_ptr(), cv.wait_queue_head.get(), self.table) }
}
}