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

Add XArray abstraction #1019

Draft
wants to merge 37 commits into
base: rust-dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
520a56a
rust: allocator: Prevents mis-aligned allocation
fbq Jun 13, 2023
3d8d9bc
rust: make `UnsafeCell` the outer type in `Opaque`
Darksonn Jun 14, 2023
7671527
rust: types: make `Opaque` be `!Unpin`
Jun 30, 2023
0ad204c
kbuild: rust_is_available: remove -v option
masahir0y Jun 16, 2023
70a61eb
kbuild: rust_is_available: fix version check when CC has multiple arg…
ruscur Jun 16, 2023
a250bde
docs: rust: add paragraph about finding a suitable `libclang`
ojeda Jun 16, 2023
00383f7
kbuild: rust_is_available: print docs reference
ojeda Jun 16, 2023
8b2e73a
kbuild: rust_is_available: add check for `bindgen` invocation
ojeda Jun 16, 2023
eb9199d
kbuild: rust_is_available: check that environment variables are set
ojeda Jun 16, 2023
6bed841
kbuild: rust_is_available: fix confusion when a version appears in th…
ojeda Jun 16, 2023
600eb66
kbuild: rust_is_available: normalize version matching
ojeda Jun 16, 2023
6d4220b
kbuild: rust_is_available: handle failures calling `$RUSTC`/`$BINDGEN`
ojeda Jun 16, 2023
10452fc
kbuild: rust_is_available: check that output looks as expected
ojeda Jun 16, 2023
6a4e6dc
kbuild: rust_is_available: add test suite
ojeda Jun 16, 2023
f2f2787
rust: alloc: Add realloc and alloc_zeroed to the GlobalAlloc impl
fbq Jun 25, 2023
53dd54f
rust: bindgen: upgrade to 0.65.1
Shinyzenith Jun 12, 2023
02ddf5a
rust: init: make doctests compilable/testable
ojeda Jun 14, 2023
276f14d
rust: str: make doctests compilable/testable
ojeda Jun 14, 2023
c30db85
rust: sync: make doctests compilable/testable
ojeda Jun 14, 2023
4009de1
rust: types: make doctests compilable/testable
ojeda Jun 14, 2023
e9e95cd
rust: support running Rust documentation tests as KUnit ones
ojeda Jun 14, 2023
eff7a66
MAINTAINERS: add Rust KUnit files to the KUnit entry
ojeda Jun 14, 2023
72fbe4a
rust: macros: fix redefine const_name in `vtable`
cqs21 Jun 26, 2023
8e87a0d
rust: macros: add `paste!` proc macro
nbdd0121 Jun 28, 2023
7c6e564
arm64: rust: Enable Rust support for AArch64
JamieCunliffe Jun 6, 2023
522ba05
arm64: rust: Enable PAC support for Rust.
JamieCunliffe Jun 6, 2023
b1555e1
arm64: Restrict Rust support to little endian only.
JamieCunliffe Jun 6, 2023
19b33fc
rust: bindgen: update installation instructions
matthewtgilbride Jun 29, 2023
c1c510f
rust: xarray: Add an abstraction for XArray
asahilina Jun 27, 2023
91f4147
rust: xarray: add rudimentary doctest
matthewtgilbride Jun 27, 2023
6c19acb
rust: xarray: add `get_mutable` and `find_mut`
matthewtgilbride Jun 27, 2023
3016eac
rust: xarray: add reservation mechanism
asahilina Jun 27, 2023
90ddba2
Why does this cuase NULL pointer dereference?
matthewtgilbride Jul 2, 2023
702746d
Just me thrashing about - figuring out NPE
matthewtgilbride Jul 4, 2023
976067b
rust: delete `ForeignOwnable::borrow_mut`
Darksonn Jul 6, 2023
ac520c2
rust: add improved version of `ForeignOwnable::borrow_mut`
Darksonn Jul 10, 2023
642ff49
rust: xarray: figure out pin and get_scoped
matthewtgilbride Jul 17, 2023
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
2 changes: 1 addition & 1 deletion Documentation/process/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ you probably needn't concern yourself with pcmciautils.
GNU C 5.1 gcc --version
Clang/LLVM (optional) 11.0.0 clang --version
Rust (optional) 1.68.2 rustc --version
bindgen (optional) 0.56.0 bindgen --version
bindgen (optional) 0.65.1 bindgen --version
GNU make 3.82 make --version
bash 4.2 bash --version
binutils 2.25 ld -v
Expand Down
1 change: 1 addition & 0 deletions Documentation/rust/arch-support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
============ ================ ==============================================
Architecture Level of support Constraints
============ ================ ==============================================
``arm64`` Maintained Little Endian only.
``um`` Maintained ``x86_64`` only.
``x86`` Maintained ``x86_64`` only.
============ ================ ==============================================
Expand Down
19 changes: 18 additions & 1 deletion Documentation/rust/quick-start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,24 @@ the ``bindgen`` tool. A particular version is required.

Install it via (note that this will download and build the tool from source)::

cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen
cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen-cli
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also discovered this yesterday. Could you send this patch directly to the mailing list?

@ojeda probably should take this as a fix.

Copy link
Member

@ojeda ojeda Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is https://rust-for-linux.zulipchat.com/#narrow/stream/291565-Help/topic/Build.20errors/near/365685550 (applied at the rebased ojeda@698129c), i.e. I was going to fix it directly when we take the upgrade to 0.65.1.


``bindgen`` needs to find a suitable ``libclang`` in order to work. If it is
not found (or a different ``libclang`` than the one found should be used),
the process can be tweaked using the environment variables understood by
``clang-sys`` (the Rust bindings crate that ``bindgen`` uses to access
``libclang``):

* ``LLVM_CONFIG_PATH`` can be pointed to an ``llvm-config`` executable.

* Or ``LIBCLANG_PATH`` can be pointed to a ``libclang`` shared library
or to the directory containing it.

* Or ``CLANG_PATH`` can be pointed to a ``clang`` executable.

For details, please see ``clang-sys``'s documentation at:

https://github.com/KyleMayes/clang-sys#environment-variables


Requirements: Developing
Expand Down
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -11323,6 +11323,8 @@ W: https://google.github.io/kunit-docs/third_party/kernel/docs/
F: Documentation/dev-tools/kunit/
F: include/kunit/
F: lib/kunit/
F: rust/kernel/kunit.rs
F: scripts/rustdoc_test_*
F: tools/testing/kunit/

KERNEL USERMODE HELPER
Expand Down
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,6 @@ KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-std=gnu11
KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_RUSTFLAGS := $(rust_common_flags) \
--target=$(objtree)/scripts/target.json \
-Cpanic=abort -Cembed-bitcode=n -Clto=n \
-Cforce-unwind-tables=n -Ccodegen-units=1 \
-Csymbol-mangling-version=v0 \
Expand Down Expand Up @@ -1289,7 +1288,7 @@ prepare0: archprepare
# All the preparing..
prepare: prepare0
ifdef CONFIG_RUST
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh -v
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
$(Q)$(MAKE) $(build)=rust
endif

Expand Down Expand Up @@ -1823,7 +1822,7 @@ $(DOC_TARGETS):
# "Is Rust available?" target
PHONY += rustavailable
rustavailable:
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh -v && echo "Rust is available!"
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh && echo "Rust is available!"

# Documentation target
#
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ config ARM64
select HAVE_FUNCTION_ARG_ACCESS_API
select MMU_GATHER_RCU_TABLE_FREE
select HAVE_RSEQ
select HAVE_RUST if CPU_LITTLE_ENDIAN
select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
Expand Down
4 changes: 4 additions & 0 deletions arch/arm64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ KBUILD_CFLAGS += -mgeneral-regs-only \
KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
KBUILD_AFLAGS += $(compat_vdso)

KBUILD_RUSTFLAGS += --target aarch64-unknown-none -C target-feature="-neon,-fp-armv8"

KBUILD_CFLAGS += $(call cc-option,-mabi=lp64)
KBUILD_AFLAGS += $(call cc-option,-mabi=lp64)

Expand All @@ -65,7 +67,9 @@ endif

ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
KBUILD_CFLAGS += -mbranch-protection=pac-ret+bti
KBUILD_RUSTFLAGS += -Z branch-protection=bti,pac-ret
else ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
KBUILD_RUSTFLAGS += -Z branch-protection=pac-ret
ifeq ($(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET),y)
KBUILD_CFLAGS += -mbranch-protection=pac-ret
else
Expand Down
1 change: 1 addition & 0 deletions arch/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export BITS
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53383
#
KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx
KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json
KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2

ifeq ($(CONFIG_X86_KERNEL_IBT),y)
Expand Down
13 changes: 13 additions & 0 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -2911,6 +2911,19 @@ config RUST_BUILD_ASSERT_ALLOW

If unsure, say N.

config RUST_KERNEL_KUNIT_TEST
bool "KUnit test for the `kernel` crate" if !KUNIT_ALL_TESTS
depends on RUST && KUNIT=y
default KUNIT_ALL_TESTS
help
This builds the documentation tests of the `kernel` crate
as KUnit tests.

For more information on KUnit and unit tests in general,
please refer to the KUnit documentation in Documentation/dev-tools/kunit/.

If unsure, say N.

endmenu # "Rust"

endmenu # Kernel hacking
2 changes: 2 additions & 0 deletions rust/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

bindings_generated.rs
bindings_helpers_generated.rs
doctests_kernel_generated.rs
doctests_kernel_generated_kunit.c
uapi_generated.rs
exports_*_generated.h
doc/
Expand Down
41 changes: 37 additions & 4 deletions rust/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ endif

obj-$(CONFIG_RUST) += exports.o

always-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated.rs
always-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated_kunit.c

obj-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated.o
obj-$(CONFIG_RUST_KERNEL_KUNIT_TEST) += doctests_kernel_generated_kunit.o

# Avoids running `$(RUSTC)` for the sysroot when it may not be available.
ifdef CONFIG_RUST

Expand All @@ -39,9 +45,11 @@ ifeq ($(quiet),silent_)
cargo_quiet=-q
rust_test_quiet=-q
rustdoc_test_quiet=--test-args -q
rustdoc_test_kernel_quiet=>/dev/null
else ifeq ($(quiet),quiet_)
rust_test_quiet=-q
rustdoc_test_quiet=--test-args -q
rustdoc_test_kernel_quiet=>/dev/null
else
cargo_quiet=--verbose
endif
Expand Down Expand Up @@ -157,6 +165,27 @@ quiet_cmd_rustdoc_test = RUSTDOC T $<
-L$(objtree)/$(obj)/test --output $(objtree)/$(obj)/doc \
--crate-name $(subst rusttest-,,$@) $<

quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
cmd_rustdoc_test_kernel = \
rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
OBJTREE=$(abspath $(objtree)) \
$(RUSTDOC) --test $(rust_flags) \
@$(objtree)/include/generated/rustc_cfg \
-L$(objtree)/$(obj) --extern alloc --extern kernel \
--extern build_error --extern macros \
--extern bindings --extern uapi \
--no-run --crate-name kernel -Zunstable-options \
--test-builder $(objtree)/scripts/rustdoc_test_builder \
$< $(rustdoc_test_kernel_quiet); \
$(objtree)/scripts/rustdoc_test_gen

%/doctests_kernel_generated.rs %/doctests_kernel_generated_kunit.c: \
$(src)/kernel/lib.rs $(obj)/kernel.o \
$(objtree)/scripts/rustdoc_test_builder \
$(objtree)/scripts/rustdoc_test_gen FORCE
$(call if_changed,rustdoc_test_kernel)

# We cannot use `-Zpanic-abort-tests` because some tests are dynamic,
# so for the moment we skip `-Cpanic=abort`.
quiet_cmd_rustc_test = RUSTC T $<
Expand Down Expand Up @@ -262,6 +291,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \

# Derived from `scripts/Makefile.clang`.
BINDGEN_TARGET_x86 := x86_64-linux-gnu
BINDGEN_TARGET_arm64 := aarch64-linux-gnu
BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH))

# All warnings are inhibited since GCC builds are very experimental,
Expand Down Expand Up @@ -300,7 +330,7 @@ quiet_cmd_bindgen = BINDGEN $@
$(BINDGEN) $< $(bindgen_target_flags) \
--use-core --with-derive-default --ctypes-prefix core::ffi --no-layout-tests \
--no-debug '.*' \
--size_t-is-usize -o $@ -- $(bindgen_c_flags_final) -DMODULE \
-o $@ -- $(bindgen_c_flags_final) -DMODULE \
$(bindgen_target_cflags) $(bindgen_target_extra)

$(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
Expand All @@ -320,8 +350,8 @@ $(obj)/uapi/uapi_generated.rs: $(src)/uapi/uapi_helper.h \
# given it is `libclang`; but for consistency, future Clang changes and/or
# a potential future GCC backend for `bindgen`, we disable it too.
$(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_flags = \
--blacklist-type '.*' --whitelist-var '' \
--whitelist-function 'rust_helper_.*'
--blocklist-type '.*' --allowlist-var '' \
--allowlist-function 'rust_helper_.*'
$(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_cflags = \
-I$(objtree)/$(obj) -Wno-missing-prototypes -Wno-missing-declarations
$(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_extra = ; \
Expand Down Expand Up @@ -393,8 +423,11 @@ $(obj)/core.o: private skip_clippy = 1
$(obj)/core.o: private skip_flags = -Dunreachable_pub
$(obj)/core.o: private rustc_objcopy = $(foreach sym,$(redirect-intrinsics),--redefine-sym $(sym)=__rust$(sym))
$(obj)/core.o: private rustc_target_flags = $(core-cfgs)
$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs scripts/target.json FORCE
$(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs FORCE
$(call if_changed_dep,rustc_library)
ifeq ($(ARCH),x86_64)
$(obj)/core.o: scripts/target.json
endif

$(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*'
$(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE
Expand Down
19 changes: 19 additions & 0 deletions rust/bindings/bindings_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,31 @@
* Sorted alphabetically.
*/

#include <kunit/test.h>
#include <linux/errname.h>
#include <linux/slab.h>
#include <linux/refcount.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/xarray.h>

/* `bindgen` gets confused at certain things. */
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;

const gfp_t BINDINGS_XA_FLAGS_LOCK_IRQ = XA_FLAGS_LOCK_IRQ;
const gfp_t BINDINGS_XA_FLAGS_LOCK_BH = XA_FLAGS_LOCK_BH;
const gfp_t BINDINGS_XA_FLAGS_TRACK_FREE = XA_FLAGS_TRACK_FREE;
const gfp_t BINDINGS_XA_FLAGS_ZERO_BUSY = XA_FLAGS_ZERO_BUSY;
const gfp_t BINDINGS_XA_FLAGS_ALLOC_WRAPPED = XA_FLAGS_ALLOC_WRAPPED;
const gfp_t BINDINGS_XA_FLAGS_ACCOUNT = XA_FLAGS_ACCOUNT;
const gfp_t BINDINGS_XA_FLAGS_ALLOC = XA_FLAGS_ALLOC;
const gfp_t BINDINGS_XA_FLAGS_ALLOC1 = XA_FLAGS_ALLOC1;

const xa_mark_t BINDINGS_XA_MARK_0 = XA_MARK_0;
const xa_mark_t BINDINGS_XA_MARK_1 = XA_MARK_1;
const xa_mark_t BINDINGS_XA_MARK_2 = XA_MARK_2;
const xa_mark_t BINDINGS_XA_PRESENT = XA_PRESENT;
const xa_mark_t BINDINGS_XA_MARK_MAX = XA_MARK_MAX;
const xa_mark_t BINDINGS_XA_FREE_MARK = XA_FREE_MARK;
57 changes: 50 additions & 7 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* accidentally exposed.
*/

#include <linux/stddef.h>
#include <kunit/test-bug.h>
#include <linux/bug.h>
#include <linux/build_bug.h>
#include <linux/err.h>
Expand All @@ -27,6 +29,7 @@
#include <linux/spinlock.h>
#include <linux/sched/signal.h>
#include <linux/wait.h>
#include <linux/xarray.h>

__noreturn void rust_helper_BUG(void)
{
Expand Down Expand Up @@ -135,20 +138,60 @@ void rust_helper_put_task_struct(struct task_struct *t)
}
EXPORT_SYMBOL_GPL(rust_helper_put_task_struct);

struct kunit *rust_helper_kunit_get_current_test(void)
{
return kunit_get_current_test();
}
EXPORT_SYMBOL_GPL(rust_helper_kunit_get_current_test);
void rust_helper_xa_init_flags(struct xarray *xa, gfp_t flags)
{
xa_init_flags(xa, flags);
}
EXPORT_SYMBOL_GPL(rust_helper_xa_init_flags);

bool rust_helper_xa_empty(struct xarray *xa)
{
return xa_empty(xa);
}
EXPORT_SYMBOL_GPL(rust_helper_xa_empty);

int rust_helper_xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, gfp_t gfp)
{
return xa_alloc(xa, id, entry, limit, gfp);
}
EXPORT_SYMBOL_GPL(rust_helper_xa_alloc);

void rust_helper_xa_lock(struct xarray *xa)
{
xa_lock(xa);
}
EXPORT_SYMBOL_GPL(rust_helper_xa_lock);

void rust_helper_xa_unlock(struct xarray *xa)
{
xa_unlock(xa);
}
EXPORT_SYMBOL_GPL(rust_helper_xa_unlock);

int rust_helper_xa_err(void *entry)
{
return xa_err(entry);
}
EXPORT_SYMBOL_GPL(rust_helper_xa_err);

/*
* We use `bindgen`'s `--size_t-is-usize` option to bind the C `size_t` type
* as the Rust `usize` type, so we can use it in contexts where Rust
* expects a `usize` like slice (array) indices. `usize` is defined to be
* the same as C's `uintptr_t` type (can hold any pointer) but not
* necessarily the same as `size_t` (can hold the size of any single
* `bindgen` binds the C `size_t` type the Rust `usize` type, so we can
* use it in contexts where Rust expects a `usize` like slice (array) indices.
* `usize` is defined to be the same as C's `uintptr_t` type (can hold any pointer)
* but not necessarily the same as `size_t` (can hold the size of any single
* object). Most modern platforms use the same concrete integer type for
* both of them, but in case we find ourselves on a platform where
* that's not true, fail early instead of risking ABI or
* integer-overflow issues.
*
* If your platform fails this assertion, it means that you are in
* danger of integer-overflow bugs (even if you attempt to remove
* `--size_t-is-usize`). It may be easiest to change the kernel ABI on
* danger of integer-overflow bugs (even if you attempt to add
* `--no-size_t-is-usize`). It may be easiest to change the kernel ABI on
* your platform such that `size_t` matches `uintptr_t` (i.e., to increase
* `size_t`, because `uintptr_t` has to be at least as big as `size_t`).
*/
Expand Down
Loading