From: Wedson Almeida Filho
maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5J75G
CVE: NA
Reference: https://lore.kernel.org/rust-for-linux/CANiq72nDcJLSB3pLhkdqGdLitfmqqCUVVfkY5EjP9AcwVv9B4A@mail.gmail.com/T/#t
--------------------------------
The `kernel` crate currently includes all the abstractions that wrap
kernel features written in C.
These abstractions call the C side of the kernel via the generated
bindings with the `bindgen` tool. Modules developed in Rust should
never call the bindings themselves.
In the future, as the abstractions grow in number, we may need
to split this crate into several, possibly following a similar
subdivision in subsystems as the kernel itself and/or moving
the code to the actual subsystems.
Co-developed-by: Alex Gaynor
Signed-off-by: Alex Gaynor
Co-developed-by: Geoffrey Thomas
Signed-off-by: Geoffrey Thomas
Co-developed-by: Finn Behrens
Signed-off-by: Finn Behrens
Co-developed-by: Adam Bratschi-Kaye
Signed-off-by: Adam Bratschi-Kaye
Co-developed-by: Michael Ellerman
Signed-off-by: Michael Ellerman
Co-developed-by: Sumera Priyadarsini
Signed-off-by: Sumera Priyadarsini
Co-developed-by: Sven Van Asbroeck
Signed-off-by: Sven Van Asbroeck
Co-developed-by: Gary Guo
Signed-off-by: Gary Guo
Co-developed-by: Boris-Chengbiao Zhou
Signed-off-by: Boris-Chengbiao Zhou
Co-developed-by: Boqun Feng
Signed-off-by: Boqun Feng
Co-developed-by: Fox Chen
Signed-off-by: Fox Chen
Co-developed-by: Dan Robertson
Signed-off-by: Dan Robertson
Co-developed-by: Viktor Garske
Signed-off-by: Viktor Garske
Co-developed-by: Dariusz Sosnowski
Signed-off-by: Dariusz Sosnowski
Co-developed-by: Léo Lanteri Thauvin
Signed-off-by: Léo Lanteri Thauvin
Co-developed-by: Niklas Mohrin
Signed-off-by: Niklas Mohrin
Co-developed-by: Gioh Kim
Signed-off-by: Gioh Kim
Co-developed-by: Daniel Xu
Signed-off-by: Daniel Xu
Co-developed-by: Milan Landaverde
Signed-off-by: Milan Landaverde
Co-developed-by: Morgan Bartlett
Signed-off-by: Morgan Bartlett
Co-developed-by: Maciej Falkowski
Signed-off-by: Maciej Falkowski
Co-developed-by: Jiapeng Chong
Signed-off-by: Jiapeng Chong
Co-developed-by: Nándor István Krácser
Signed-off-by: Nándor István Krácser
Co-developed-by: David Gow
Signed-off-by: David Gow
Signed-off-by: Wedson Almeida Filho
Co-developed-by: Miguel Ojeda
Signed-off-by: Miguel Ojeda
Signed-off-by: Weilong Chen
---
rust/kernel/allocator.rs | 65 +++
rust/kernel/amba.rs | 257 ++++++++++
rust/kernel/bindings.rs | 47 ++
rust/kernel/bindings_helper.h | 46 ++
rust/kernel/build_assert.rs | 82 ++++
rust/kernel/c_types.rs | 119 +++++
rust/kernel/chrdev.rs | 207 ++++++++
rust/kernel/clk.rs | 79 ++++
rust/kernel/cred.rs | 46 ++
rust/kernel/device.rs | 546 +++++++++++++++++++++
rust/kernel/driver.rs | 442 +++++++++++++++++
rust/kernel/error.rs | 565 ++++++++++++++++++++++
rust/kernel/file.rs | 860 ++++++++++++++++++++++++++++++++++
rust/kernel/gpio.rs | 478 +++++++++++++++++++
rust/kernel/hwrng.rs | 242 ++++++++++
rust/kernel/io_buffer.rs | 153 ++++++
rust/kernel/io_mem.rs | 275 +++++++++++
rust/kernel/iov_iter.rs | 81 ++++
rust/kernel/irq.rs | 411 ++++++++++++++++
rust/kernel/kasync.rs | 6 +
rust/kernel/kasync/net.rs | 322 +++++++++++++
rust/kernel/kunit.rs | 91 ++++
rust/kernel/lib.rs | 261 +++++++++++
rust/kernel/linked_list.rs | 247 ++++++++++
rust/kernel/miscdev.rs | 291 ++++++++++++
rust/kernel/mm.rs | 149 ++++++
rust/kernel/module_param.rs | 498 ++++++++++++++++++++
rust/kernel/net.rs | 392 ++++++++++++++++
rust/kernel/net/filter.rs | 447 ++++++++++++++++++
rust/kernel/of.rs | 63 +++
rust/kernel/pages.rs | 144 ++++++
rust/kernel/platform.rs | 223 +++++++++
rust/kernel/power.rs | 118 +++++
rust/kernel/prelude.rs | 36 ++
rust/kernel/print.rs | 405 ++++++++++++++++
rust/kernel/random.rs | 42 ++
rust/kernel/raw_list.rs | 361 ++++++++++++++
rust/kernel/rbtree.rs | 563 ++++++++++++++++++++++
rust/kernel/revocable.rs | 161 +++++++
rust/kernel/security.rs | 38 ++
rust/kernel/static_assert.rs | 38 ++
rust/kernel/std_vendor.rs | 160 +++++++
rust/kernel/str.rs | 597 +++++++++++++++++++++++
rust/kernel/sysctl.rs | 199 ++++++++
rust/kernel/task.rs | 175 +++++++
rust/kernel/types.rs | 679 +++++++++++++++++++++++++++
rust/kernel/user_ptr.rs | 175 +++++++
47 files changed, 11882 insertions(+)
create mode 100644 rust/kernel/allocator.rs
create mode 100644 rust/kernel/amba.rs
create mode 100644 rust/kernel/bindings.rs
create mode 100644 rust/kernel/bindings_helper.h
create mode 100644 rust/kernel/build_assert.rs
create mode 100644 rust/kernel/c_types.rs
create mode 100644 rust/kernel/chrdev.rs
create mode 100644 rust/kernel/clk.rs
create mode 100644 rust/kernel/cred.rs
create mode 100644 rust/kernel/device.rs
create mode 100644 rust/kernel/driver.rs
create mode 100644 rust/kernel/error.rs
create mode 100644 rust/kernel/file.rs
create mode 100644 rust/kernel/gpio.rs
create mode 100644 rust/kernel/hwrng.rs
create mode 100644 rust/kernel/io_buffer.rs
create mode 100644 rust/kernel/io_mem.rs
create mode 100644 rust/kernel/iov_iter.rs
create mode 100644 rust/kernel/irq.rs
create mode 100644 rust/kernel/kasync.rs
create mode 100644 rust/kernel/kasync/net.rs
create mode 100644 rust/kernel/kunit.rs
create mode 100644 rust/kernel/lib.rs
create mode 100644 rust/kernel/linked_list.rs
create mode 100644 rust/kernel/miscdev.rs
create mode 100644 rust/kernel/mm.rs
create mode 100644 rust/kernel/module_param.rs
create mode 100644 rust/kernel/net.rs
create mode 100644 rust/kernel/net/filter.rs
create mode 100644 rust/kernel/of.rs
create mode 100644 rust/kernel/pages.rs
create mode 100644 rust/kernel/platform.rs
create mode 100644 rust/kernel/power.rs
create mode 100644 rust/kernel/prelude.rs
create mode 100644 rust/kernel/print.rs
create mode 100644 rust/kernel/random.rs
create mode 100644 rust/kernel/raw_list.rs
create mode 100644 rust/kernel/rbtree.rs
create mode 100644 rust/kernel/revocable.rs
create mode 100644 rust/kernel/security.rs
create mode 100644 rust/kernel/static_assert.rs
create mode 100644 rust/kernel/std_vendor.rs
create mode 100644 rust/kernel/str.rs
create mode 100644 rust/kernel/sysctl.rs
create mode 100644 rust/kernel/task.rs
create mode 100644 rust/kernel/types.rs
create mode 100644 rust/kernel/user_ptr.rs
diff --git a/rust/kernel/allocator.rs b/rust/kernel/allocator.rs
new file mode 100644
index 000000000000..4c5d2fc6f206
--- /dev/null
+++ b/rust/kernel/allocator.rs
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Allocator support.
+
+use core::alloc::{GlobalAlloc, Layout};
+use core::ptr;
+
+use crate::bindings;
+use crate::c_types;
+
+struct KernelAllocator;
+
+unsafe impl GlobalAlloc for KernelAllocator {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ // `krealloc()` is used instead of `kmalloc()` because the latter is
+ // an inline function and cannot be bound to as a result.
+ unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 }
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
+ unsafe {
+ bindings::kfree(ptr as *const c_types::c_void);
+ }
+ }
+}
+
+#[global_allocator]
+static ALLOCATOR: KernelAllocator = KernelAllocator;
+
+// `rustc` only generates these for some crate types. Even then, we would need
+// to extract the object file that has them from the archive. For the moment,
+// let's generate them ourselves instead.
+//
+// Note that `#[no_mangle]` implies exported too, nowadays.
+#[no_mangle]
+fn __rust_alloc(size: usize, _align: usize) -> *mut u8 {
+ unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 }
+}
+
+#[no_mangle]
+fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
+ unsafe { bindings::kfree(ptr as *const c_types::c_void) };
+}
+
+#[no_mangle]
+fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 {
+ unsafe {
+ bindings::krealloc(
+ ptr as *const c_types::c_void,
+ new_size,
+ bindings::GFP_KERNEL,
+ ) as *mut u8
+ }
+}
+
+#[no_mangle]
+fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 {
+ unsafe {
+ bindings::krealloc(
+ core::ptr::null(),
+ size,
+ bindings::GFP_KERNEL | bindings::__GFP_ZERO,
+ ) as *mut u8
+ }
+}
diff --git a/rust/kernel/amba.rs b/rust/kernel/amba.rs
new file mode 100644
index 000000000000..7ca5358d2580
--- /dev/null
+++ b/rust/kernel/amba.rs
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Amba devices and drivers.
+//!
+//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
+
+use crate::{
+ bindings, c_types, device, driver, error::from_kernel_result, io_mem::Resource, power,
+ str::CStr, to_result, types::PointerWrapper, Result, ThisModule,
+};
+
+/// A registration of an amba driver.
+pub type Registration = driver::Registration>;
+
+/// Id of an Amba device.
+#[derive(Clone, Copy)]
+pub struct DeviceId {
+ /// Device id.
+ pub id: u32,
+
+ /// Mask that identifies which bits are valid in the device id.
+ pub mask: u32,
+}
+
+// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `amba_id::data`.
+unsafe impl const driver::RawDeviceId for DeviceId {
+ type RawType = bindings::amba_id;
+ const ZERO: Self::RawType = bindings::amba_id {
+ id: 0,
+ mask: 0,
+ data: core::ptr::null_mut(),
+ };
+
+ fn to_rawid(&self, offset: isize) -> Self::RawType {
+ bindings::amba_id {
+ id: self.id,
+ mask: self.mask,
+ data: offset as _,
+ }
+ }
+}
+
+/// An amba driver.
+pub trait Driver {
+ /// Data stored on device by driver.
+ type Data: PointerWrapper + Send + Sync + driver::DeviceRemoval = ();
+
+ /// The type that implements the power-management operations.
+ ///
+ /// The default is a type that implements no power-management operations. Drivers that do
+ /// implement them need to specify the type (commonly [`Self`]).
+ type PowerOps: power::Operations = power::NoOperations;
+
+ /// The type holding information about each device id supported by the driver.
+ type IdInfo: 'static = ();
+
+ /// The table of device ids supported by the driver.
+ const ID_TABLE: Option> = None;
+
+ /// Probes for the device with the given id.
+ fn probe(dev: &mut Device, id_info: Option<&Self::IdInfo>) -> Result;
+
+ /// Cleans any resources up that are associated with the device.
+ ///
+ /// This is called when the driver is detached from the device.
+ fn remove(_data: &Self::Data) {}
+}
+
+/// An adapter for the registration of Amba drivers.
+pub struct Adapter(T);
+
+impl driver::DriverOps for Adapter {
+ type RegType = bindings::amba_driver;
+
+ unsafe fn register(
+ reg: *mut bindings::amba_driver,
+ name: &'static CStr,
+ module: &'static ThisModule,
+ ) -> Result {
+ // SAFETY: By the safety requirements of this function (defined in the trait definition),
+ // `reg` is non-null and valid.
+ let amba = unsafe { &mut *reg };
+ amba.drv.name = name.as_char_ptr();
+ amba.drv.owner = module.0;
+ amba.probe = Some(probe_callback::);
+ amba.remove = Some(remove_callback::);
+ if let Some(t) = T::ID_TABLE {
+ amba.id_table = t.as_ref();
+ }
+ if cfg!(CONFIG_PM) {
+ // SAFETY: `probe_callback` sets the driver data after calling `T::Data::into_pointer`,
+ // and we guarantee that `T::Data` is the same as `T::PowerOps::Data` by a constraint
+ // in the type declaration.
+ amba.drv.pm = unsafe { power::OpsTable::::build() };
+ }
+ // SAFETY: By the safety requirements of this function, `reg` is valid and fully
+ // initialised.
+ to_result(|| unsafe { bindings::amba_driver_register(reg) })
+ }
+
+ unsafe fn unregister(reg: *mut bindings::amba_driver) {
+ // SAFETY: By the safety requirements of this function (defined in the trait definition),
+ // `reg` was passed (and updated) by a previous successful call to `amba_driver_register`.
+ unsafe { bindings::amba_driver_unregister(reg) };
+ }
+}
+
+unsafe extern "C" fn probe_callback(
+ adev: *mut bindings::amba_device,
+ aid: *const bindings::amba_id,
+) -> c_types::c_int {
+ from_kernel_result! {
+ // SAFETY: `adev` is valid by the contract with the C code. `dev` is alive only for the
+ // duration of this call, so it is guaranteed to remain alive for the lifetime of `dev`.
+ let mut dev = unsafe { Device::from_ptr(adev) };
+ // SAFETY: `aid` is valid by the requirements the contract with the C code.
+ let offset = unsafe { (*aid).data };
+ let info = if offset.is_null() {
+ None
+ } else {
+ // SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`,
+ // which guarantees that the resulting pointer is within the table.
+ let ptr = unsafe { aid.cast::().offset(offset as _).cast::