Skip to content

Commit

Permalink
rust: use the generated helper bindings
Browse files Browse the repository at this point in the history
Signed-off-by: Gary Guo <gary@garyguo.net>
  • Loading branch information
nbdd0121 committed Jul 29, 2021
1 parent 0865643 commit e72fdb3
Show file tree
Hide file tree
Showing 15 changed files with 52 additions and 195 deletions.
19 changes: 10 additions & 9 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ unsigned long rust_helper_clear_user(void __user *to, unsigned long n)
return clear_user(to, n);
}

void rust_helper_spin_lock_init(spinlock_t *lock, const char *name,
void rust_helper___spin_lock_init(spinlock_t *lock, const char *name,
struct lock_class_key *key)
{
#ifdef CONFIG_DEBUG_SPINLOCK
Expand All @@ -41,7 +41,7 @@ void rust_helper_spin_lock_init(spinlock_t *lock, const char *name,
spin_lock_init(lock);
#endif
}
EXPORT_SYMBOL_GPL(rust_helper_spin_lock_init);
EXPORT_SYMBOL_GPL(rust_helper___spin_lock_init);

void rust_helper_spin_lock(spinlock_t *lock)
{
Expand Down Expand Up @@ -103,22 +103,23 @@ size_t rust_helper_copy_to_iter(const void *addr, size_t bytes, struct iov_iter
}
EXPORT_SYMBOL_GPL(rust_helper_copy_to_iter);

bool rust_helper_is_err(__force const void *ptr)
bool rust_helper_IS_ERR(__force const void *ptr)
{
return IS_ERR(ptr);
}
EXPORT_SYMBOL_GPL(rust_helper_is_err);
EXPORT_SYMBOL_GPL(rust_helper_IS_ERR);

long rust_helper_ptr_err(__force const void *ptr)
long rust_helper_PTR_ERR(__force const void *ptr)
{
return PTR_ERR(ptr);
}
EXPORT_SYMBOL_GPL(rust_helper_ptr_err);
EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR);

const char *rust_helper_errname(int err)
{
return errname(err);
}
EXPORT_SYMBOL_GPL(rust_helper_errname);

void rust_helper_mutex_lock(struct mutex *lock)
{
Expand All @@ -141,11 +142,11 @@ rust_helper_platform_set_drvdata(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(rust_helper_platform_set_drvdata);

refcount_t rust_helper_refcount_new(void)
refcount_t rust_helper_REFCOUNT_INIT(int n)
{
return (refcount_t)REFCOUNT_INIT(1);
return (refcount_t)REFCOUNT_INIT(n);
}
EXPORT_SYMBOL_GPL(rust_helper_refcount_new);
EXPORT_SYMBOL_GPL(rust_helper_REFCOUNT_INIT);

void rust_helper_refcount_inc(refcount_t *r)
{
Expand Down
25 changes: 7 additions & 18 deletions rust/kernel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,8 @@ impl Error {

impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
extern "C" {
fn rust_helper_errname(err: c_types::c_int) -> *const c_types::c_char;
}
// SAFETY: FFI call.
let name = unsafe { rust_helper_errname(-self.0) };
let name = unsafe { bindings::errname(-self.0) };

if name.is_null() {
// Print out number if no name can be found.
Expand Down Expand Up @@ -268,7 +265,7 @@ where
/// ) -> c_types::c_int {
/// from_kernel_result! {
/// let ptr = devm_alloc(pdev)?;
/// rust_helper_platform_set_drvdata(pdev, ptr);
/// bindings::platform_set_drvdata(pdev, ptr);
/// Ok(0)
/// }
/// }
Expand Down Expand Up @@ -312,28 +309,20 @@ macro_rules! from_kernel_result {
// TODO: remove `dead_code` marker once an in-kernel client is available.
#[allow(dead_code)]
pub(crate) fn from_kernel_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
extern "C" {
#[allow(improper_ctypes)]
fn rust_helper_is_err(ptr: *const c_types::c_void) -> bool;

#[allow(improper_ctypes)]
fn rust_helper_ptr_err(ptr: *const c_types::c_void) -> c_types::c_long;
}

// CAST: casting a pointer to `*const c_types::c_void` is always valid.
let const_ptr: *const c_types::c_void = ptr.cast();
// SAFETY: the FFI function does not deref the pointer.
if unsafe { rust_helper_is_err(const_ptr) } {
if unsafe { bindings::IS_ERR(const_ptr) } {
// SAFETY: the FFI function does not deref the pointer.
let err = unsafe { rust_helper_ptr_err(const_ptr) };
// CAST: if `rust_helper_is_err()` returns `true`,
// then `rust_helper_ptr_err()` is guaranteed to return a
let err = unsafe { bindings::PTR_ERR(const_ptr) };
// CAST: if `IS_ERR()` returns `true`,
// then `PTR_ERR()` is guaranteed to return a
// negative value greater-or-equal to `-bindings::MAX_ERRNO`,
// which always fits in an `i16`, as per the invariant above.
// And an `i16` always fits in an `i32`. So casting `err` to
// an `i32` can never overflow, and is always valid.
//
// SAFETY: `rust_helper_is_err()` ensures `err` is a
// SAFETY: `IS_ERR()` ensures `err` is a
// negative value greater-or-equal to `-bindings::MAX_ERRNO`
return Err(unsafe { Error::from_kernel_errno_unchecked(err as i32) });
}
Expand Down
20 changes: 3 additions & 17 deletions rust/kernel/iov_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,12 @@
//! C header: [`include/linux/uio.h`](../../../../include/linux/uio.h)
use crate::{
bindings, c_types,
bindings,
error::Error,
io_buffer::{IoBufferReader, IoBufferWriter},
Result,
};

extern "C" {
fn rust_helper_copy_to_iter(
addr: *const c_types::c_void,
bytes: usize,
i: *mut bindings::iov_iter,
) -> usize;

fn rust_helper_copy_from_iter(
addr: *mut c_types::c_void,
bytes: usize,
i: *mut bindings::iov_iter,
) -> usize;
}

/// Wraps the kernel's `struct iov_iter`.
///
/// # Invariants
Expand Down Expand Up @@ -70,7 +56,7 @@ impl IoBufferWriter for IovIter {
}

unsafe fn write_raw(&mut self, data: *const u8, len: usize) -> Result {
let res = unsafe { rust_helper_copy_to_iter(data as _, len, self.ptr) };
let res = unsafe { bindings::copy_to_iter(data as _, len, self.ptr) };
if res != len {
Err(Error::EFAULT)
} else {
Expand All @@ -85,7 +71,7 @@ impl IoBufferReader for IovIter {
}

unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result {
let res = unsafe { rust_helper_copy_from_iter(out as _, len, self.ptr) };
let res = unsafe { bindings::copy_from_iter(out as _, len, self.ptr) };
if res != len {
Err(Error::EFAULT)
} else {
Expand Down
20 changes: 3 additions & 17 deletions rust/kernel/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ use crate::{
};
use core::{marker::PhantomData, ptr};

extern "C" {
#[allow(improper_ctypes)]
fn rust_helper_alloc_pages(
gfp_mask: bindings::gfp_t,
order: c_types::c_uint,
) -> *mut bindings::page;

#[allow(improper_ctypes)]
fn rust_helper_kmap(page: *mut bindings::page) -> *mut c_types::c_void;

#[allow(improper_ctypes)]
fn rust_helper_kunmap(page: *mut bindings::page);
}

/// A set of physical pages.
///
/// `Pages` holds a reference to a set of pages of order `ORDER`. Having the order as a generic
Expand All @@ -42,7 +28,7 @@ impl<const ORDER: u32> Pages<ORDER> {
// TODO: Consider whether we want to allow callers to specify flags.
// SAFETY: This only allocates pages. We check that it succeeds in the next statement.
let pages = unsafe {
rust_helper_alloc_pages(
bindings::alloc_pages(
bindings::GFP_KERNEL | bindings::__GFP_ZERO | bindings::__GFP_HIGHMEM,
ORDER,
)
Expand Down Expand Up @@ -141,7 +127,7 @@ impl<const ORDER: u32> Pages<ORDER> {
let page = unsafe { self.pages.add(index) };

// SAFETY: `page` is valid based on the checks above.
let ptr = unsafe { rust_helper_kmap(page) };
let ptr = unsafe { bindings::kmap(page) };
if ptr.is_null() {
return None;
}
Expand Down Expand Up @@ -171,6 +157,6 @@ impl Drop for PageMapping<'_> {
fn drop(&mut self) {
// SAFETY: An instance of `PageMapping` is created only when `kmap` succeeded for the given
// page, so it is safe to unmap it here.
unsafe { rust_helper_kunmap(self.page) };
unsafe { bindings::kunmap(self.page) };
}
}
17 changes: 2 additions & 15 deletions rust/kernel/platdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,6 @@ pub struct Registration {
// (it is fine for multiple threads to have a shared reference to it).
unsafe impl Sync for Registration {}

extern "C" {
#[allow(improper_ctypes)]
fn rust_helper_platform_get_drvdata(
pdev: *const bindings::platform_device,
) -> *mut c_types::c_void;

#[allow(improper_ctypes)]
fn rust_helper_platform_set_drvdata(
pdev: *mut bindings::platform_device,
data: *mut c_types::c_void,
);
}

extern "C" fn probe_callback<P: PlatformDriver>(
pdev: *mut bindings::platform_device,
) -> c_types::c_int {
Expand All @@ -52,7 +39,7 @@ extern "C" fn probe_callback<P: PlatformDriver>(
let drv_data = drv_data.into_pointer() as *mut c_types::c_void;
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
unsafe {
rust_helper_platform_set_drvdata(pdev, drv_data);
bindings::platform_set_drvdata(pdev, drv_data);
}
Ok(0)
}
Expand All @@ -65,7 +52,7 @@ extern "C" fn remove_callback<P: PlatformDriver>(
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
let device_id = unsafe { (*pdev).id };
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
let ptr = unsafe { rust_helper_platform_get_drvdata(pdev) };
let ptr = unsafe { bindings::platform_get_drvdata(pdev) };
// SAFETY:
// - we allocated this pointer using `P::DrvData::into_pointer`,
// so it is safe to turn back into a `P::DrvData`.
Expand Down
7 changes: 1 addition & 6 deletions rust/kernel/power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
use crate::{bindings, c_types, from_kernel_result, sync::Ref, types::PointerWrapper, Result};
use core::{marker::PhantomData, ops::Deref};

extern "C" {
#[allow(improper_ctypes)]
fn rust_helper_dev_get_drvdata(dev: *mut bindings::device) -> *mut c_types::c_void;
}

/// Corresponds to the kernel's `struct dev_pm_ops`.
///
/// It is meant to be implemented by drivers that support power-management operations.
Expand Down Expand Up @@ -47,7 +42,7 @@ macro_rules! pm_callback {
) -> c_types::c_int {
from_kernel_result! {
// SAFETY: `dev` is valid as it was passed in by the C portion.
let ptr = unsafe { rust_helper_dev_get_drvdata(dev) };
let ptr = unsafe { bindings::dev_get_drvdata(dev) };
// SAFETY: By the safety requirements of `OpsTable::build`, we know that `ptr` came
// from a previous call to `T::Data::into_pointer`.
let data = unsafe { T::Data::borrow(ptr) };
Expand Down
10 changes: 1 addition & 9 deletions rust/kernel/rbtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@ use core::{
ptr::{addr_of_mut, NonNull},
};

extern "C" {
fn rust_helper_rb_link_node(
node: *mut bindings::rb_node,
parent: *const bindings::rb_node,
rb_link: *mut *mut bindings::rb_node,
);
}

struct Node<K, V> {
links: bindings::rb_node,
key: K,
Expand Down Expand Up @@ -289,7 +281,7 @@ impl<K, V> RBTree<K, V> {
// "forgot" it with `Box::into_raw`.
// SAFETY: All pointers are non-null and valid (`*new_link` is null, but `new_link` is a
// mutable reference).
unsafe { rust_helper_rb_link_node(node_links, parent, new_link) };
unsafe { bindings::rb_link_node(node_links, parent, new_link) };

// SAFETY: All pointers are valid. `node` has just been inserted into the tree.
unsafe { bindings::rb_insert_color(node_links, &mut self.root) };
Expand Down
33 changes: 5 additions & 28 deletions rust/kernel/security.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,13 @@
//!
//! C header: [`include/linux/security.h`](../../../../include/linux/security.h).
use crate::{bindings, c_types, error::Error, file::File, task::Task, Result};

extern "C" {
#[allow(improper_ctypes)]
fn rust_helper_security_binder_set_context_mgr(
mgr: *mut bindings::task_struct,
) -> c_types::c_int;
#[allow(improper_ctypes)]
fn rust_helper_security_binder_transaction(
from: *mut bindings::task_struct,
to: *mut bindings::task_struct,
) -> c_types::c_int;
#[allow(improper_ctypes)]
fn rust_helper_security_binder_transfer_binder(
from: *mut bindings::task_struct,
to: *mut bindings::task_struct,
) -> c_types::c_int;
#[allow(improper_ctypes)]
fn rust_helper_security_binder_transfer_file(
from: *mut bindings::task_struct,
to: *mut bindings::task_struct,
file: *mut bindings::file,
) -> c_types::c_int;
}
use crate::{bindings, error::Error, file::File, task::Task, Result};

/// Calls the security modules to determine if the given task can become the manager of a binder
/// context.
pub fn binder_set_context_mgr(mgr: &Task) -> Result {
// SAFETY: By the `Task` invariants, `mgr.ptr` is valid.
let ret = unsafe { rust_helper_security_binder_set_context_mgr(mgr.ptr) };
let ret = unsafe { bindings::security_binder_set_context_mgr(mgr.ptr) };
if ret != 0 {
Err(Error::from_kernel_errno(ret))
} else {
Expand All @@ -45,7 +22,7 @@ pub fn binder_set_context_mgr(mgr: &Task) -> Result {
/// task `to`.
pub fn binder_transaction(from: &Task, to: &Task) -> Result {
// SAFETY: By the `Task` invariants, `from.ptr` and `to.ptr` are valid.
let ret = unsafe { rust_helper_security_binder_transaction(from.ptr, to.ptr) };
let ret = unsafe { bindings::security_binder_transaction(from.ptr, to.ptr) };
if ret != 0 {
Err(Error::from_kernel_errno(ret))
} else {
Expand All @@ -57,7 +34,7 @@ pub fn binder_transaction(from: &Task, to: &Task) -> Result {
/// (owned by itself or other processes) to task `to` through a binder transaction.
pub fn binder_transfer_binder(from: &Task, to: &Task) -> Result {
// SAFETY: By the `Task` invariants, `from.ptr` and `to.ptr` are valid.
let ret = unsafe { rust_helper_security_binder_transfer_binder(from.ptr, to.ptr) };
let ret = unsafe { bindings::security_binder_transfer_binder(from.ptr, to.ptr) };
if ret != 0 {
Err(Error::from_kernel_errno(ret))
} else {
Expand All @@ -70,7 +47,7 @@ pub fn binder_transfer_binder(from: &Task, to: &Task) -> Result {
pub fn binder_transfer_file(from: &Task, to: &Task, file: &File) -> Result {
// SAFETY: By the `Task` invariants, `from.ptr` and `to.ptr` are valid. Similarly, by the
// `File` invariants, `file.ptr` is also valid.
let ret = unsafe { rust_helper_security_binder_transfer_file(from.ptr, to.ptr, file.ptr) };
let ret = unsafe { bindings::security_binder_transfer_file(from.ptr, to.ptr, file.ptr) };
if ret != 0 {
Err(Error::from_kernel_errno(ret))
} else {
Expand Down
12 changes: 3 additions & 9 deletions rust/kernel/sync/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ use core::{
ptr::NonNull,
};

extern "C" {
fn rust_helper_refcount_new() -> bindings::refcount_t;
fn rust_helper_refcount_inc(r: *mut bindings::refcount_t);
fn rust_helper_refcount_dec_and_test(r: *mut bindings::refcount_t) -> bool;
}

/// A reference-counted pointer to an instance of `T`.
///
/// The reference count is incremented when new instances of [`Ref`] are created, and decremented
Expand Down Expand Up @@ -86,7 +80,7 @@ impl<T> Ref<T> {
// INVARIANT: The refcount is initialised to a non-zero value.
let mut inner = Box::try_new(RefInner {
// SAFETY: Just an FFI call that returns a `refcount_t` initialised to 1.
refcount: UnsafeCell::new(unsafe { rust_helper_refcount_new() }),
refcount: UnsafeCell::new(unsafe { bindings::REFCOUNT_INIT(1) }),
data: contents,
})?;

Expand Down Expand Up @@ -169,7 +163,7 @@ impl<T: ?Sized> Clone for Ref<T> {
// INVARIANT: C `refcount_inc` saturates the refcount, so it cannot overflow to zero.
// SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
// safe to increment the refcount.
unsafe { rust_helper_refcount_inc(self.ptr.as_ref().refcount.get()) };
unsafe { bindings::refcount_inc(self.ptr.as_ref().refcount.get()) };
Self {
ptr: self.ptr,
_p: PhantomData,
Expand All @@ -196,7 +190,7 @@ impl<T: ?Sized> Drop for Ref<T> {
// INVARIANT: If the refcount reaches zero, there are no other instances of `Ref`, and
// this instance is being dropped, so the broken invariant is not observable.
// SAFETY: Also by the type invariant, we are allowed to decrement the refcount.
let is_zero = unsafe { rust_helper_refcount_dec_and_test(refcount) };
let is_zero = unsafe { bindings::refcount_dec_and_test(refcount) };
if is_zero {
// The count reached zero, we must free the memory.
//
Expand Down
Loading

0 comments on commit e72fdb3

Please sign in to comment.