2021-07-03 14:52:41 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Non-trivial C macros cannot be used in Rust. Similarly, inlined C functions
|
|
|
|
* cannot be called either. This file explicitly creates functions ("helpers")
|
|
|
|
* that wrap those so that they can be called from Rust.
|
|
|
|
*
|
2024-04-11 20:54:28 +00:00
|
|
|
* Even though Rust kernel modules should never use the bindings directly, some
|
2021-07-03 14:52:41 +00:00
|
|
|
* of these helpers need to be exported because Rust generics and inlined
|
|
|
|
* functions may not get their code generated in the crate where they are
|
|
|
|
* defined. Other helpers, called from non-inline functions, may not be
|
|
|
|
* exported, in principle. However, in general, the Rust compiler does not
|
|
|
|
* guarantee codegen will be performed for a non-inline function either.
|
|
|
|
* Therefore, this file exports all the helpers. In the future, this may be
|
|
|
|
* revisited to reduce the number of exports after the compiler is informed
|
|
|
|
* about the places codegen is required.
|
|
|
|
*
|
|
|
|
* All symbols are exported as GPL-only to guarantee no GPL-only feature is
|
|
|
|
* accidentally exposed.
|
2023-04-26 20:49:23 +00:00
|
|
|
*
|
|
|
|
* Sorted alphabetically.
|
2021-07-03 14:52:41 +00:00
|
|
|
*/
|
|
|
|
|
rust: support running Rust documentation tests as KUnit ones
Rust has documentation tests: these are typically examples of
usage of any item (e.g. function, struct, module...).
They are very convenient because they are just written
alongside the documentation. For instance:
/// Sums two numbers.
///
/// ```
/// assert_eq!(mymod::f(10, 20), 30);
/// ```
pub fn f(a: i32, b: i32) -> i32 {
a + b
}
In userspace, the tests are collected and run via `rustdoc`.
Using the tool as-is would be useful already, since it allows
to compile-test most tests (thus enforcing they are kept
in sync with the code they document) and run those that do not
depend on in-kernel APIs.
However, by transforming the tests into a KUnit test suite,
they can also be run inside the kernel. Moreover, the tests
get to be compiled as other Rust kernel objects instead of
targeting userspace.
On top of that, the integration with KUnit means the Rust
support gets to reuse the existing testing facilities. For
instance, the kernel log would look like:
KTAP version 1
1..1
KTAP version 1
# Subtest: rust_doctests_kernel
1..59
# rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13
ok 1 rust_doctest_kernel_build_assert_rs_0
# rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56
ok 2 rust_doctest_kernel_build_assert_rs_1
# rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122
ok 3 rust_doctest_kernel_init_rs_0
...
# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
ok 59 rust_doctest_kernel_types_rs_2
# rust_doctests_kernel: pass:59 fail:0 skip:0 total:59
# Totals: pass:59 fail:0 skip:0 total:59
ok 1 rust_doctests_kernel
Therefore, add support for running Rust documentation tests
in KUnit. Some other notes about the current implementation
and support follow.
The transformation is performed by a couple scripts written
as Rust hostprogs.
Tests using the `?` operator are also supported as usual, e.g.:
/// ```
/// # use kernel::{spawn_work_item, workqueue};
/// spawn_work_item!(workqueue::system(), || pr_info!("x"))?;
/// # Ok::<(), Error>(())
/// ```
The tests are also compiled with Clippy under `CLIPPY=1`, just
like normal code, thus also benefitting from extra linting.
The names of the tests are currently automatically generated.
This allows to reduce the burden for documentation writers,
while keeping them fairly stable for bisection. This is an
improvement over the `rustdoc`-generated names, which include
the line number; but ideally we would like to get `rustdoc` to
provide the Rust item path and a number (for multiple examples
in a single documented Rust item).
In order for developers to easily see from which original line
a failed doctests came from, a KTAP diagnostic line is printed
to the log, containing the location (file and line) of the
original test (i.e. instead of the location in the generated
Rust file):
# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
This line follows the syntax for declaring test metadata in the
proposed KTAP v2 spec [1], which may be used for the proposed
KUnit test attributes API [2]. Thus hopefully this will make
migration easier later on (suggested by David [3]).
The original line in that test attribute is figured out by
providing an anchor (suggested by Boqun [4]). The original file
is found by walking the filesystem, checking directory prefixes
to reduce the amount of combinations to check, and it is only
done once per file. Ambiguities are detected and reported.
A notable difference from KUnit C tests is that the Rust tests
appear to assert using the usual `assert!` and `assert_eq!`
macros from the Rust standard library (`core`). We provide
a custom version that forwards the call to KUnit instead.
Importantly, these macros do not require passing context,
unlike the KUnit C ones (i.e. `struct kunit *`). This makes
them easier to use, and readers of the documentation do not need
to care about which testing framework is used. In addition, it
may allow us to test third-party code more easily in the future.
However, a current limitation is that KUnit does not support
assertions in other tasks. Thus we presently simply print an
error to the kernel log if an assertion actually failed. This
should be revisited to properly fail the test, perhaps saving
the context somewhere else, or letting KUnit handle it.
Link: https://lore.kernel.org/lkml/20230420205734.1288498-1-rmoar@google.com/ [1]
Link: https://lore.kernel.org/linux-kselftest/20230707210947.1208717-1-rmoar@google.com/ [2]
Link: https://lore.kernel.org/rust-for-linux/CABVgOSkOLO-8v6kdAGpmYnZUb+LKOX0CtYCo-Bge7r_2YTuXDQ@mail.gmail.com/ [3]
Link: https://lore.kernel.org/rust-for-linux/ZIps86MbJF%2FiGIzd@boqun-archlinux/ [4]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Reviewed-by: David Gow <davidgow@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2023-07-18 05:27:51 +00:00
|
|
|
#include <kunit/test-bug.h>
|
2021-07-03 14:52:41 +00:00
|
|
|
#include <linux/bug.h>
|
|
|
|
#include <linux/build_bug.h>
|
2024-06-18 15:48:34 +00:00
|
|
|
#include <linux/device.h>
|
2023-04-03 09:48:11 +00:00
|
|
|
#include <linux/err.h>
|
2023-05-31 17:44:50 +00:00
|
|
|
#include <linux/errname.h>
|
rust: add abstraction for `struct page`
Adds a new struct called `Page` that wraps a pointer to `struct page`.
This struct is assumed to hold ownership over the page, so that Rust
code can allocate and manage pages directly.
The page type has various methods for reading and writing into the page.
These methods will temporarily map the page to allow the operation. All
of these methods use a helper that takes an offset and length, performs
bounds checks, and returns a pointer to the given offset in the page.
This patch only adds support for pages of order zero, as that is all
Rust Binder needs. However, it is written to make it easy to add support
for higher-order pages in the future. To do that, you would add a const
generic parameter to `Page` that specifies the order. Most of the
methods do not need to be adjusted, as the logic for dealing with
mapping multiple pages at once can be isolated to just the
`with_pointer_into_page` method.
Rust Binder needs to manage pages directly as that is how transactions
are delivered: Each process has an mmap'd region for incoming
transactions. When an incoming transaction arrives, the Binder driver
will choose a region in the mmap, allocate and map the relevant pages
manually, and copy the incoming transaction directly into the page. This
architecture allows the driver to copy transactions directly from the
address space of one process to another, without an intermediate copy
to a kernel buffer.
This code is based on Wedson's page abstractions from the old rust
branch, but it has been modified by Alice by removing the incomplete
support for higher-order pages, by introducing the `with_*` helpers
to consolidate the bounds checking logic into a single place, and
various other changes.
Co-developed-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240528-alice-mm-v7-4-78222c31b8f4@google.com
[ Fixed typos and added a few intra-doc links. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2024-05-28 14:58:05 +00:00
|
|
|
#include <linux/gfp.h>
|
|
|
|
#include <linux/highmem.h>
|
2023-04-11 05:45:33 +00:00
|
|
|
#include <linux/mutex.h>
|
2023-04-26 20:49:23 +00:00
|
|
|
#include <linux/refcount.h>
|
2023-04-11 05:45:39 +00:00
|
|
|
#include <linux/sched/signal.h>
|
2024-03-21 16:36:46 +00:00
|
|
|
#include <linux/slab.h>
|
2023-04-26 20:49:23 +00:00
|
|
|
#include <linux/spinlock.h>
|
2023-03-26 03:57:38 +00:00
|
|
|
#include <linux/wait.h>
|
rust: workqueue: add helper for defining work_struct fields
The main challenge with defining `work_struct` fields is making sure
that the function pointer stored in the `work_struct` is appropriate for
the work item type it is embedded in. It needs to know the offset of the
`work_struct` field being used (even if there are several!) so that it
can do a `container_of`, and it needs to know the type of the work item
so that it can call into the right user-provided code. All of this needs
to happen in a way that provides a safe API to the user, so that users
of the workqueue cannot mix up the function pointers.
There are three important pieces that are relevant when doing this:
* The pointer type.
* The work item struct. This is what the pointer points at.
* The `work_struct` field. This is a field of the work item struct.
This patch introduces a separate trait for each piece. The pointer type
is given a `WorkItemPointer` trait, which pointer types need to
implement to be usable with the workqueue. This trait will be
implemented for `Arc` and `Box` in a later patch in this patchset.
Implementing this trait is unsafe because this is where the
`container_of` operation happens, but user-code will not need to
implement it themselves.
The work item struct should then implement the `WorkItem` trait. This
trait is where user-code specifies what they want to happen when a work
item is executed. It also specifies what the correct pointer type is.
Finally, to make the work item struct know the offset of its
`work_struct` field, we use a trait called `HasWork<T, ID>`. If a type
implements this trait, then the type declares that, at the given offset,
there is a field of type `Work<T, ID>`. The trait is marked unsafe
because the OFFSET constant must be correct, but we provide an
`impl_has_work!` macro that can safely implement `HasWork<T>` on a type.
The macro expands to something that only compiles if the specified field
really has the type `Work<T>`. It is used like this:
```
struct MyWorkItem {
work_field: Work<MyWorkItem, 1>,
}
impl_has_work! {
impl HasWork<MyWorkItem, 1> for MyWorkItem { self.work_field }
}
```
Note that since the `Work` type is annotated with an id, you can have
several `work_struct` fields by using a different id for each one.
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
2023-08-28 10:48:04 +00:00
|
|
|
#include <linux/workqueue.h>
|
2021-07-03 14:52:41 +00:00
|
|
|
|
|
|
|
__noreturn void rust_helper_BUG(void)
|
|
|
|
{
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_BUG);
|
|
|
|
|
rust: uaccess: add userspace pointers
A pointer to an area in userspace memory, which can be either read-only
or read-write.
All methods on this struct are safe: attempting to read or write on bad
addresses (either out of the bound of the slice or unmapped addresses)
will return `EFAULT`. Concurrent access, *including data races to/from
userspace memory*, is permitted, because fundamentally another userspace
thread/process could always be modifying memory at the same time (in the
same way that userspace Rust's `std::io` permits data races with the
contents of files on disk). In the presence of a race, the exact byte
values read/written are unspecified but the operation is well-defined.
Kernelspace code should validate its copy of data after completing a
read, and not expect that multiple reads of the same address will return
the same value.
These APIs are designed to make it difficult to accidentally write
TOCTOU bugs. Every time you read from a memory location, the pointer is
advanced by the length so that you cannot use that reader to read the
same memory location twice. Preventing double-fetches avoids TOCTOU
bugs. This is accomplished by taking `self` by value to prevent
obtaining multiple readers on a given `UserSlice`, and the readers only
permitting forward reads. If double-fetching a memory location is
necessary for some reason, then that is done by creating multiple
readers to the same memory location.
Constructing a `UserSlice` performs no checks on the provided address
and length, it can safely be constructed inside a kernel thread with no
current userspace process. Reads and writes wrap the kernel APIs
`copy_from_user` and `copy_to_user`, which check the memory map of the
current process and enforce that the address range is within the user
range (no additional calls to `access_ok` are needed).
This code is based on something that was originally written by Wedson on
the old rust branch. It was modified by Alice by removing the
`IoBufferReader` and `IoBufferWriter` traits, and various other changes.
Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240528-alice-mm-v7-1-78222c31b8f4@google.com
[ Wrapped docs to 100 and added a few intra-doc links. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2024-05-28 14:58:02 +00:00
|
|
|
unsigned long rust_helper_copy_from_user(void *to, const void __user *from,
|
|
|
|
unsigned long n)
|
|
|
|
{
|
|
|
|
return copy_from_user(to, from, n);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_copy_from_user);
|
|
|
|
|
|
|
|
unsigned long rust_helper_copy_to_user(void __user *to, const void *from,
|
|
|
|
unsigned long n)
|
|
|
|
{
|
|
|
|
return copy_to_user(to, from, n);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_copy_to_user);
|
|
|
|
|
2023-04-11 05:45:33 +00:00
|
|
|
void rust_helper_mutex_lock(struct mutex *lock)
|
|
|
|
{
|
|
|
|
mutex_lock(lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_mutex_lock);
|
|
|
|
|
2023-04-19 17:44:26 +00:00
|
|
|
void rust_helper___spin_lock_init(spinlock_t *lock, const char *name,
|
|
|
|
struct lock_class_key *key)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_DEBUG_SPINLOCK
|
|
|
|
__raw_spin_lock_init(spinlock_check(lock), name, key, LD_WAIT_CONFIG);
|
|
|
|
#else
|
|
|
|
spin_lock_init(lock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper___spin_lock_init);
|
|
|
|
|
|
|
|
void rust_helper_spin_lock(spinlock_t *lock)
|
|
|
|
{
|
|
|
|
spin_lock(lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_spin_lock);
|
|
|
|
|
|
|
|
void rust_helper_spin_unlock(spinlock_t *lock)
|
|
|
|
{
|
|
|
|
spin_unlock(lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_spin_unlock);
|
|
|
|
|
2023-03-26 03:57:38 +00:00
|
|
|
void rust_helper_init_wait(struct wait_queue_entry *wq_entry)
|
|
|
|
{
|
|
|
|
init_wait(wq_entry);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_init_wait);
|
|
|
|
|
2023-04-11 05:45:39 +00:00
|
|
|
int rust_helper_signal_pending(struct task_struct *t)
|
|
|
|
{
|
|
|
|
return signal_pending(t);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_signal_pending);
|
|
|
|
|
rust: add abstraction for `struct page`
Adds a new struct called `Page` that wraps a pointer to `struct page`.
This struct is assumed to hold ownership over the page, so that Rust
code can allocate and manage pages directly.
The page type has various methods for reading and writing into the page.
These methods will temporarily map the page to allow the operation. All
of these methods use a helper that takes an offset and length, performs
bounds checks, and returns a pointer to the given offset in the page.
This patch only adds support for pages of order zero, as that is all
Rust Binder needs. However, it is written to make it easy to add support
for higher-order pages in the future. To do that, you would add a const
generic parameter to `Page` that specifies the order. Most of the
methods do not need to be adjusted, as the logic for dealing with
mapping multiple pages at once can be isolated to just the
`with_pointer_into_page` method.
Rust Binder needs to manage pages directly as that is how transactions
are delivered: Each process has an mmap'd region for incoming
transactions. When an incoming transaction arrives, the Binder driver
will choose a region in the mmap, allocate and map the relevant pages
manually, and copy the incoming transaction directly into the page. This
architecture allows the driver to copy transactions directly from the
address space of one process to another, without an intermediate copy
to a kernel buffer.
This code is based on Wedson's page abstractions from the old rust
branch, but it has been modified by Alice by removing the incomplete
support for higher-order pages, by introducing the `with_*` helpers
to consolidate the bounds checking logic into a single place, and
various other changes.
Co-developed-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240528-alice-mm-v7-4-78222c31b8f4@google.com
[ Fixed typos and added a few intra-doc links. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2024-05-28 14:58:05 +00:00
|
|
|
struct page *rust_helper_alloc_pages(gfp_t gfp_mask, unsigned int order)
|
|
|
|
{
|
|
|
|
return alloc_pages(gfp_mask, order);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_alloc_pages);
|
|
|
|
|
|
|
|
void *rust_helper_kmap_local_page(struct page *page)
|
|
|
|
{
|
|
|
|
return kmap_local_page(page);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_kmap_local_page);
|
|
|
|
|
|
|
|
void rust_helper_kunmap_local(const void *addr)
|
|
|
|
{
|
|
|
|
kunmap_local(addr);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_kunmap_local);
|
|
|
|
|
2022-12-28 06:03:40 +00:00
|
|
|
refcount_t rust_helper_REFCOUNT_INIT(int n)
|
|
|
|
{
|
|
|
|
return (refcount_t)REFCOUNT_INIT(n);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_REFCOUNT_INIT);
|
|
|
|
|
|
|
|
void rust_helper_refcount_inc(refcount_t *r)
|
|
|
|
{
|
|
|
|
refcount_inc(r);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_refcount_inc);
|
|
|
|
|
|
|
|
bool rust_helper_refcount_dec_and_test(refcount_t *r)
|
|
|
|
{
|
|
|
|
return refcount_dec_and_test(r);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test);
|
|
|
|
|
2023-04-03 09:48:11 +00:00
|
|
|
__force void *rust_helper_ERR_PTR(long err)
|
|
|
|
{
|
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_ERR_PTR);
|
|
|
|
|
2023-04-03 09:48:14 +00:00
|
|
|
bool rust_helper_IS_ERR(__force const void *ptr)
|
|
|
|
{
|
|
|
|
return IS_ERR(ptr);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_IS_ERR);
|
|
|
|
|
|
|
|
long rust_helper_PTR_ERR(__force const void *ptr)
|
|
|
|
{
|
|
|
|
return PTR_ERR(ptr);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR);
|
|
|
|
|
2023-05-31 17:44:50 +00:00
|
|
|
const char *rust_helper_errname(int err)
|
|
|
|
{
|
|
|
|
return errname(err);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_errname);
|
|
|
|
|
2023-04-11 05:45:40 +00:00
|
|
|
struct task_struct *rust_helper_get_current(void)
|
|
|
|
{
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_get_current);
|
|
|
|
|
2023-04-11 05:45:39 +00:00
|
|
|
void rust_helper_get_task_struct(struct task_struct *t)
|
|
|
|
{
|
|
|
|
get_task_struct(t);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_get_task_struct);
|
|
|
|
|
|
|
|
void rust_helper_put_task_struct(struct task_struct *t)
|
|
|
|
{
|
|
|
|
put_task_struct(t);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_put_task_struct);
|
|
|
|
|
rust: support running Rust documentation tests as KUnit ones
Rust has documentation tests: these are typically examples of
usage of any item (e.g. function, struct, module...).
They are very convenient because they are just written
alongside the documentation. For instance:
/// Sums two numbers.
///
/// ```
/// assert_eq!(mymod::f(10, 20), 30);
/// ```
pub fn f(a: i32, b: i32) -> i32 {
a + b
}
In userspace, the tests are collected and run via `rustdoc`.
Using the tool as-is would be useful already, since it allows
to compile-test most tests (thus enforcing they are kept
in sync with the code they document) and run those that do not
depend on in-kernel APIs.
However, by transforming the tests into a KUnit test suite,
they can also be run inside the kernel. Moreover, the tests
get to be compiled as other Rust kernel objects instead of
targeting userspace.
On top of that, the integration with KUnit means the Rust
support gets to reuse the existing testing facilities. For
instance, the kernel log would look like:
KTAP version 1
1..1
KTAP version 1
# Subtest: rust_doctests_kernel
1..59
# rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13
ok 1 rust_doctest_kernel_build_assert_rs_0
# rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56
ok 2 rust_doctest_kernel_build_assert_rs_1
# rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122
ok 3 rust_doctest_kernel_init_rs_0
...
# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
ok 59 rust_doctest_kernel_types_rs_2
# rust_doctests_kernel: pass:59 fail:0 skip:0 total:59
# Totals: pass:59 fail:0 skip:0 total:59
ok 1 rust_doctests_kernel
Therefore, add support for running Rust documentation tests
in KUnit. Some other notes about the current implementation
and support follow.
The transformation is performed by a couple scripts written
as Rust hostprogs.
Tests using the `?` operator are also supported as usual, e.g.:
/// ```
/// # use kernel::{spawn_work_item, workqueue};
/// spawn_work_item!(workqueue::system(), || pr_info!("x"))?;
/// # Ok::<(), Error>(())
/// ```
The tests are also compiled with Clippy under `CLIPPY=1`, just
like normal code, thus also benefitting from extra linting.
The names of the tests are currently automatically generated.
This allows to reduce the burden for documentation writers,
while keeping them fairly stable for bisection. This is an
improvement over the `rustdoc`-generated names, which include
the line number; but ideally we would like to get `rustdoc` to
provide the Rust item path and a number (for multiple examples
in a single documented Rust item).
In order for developers to easily see from which original line
a failed doctests came from, a KTAP diagnostic line is printed
to the log, containing the location (file and line) of the
original test (i.e. instead of the location in the generated
Rust file):
# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150
This line follows the syntax for declaring test metadata in the
proposed KTAP v2 spec [1], which may be used for the proposed
KUnit test attributes API [2]. Thus hopefully this will make
migration easier later on (suggested by David [3]).
The original line in that test attribute is figured out by
providing an anchor (suggested by Boqun [4]). The original file
is found by walking the filesystem, checking directory prefixes
to reduce the amount of combinations to check, and it is only
done once per file. Ambiguities are detected and reported.
A notable difference from KUnit C tests is that the Rust tests
appear to assert using the usual `assert!` and `assert_eq!`
macros from the Rust standard library (`core`). We provide
a custom version that forwards the call to KUnit instead.
Importantly, these macros do not require passing context,
unlike the KUnit C ones (i.e. `struct kunit *`). This makes
them easier to use, and readers of the documentation do not need
to care about which testing framework is used. In addition, it
may allow us to test third-party code more easily in the future.
However, a current limitation is that KUnit does not support
assertions in other tasks. Thus we presently simply print an
error to the kernel log if an assertion actually failed. This
should be revisited to properly fail the test, perhaps saving
the context somewhere else, or letting KUnit handle it.
Link: https://lore.kernel.org/lkml/20230420205734.1288498-1-rmoar@google.com/ [1]
Link: https://lore.kernel.org/linux-kselftest/20230707210947.1208717-1-rmoar@google.com/ [2]
Link: https://lore.kernel.org/rust-for-linux/CABVgOSkOLO-8v6kdAGpmYnZUb+LKOX0CtYCo-Bge7r_2YTuXDQ@mail.gmail.com/ [3]
Link: https://lore.kernel.org/rust-for-linux/ZIps86MbJF%2FiGIzd@boqun-archlinux/ [4]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Reviewed-by: David Gow <davidgow@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2023-07-18 05:27:51 +00:00
|
|
|
struct kunit *rust_helper_kunit_get_current_test(void)
|
|
|
|
{
|
|
|
|
return kunit_get_current_test();
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_kunit_get_current_test);
|
|
|
|
|
rust: workqueue: add helper for defining work_struct fields
The main challenge with defining `work_struct` fields is making sure
that the function pointer stored in the `work_struct` is appropriate for
the work item type it is embedded in. It needs to know the offset of the
`work_struct` field being used (even if there are several!) so that it
can do a `container_of`, and it needs to know the type of the work item
so that it can call into the right user-provided code. All of this needs
to happen in a way that provides a safe API to the user, so that users
of the workqueue cannot mix up the function pointers.
There are three important pieces that are relevant when doing this:
* The pointer type.
* The work item struct. This is what the pointer points at.
* The `work_struct` field. This is a field of the work item struct.
This patch introduces a separate trait for each piece. The pointer type
is given a `WorkItemPointer` trait, which pointer types need to
implement to be usable with the workqueue. This trait will be
implemented for `Arc` and `Box` in a later patch in this patchset.
Implementing this trait is unsafe because this is where the
`container_of` operation happens, but user-code will not need to
implement it themselves.
The work item struct should then implement the `WorkItem` trait. This
trait is where user-code specifies what they want to happen when a work
item is executed. It also specifies what the correct pointer type is.
Finally, to make the work item struct know the offset of its
`work_struct` field, we use a trait called `HasWork<T, ID>`. If a type
implements this trait, then the type declares that, at the given offset,
there is a field of type `Work<T, ID>`. The trait is marked unsafe
because the OFFSET constant must be correct, but we provide an
`impl_has_work!` macro that can safely implement `HasWork<T>` on a type.
The macro expands to something that only compiles if the specified field
really has the type `Work<T>`. It is used like this:
```
struct MyWorkItem {
work_field: Work<MyWorkItem, 1>,
}
impl_has_work! {
impl HasWork<MyWorkItem, 1> for MyWorkItem { self.work_field }
}
```
Note that since the `Work` type is annotated with an id, you can have
several `work_struct` fields by using a different id for each one.
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
2023-08-28 10:48:04 +00:00
|
|
|
void rust_helper_init_work_with_key(struct work_struct *work, work_func_t func,
|
|
|
|
bool onstack, const char *name,
|
|
|
|
struct lock_class_key *key)
|
|
|
|
{
|
|
|
|
__init_work(work, onstack);
|
|
|
|
work->data = (atomic_long_t)WORK_DATA_INIT();
|
|
|
|
lockdep_init_map(&work->lockdep_map, name, key, 0);
|
|
|
|
INIT_LIST_HEAD(&work->entry);
|
|
|
|
work->func = func;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_init_work_with_key);
|
|
|
|
|
2024-03-21 16:36:46 +00:00
|
|
|
void * __must_check __realloc_size(2)
|
|
|
|
rust_helper_krealloc(const void *objp, size_t new_size, gfp_t flags)
|
|
|
|
{
|
|
|
|
return krealloc(objp, new_size, flags);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_krealloc);
|
|
|
|
|
2021-07-03 14:52:41 +00:00
|
|
|
/*
|
rust: bindgen: upgrade to 0.65.1
In LLVM 16, anonymous items may return names like `(unnamed union at ..)`
rather than empty names [1], which breaks Rust-enabled builds because
bindgen assumed an empty name instead of detecting them via
`clang_Cursor_isAnonymous` [2]:
$ make rustdoc LLVM=1 CLIPPY=1 -j$(nproc)
RUSTC L rust/core.o
BINDGEN rust/bindings/bindings_generated.rs
BINDGEN rust/bindings/bindings_helpers_generated.rs
BINDGEN rust/uapi/uapi_generated.rs
thread 'main' panicked at '"ftrace_branch_data_union_(anonymous_at__/_/include/linux/compiler_types_h_146_2)" is not a valid Ident', .../proc-macro2-1.0.24/src/fallback.rs:693:9
...
thread 'main' panicked at '"ftrace_branch_data_union_(anonymous_at__/_/include/linux/compiler_types_h_146_2)" is not a valid Ident', .../proc-macro2-1.0.24/src/fallback.rs:693:9
...
This was fixed in bindgen 0.62.0. Therefore, upgrade bindgen to
a more recent version, 0.65.1, to support LLVM 16.
Since bindgen 0.58.0 changed the `--{white,black}list-*` flags to
`--{allow,block}list-*` [3], update them on our side too.
In addition, bindgen 0.61.0 moved its CLI utility into a binary crate
called `bindgen-cli` [4]. Thus update the installation command in the
Quick Start guide.
Moreover, bindgen 0.61.0 changed the default functionality to bind
`size_t` to `usize` [5] and added the `--no-size_t-is-usize` flag
to not bind `size_t` as `usize`. Then bindgen 0.65.0 removed
the `--size_t-is-usize` flag [6]. Thus stop passing the flag to bindgen.
Finally, bindgen 0.61.0 added support for the `noreturn` attribute (in
its different forms) [7]. Thus remove the infinite loop in our Rust
panic handler after calling `BUG()`, since bindgen now correctly
generates a `BUG()` binding that returns `!` instead of `()`.
Link: https://github.com/llvm/llvm-project/commit/19e984ef8f49bc3ccced15621989fa9703b2cd5b [1]
Link: https://github.com/rust-lang/rust-bindgen/pull/2319 [2]
Link: https://github.com/rust-lang/rust-bindgen/pull/1990 [3]
Link: https://github.com/rust-lang/rust-bindgen/pull/2284 [4]
Link: https://github.com/rust-lang/rust-bindgen/commit/cc78b6fdb6e829e5fb8fa1639f2182cb49333569 [5]
Link: https://github.com/rust-lang/rust-bindgen/pull/2408 [6]
Link: https://github.com/rust-lang/rust-bindgen/issues/2094 [7]
Signed-off-by: Aakash Sen Sharma <aakashsensharma@gmail.com>
Closes: https://github.com/Rust-for-Linux/linux/issues/1013
Tested-by: Ariel Miculas <amiculas@cisco.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Link: https://lore.kernel.org/r/20230612194311.24826-1-aakashsensharma@gmail.com
[ Reworded commit message. Mentioned the `bindgen-cli` binary crate
change, linked to it and updated the Quick Start guide. Re-added a
deleted "as" word in a code comment and reflowed comment to respect
the maximum length. ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2023-06-12 19:43:11 +00:00
|
|
|
* `bindgen` binds 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 object). Most modern platforms use the same concrete integer type for
|
2021-07-03 14:52:41 +00:00
|
|
|
* 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
|
rust: bindgen: upgrade to 0.65.1
In LLVM 16, anonymous items may return names like `(unnamed union at ..)`
rather than empty names [1], which breaks Rust-enabled builds because
bindgen assumed an empty name instead of detecting them via
`clang_Cursor_isAnonymous` [2]:
$ make rustdoc LLVM=1 CLIPPY=1 -j$(nproc)
RUSTC L rust/core.o
BINDGEN rust/bindings/bindings_generated.rs
BINDGEN rust/bindings/bindings_helpers_generated.rs
BINDGEN rust/uapi/uapi_generated.rs
thread 'main' panicked at '"ftrace_branch_data_union_(anonymous_at__/_/include/linux/compiler_types_h_146_2)" is not a valid Ident', .../proc-macro2-1.0.24/src/fallback.rs:693:9
...
thread 'main' panicked at '"ftrace_branch_data_union_(anonymous_at__/_/include/linux/compiler_types_h_146_2)" is not a valid Ident', .../proc-macro2-1.0.24/src/fallback.rs:693:9
...
This was fixed in bindgen 0.62.0. Therefore, upgrade bindgen to
a more recent version, 0.65.1, to support LLVM 16.
Since bindgen 0.58.0 changed the `--{white,black}list-*` flags to
`--{allow,block}list-*` [3], update them on our side too.
In addition, bindgen 0.61.0 moved its CLI utility into a binary crate
called `bindgen-cli` [4]. Thus update the installation command in the
Quick Start guide.
Moreover, bindgen 0.61.0 changed the default functionality to bind
`size_t` to `usize` [5] and added the `--no-size_t-is-usize` flag
to not bind `size_t` as `usize`. Then bindgen 0.65.0 removed
the `--size_t-is-usize` flag [6]. Thus stop passing the flag to bindgen.
Finally, bindgen 0.61.0 added support for the `noreturn` attribute (in
its different forms) [7]. Thus remove the infinite loop in our Rust
panic handler after calling `BUG()`, since bindgen now correctly
generates a `BUG()` binding that returns `!` instead of `()`.
Link: https://github.com/llvm/llvm-project/commit/19e984ef8f49bc3ccced15621989fa9703b2cd5b [1]
Link: https://github.com/rust-lang/rust-bindgen/pull/2319 [2]
Link: https://github.com/rust-lang/rust-bindgen/pull/1990 [3]
Link: https://github.com/rust-lang/rust-bindgen/pull/2284 [4]
Link: https://github.com/rust-lang/rust-bindgen/commit/cc78b6fdb6e829e5fb8fa1639f2182cb49333569 [5]
Link: https://github.com/rust-lang/rust-bindgen/pull/2408 [6]
Link: https://github.com/rust-lang/rust-bindgen/issues/2094 [7]
Signed-off-by: Aakash Sen Sharma <aakashsensharma@gmail.com>
Closes: https://github.com/Rust-for-Linux/linux/issues/1013
Tested-by: Ariel Miculas <amiculas@cisco.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Link: https://lore.kernel.org/r/20230612194311.24826-1-aakashsensharma@gmail.com
[ Reworded commit message. Mentioned the `bindgen-cli` binary crate
change, linked to it and updated the Quick Start guide. Re-added a
deleted "as" word in a code comment and reflowed comment to respect
the maximum length. ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2023-06-12 19:43:11 +00:00
|
|
|
* 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
|
2021-07-03 14:52:41 +00:00
|
|
|
* 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`).
|
|
|
|
*/
|
|
|
|
static_assert(
|
|
|
|
sizeof(size_t) == sizeof(uintptr_t) &&
|
|
|
|
__alignof__(size_t) == __alignof__(uintptr_t),
|
|
|
|
"Rust code expects C `size_t` to match Rust `usize`"
|
|
|
|
);
|
2024-06-11 11:45:49 +00:00
|
|
|
|
|
|
|
// This will soon be moved to a separate file, so no need to merge with above.
|
|
|
|
#include <linux/blk-mq.h>
|
|
|
|
#include <linux/blkdev.h>
|
|
|
|
|
|
|
|
void *rust_helper_blk_mq_rq_to_pdu(struct request *rq)
|
|
|
|
{
|
|
|
|
return blk_mq_rq_to_pdu(rq);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_blk_mq_rq_to_pdu);
|
|
|
|
|
|
|
|
struct request *rust_helper_blk_mq_rq_from_pdu(void *pdu)
|
|
|
|
{
|
|
|
|
return blk_mq_rq_from_pdu(pdu);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(rust_helper_blk_mq_rq_from_pdu);
|