diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index c630e65098ed..2a16d5e64e6c 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -17,23 +17,35 @@ use macros::{pin_data, pinned_drop}; /// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call /// `bindings::__pci_register_driver` from `RegistrationOps::register` and /// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`. -pub trait RegistrationOps { +/// +/// # Safety +/// +/// A call to [`RegistrationOps::unregister`] for a given instance of `RegType` is only valid if a +/// preceding call to [`RegistrationOps::register`] has been successful. +pub unsafe trait RegistrationOps { /// The type that holds information about the registration. This is typically a struct defined /// by the C portion of the kernel. type RegType: Default; /// Registers a driver. /// + /// # Safety + /// /// On success, `reg` must remain pinned and valid until the matching call to /// [`RegistrationOps::unregister`]. - fn register( + unsafe fn register( reg: &Opaque, name: &'static CStr, module: &'static ThisModule, ) -> Result; /// Unregisters a driver previously registered with [`RegistrationOps::register`]. - fn unregister(reg: &Opaque); + /// + /// # Safety + /// + /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for + /// the same `reg`. + unsafe fn unregister(reg: &Opaque); } /// A [`Registration`] is a generic type that represents the registration of some driver type (e.g. @@ -68,7 +80,8 @@ impl Registration { // just been initialised above, so it's also valid for read. let drv = unsafe { &*(ptr as *const Opaque) }; - T::register(drv, name, module) + // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`. + unsafe { T::register(drv, name, module) } }), }) } @@ -77,7 +90,9 @@ impl Registration { #[pinned_drop] impl PinnedDrop for Registration { fn drop(self: Pin<&mut Self>) { - T::unregister(&self.reg); + // SAFETY: The existence of `self` guarantees that `self.reg` has previously been + // successfully registered with `T::register` + unsafe { T::unregister(&self.reg) }; } } diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index d5e7f0b15303..4c98b5b9aa1e 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -23,10 +23,12 @@ use kernel::prelude::*; /// An adapter for the registration of PCI drivers. pub struct Adapter(T); -impl driver::RegistrationOps for Adapter { +// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if +// a preceding call to `register` has been successful. +unsafe impl driver::RegistrationOps for Adapter { type RegType = bindings::pci_driver; - fn register( + unsafe fn register( pdrv: &Opaque, name: &'static CStr, module: &'static ThisModule, @@ -45,7 +47,7 @@ impl driver::RegistrationOps for Adapter { }) } - fn unregister(pdrv: &Opaque) { + unsafe fn unregister(pdrv: &Opaque) { // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. unsafe { bindings::pci_unregister_driver(pdrv.get()) } } diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 03287794f9d0..50e6b0421813 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -19,10 +19,12 @@ use core::ptr::addr_of_mut; /// An adapter for the registration of platform drivers. pub struct Adapter(T); -impl driver::RegistrationOps for Adapter { +// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if +// a preceding call to `register` has been successful. +unsafe impl driver::RegistrationOps for Adapter { type RegType = bindings::platform_driver; - fn register( + unsafe fn register( pdrv: &Opaque, name: &'static CStr, module: &'static ThisModule, @@ -44,7 +46,7 @@ impl driver::RegistrationOps for Adapter { to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) }) } - fn unregister(pdrv: &Opaque) { + unsafe fn unregister(pdrv: &Opaque) { // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. unsafe { bindings::platform_driver_unregister(pdrv.get()) }; }