Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust: generate bindings for helpers #359

Merged
merged 3 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,7 @@ rustfmt:
-o -path $(abs_objtree)/rust/test -prune \
| grep -Fv $(abs_srctree)/rust/alloc \
| grep -Fv $(abs_objtree)/rust/test \
| grep -Fv generated \
| xargs $(RUSTFMT) $(rustfmt_flags)

rustfmtcheck: rustfmt_flags = --check
Expand Down
1 change: 1 addition & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0

bindings_generated.rs
bindings_helpers_generated.rs
exports_*_generated.h
doc/
test/
31 changes: 23 additions & 8 deletions rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extra-$(CONFIG_RUST) += exports_core_generated.h

extra-$(CONFIG_RUST) += libmacros.so

extra-$(CONFIG_RUST) += bindings_generated.rs
extra-$(CONFIG_RUST) += bindings_generated.rs bindings_helpers_generated.rs
obj-$(CONFIG_RUST) += alloc.o kernel.o
extra-$(CONFIG_RUST) += exports_alloc_generated.h exports_kernel_generated.h

Expand All @@ -30,7 +30,7 @@ endif

quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
cmd_rustdoc = \
RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
OBJTREE=$(abspath $(objtree)) \
$(RUSTDOC) $(if $(rustdoc_host),,$(rust_cross_flags)) \
$(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags))) \
$(rustc_target_flags) -L $(objtree)/rust \
Expand Down Expand Up @@ -73,12 +73,13 @@ rustdoc-kernel: private rustc_target_flags = --extern alloc \
--extern macros=$(objtree)/rust/libmacros.so
rustdoc-kernel: $(srctree)/rust/kernel/lib.rs rustdoc-core \
rustdoc-macros rustdoc-compiler_builtins rustdoc-alloc \
$(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs FORCE
$(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs \
$(objtree)/rust/bindings_helpers_generated.rs FORCE
$(call if_changed,rustdoc)

quiet_cmd_rustc_test_library = RUSTC TL $<
cmd_rustc_test_library = \
RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
OBJTREE=$(abspath $(objtree)) \
$(RUSTC) $(filter-out --sysroot=%, $(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags)))) \
$(rustc_target_flags) --crate-type $(if $(rustc_test_library_proc),proc-macro,rlib) \
--out-dir $(objtree)/rust/test/ --cfg testlib \
Expand All @@ -95,7 +96,7 @@ rusttestlib-macros: $(srctree)/rust/macros/lib.rs rusttest-prepare FORCE

quiet_cmd_rustdoc_test = RUSTDOC T $<
cmd_rustdoc_test = \
RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
OBJTREE=$(abspath $(objtree)) \
$(RUSTDOC) --test $(filter-out --sysroot=%, $(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags)))) \
$(rustc_target_flags) $(rustdoc_test_target_flags) \
--sysroot $(objtree)/rust/test/sysroot $(rustdoc_test_quiet) \
Expand All @@ -107,7 +108,7 @@ quiet_cmd_rustdoc_test = RUSTDOC T $<
# so for the moment we skip `-Cpanic=abort`.
quiet_cmd_rustc_test = RUSTC T $<
cmd_rustc_test = \
RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
OBJTREE=$(abspath $(objtree)) \
$(RUSTC) --test $(filter-out --sysroot=%, $(filter-out -Cpanic=abort, $(filter-out --emit=%, $(rust_flags)))) \
$(rustc_target_flags) --out-dir $(objtree)/rust/test \
--sysroot $(objtree)/rust/test/sysroot \
Expand Down Expand Up @@ -230,6 +231,19 @@ $(objtree)/rust/bindings_generated.rs: $(srctree)/rust/kernel/bindings_helper.h
$(srctree)/rust/bindgen_parameters FORCE
$(call if_changed_dep,bindgen)

quiet_cmd_bindgen_helper = BINDGEN $@
cmd_bindgen_helper = \
$(BINDGEN) $< --blacklist-type '.*' --whitelist-var '' \
--whitelist-function 'rust_helper_.*' \
--use-core --with-derive-default --ctypes-prefix c_types \
--no-debug '.*' \
--size_t-is-usize -o $@ -- $(bindgen_c_flags_final) \
-I$(objtree)/rust/ -DMODULE; \
sed -Ei 's/pub fn rust_helper_([a-zA-Z0-9_]*)/\#[link_name="rust_helper_\1"]\n pub fn \1/g' $@

$(objtree)/rust/bindings_helpers_generated.rs: $(srctree)/rust/helpers.c FORCE
$(call if_changed_dep,bindgen_helper)

quiet_cmd_exports = EXPORTS $@
cmd_exports = \
$(NM) -p --defined-only $< \
Expand Down Expand Up @@ -267,7 +281,7 @@ $(objtree)/rust/libmacros.so: $(srctree)/rust/macros/lib.rs \

quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L $@
cmd_rustc_library = \
RUST_BINDINGS_FILE=$(abspath $(objtree)/rust/bindings_generated.rs) \
OBJTREE=$(abspath $(objtree)) \
$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
$(rust_flags) $(rust_cross_flags) $(rustc_target_flags) \
--crate-type rlib --out-dir $(objtree)/rust/ -L $(objtree)/rust/ \
Expand Down Expand Up @@ -305,7 +319,8 @@ $(objtree)/rust/kernel.o: private rustc_target_flags = --extern alloc \
--extern macros=$(objtree)/rust/libmacros.so
$(objtree)/rust/kernel.o: $(srctree)/rust/kernel/lib.rs $(objtree)/rust/alloc.o \
$(objtree)/rust/build_error.o \
$(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs FORCE
$(objtree)/rust/libmacros.so $(objtree)/rust/bindings_generated.rs \
$(objtree)/rust/bindings_helpers_generated.rs FORCE
$(call if_changed_dep,rustc_library)

# Targets that need to expand twice
Expand Down
23 changes: 12 additions & 11 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <linux/security.h>
#include <asm/io.h>

void rust_helper_BUG(void)
__noreturn void rust_helper_BUG(void)
{
BUG();
}
Expand Down Expand Up @@ -91,16 +91,16 @@ void rust_helper_writeq(u64 value, volatile void __iomem *addr)
EXPORT_SYMBOL_GPL(rust_helper_writeq);
#endif

void rust_helper_spin_lock_init(spinlock_t *lock, const char *name,
struct lock_class_key *key)
void rust_helper___spin_lock_init(spinlock_t *lock, const char *name,
struct lock_class_key *key)
{
#ifdef CONFIG_DEBUG_SPINLOCK
__spin_lock_init(lock, name, key);
#else
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 @@ -162,22 +162,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 @@ -200,11 +201,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
24 changes: 21 additions & 3 deletions rust/kernel/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,37 @@
#![cfg_attr(test, allow(deref_nullptr))]
#![cfg_attr(test, allow(unaligned_references))]
#![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))]

#[allow(
#![allow(
clippy::all,
non_camel_case_types,
non_upper_case_globals,
non_snake_case,
improper_ctypes,
unsafe_op_in_unsafe_fn
)]

mod bindings_raw {
// Use glob import here to expose all helpers.
// Symbols defined within the module will take precedence to the glob import.
pub use super::bindings_helper::*;
use crate::c_types;
include!(concat!(env!("OBJTREE"), "/rust/bindings_generated.rs"));
}

// When both a directly exposed symbol and a helper exists for the same function,
// the directly exposed symbol is preferred and the helper becomes dead code, so
// ignore the warning here.
#[allow(dead_code)]
mod bindings_helper {
// Import the generated bindings for types.
use super::bindings_raw::*;
use crate::c_types;
include!(env!("RUST_BINDINGS_FILE"));
include!(concat!(
env!("OBJTREE"),
"/rust/bindings_helpers_generated.rs"
));
}

pub use bindings_raw::*;

pub const GFP_KERNEL: gfp_t = BINDINGS_GFP_KERNEL;
Expand Down
25 changes: 7 additions & 18 deletions rust/kernel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,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 @@ -452,7 +449,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 @@ -496,28 +493,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
Loading