* [PATCH 0/9] rust: core abstractions for a USB display driver
@ 2026-08-26 16:28 Mike Lothian
2026-08-26 16:28 ` [PATCH 1/9] rust: sync: completion: add single-shot and timed operations Mike Lothian
` (9 more replies)
0 siblings, 10 replies; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Nathan Chancellor,
Nick Desaulniers, Bill Wendling, Justin Stitt, llvm
Core Rust abstractions a USB display driver needs. They are separated from the
driver because none of them are display specific: each one covers a kernel
facility that has C callers today and no Rust binding
sync: single-shot and timed completions
hrtimer: restart an ArcHrTimerHandle, and read the interrupt state inside a
hard callback
random, xxhash, time: safe wrappers over get_random_bytes(), xxh64() and
ktime_get_real_seconds()
workqueue: make OwnedQueue thread safe
io: offset copy helpers that check the bounds they are given
error: expose EPROTO
None of these nine has been posted before, so this goes out unversioned even
though the drivers it feeds are on their third round. A runtime platform-device
creator and a root-device attribute group went out inside the rust: drm v2
series, where they did not belong, and they are not here either, because the
consumer that needed them is not part of this posting
It is small on purpose. Every patch has a caller in the driver at the end of the
chain, and nothing is here on the argument that it might be useful to somebody
later
The rest of the posting, which is one series per subsystem:
rust-core, 9 patches, this one
rust-crypto, 2 patches, to linux-crypto and rust-for-linux, not sent yet
rust-usb, 5 patches, to linux-usb and rust-for-linux, not sent yet
rust-drm, 23 patches, to dri-devel and rust-for-linux, not sent yet
rust-firmware, 1 patch, to linux-kernel and rust-for-linux, not sent yet
drm-vino, 13 patches, to dri-devel, not sent yet
Vino is the user for all of them. The abstractions themselves are generic and
carry no knowledge of DisplayLink
The whole thing is one branch, base and prerequisites included, which is the
quickest way to read it:
git clone -b vino-v3 https://github.com/FireBurn/linux
cd linux
make LLVM=1 rustavailable
make LLVM=1 -j$(nproc)
make LLVM=1 -j$(nproc) modules
CONFIG_RUST=y and CONFIG_DRM_VINO=m are the two to set; DRM_VINO selects the
rest of what it needs
It is the exact tree these patches were generated from, at 4c9ba407018e, the
drm-rust-next tip of 2026-08-06. drm-next has moved on since, and this follows
drm-rust-next deliberately: the KMS layer underneath this work lives only there,
and that tree picks up drm-next on its own schedule
Two commits on the branch are not in any of the series above, because they
enable no part of Vino: a scheduler call site that stops compiling under the
locking-guard series, and the Kms associated type Tyr needs once the KMS
registration trait requires one
It applies to the base above plus this, and nothing else:
Alice Ryhl, Creation of workqueues in Rust, plus Onur Ozkan's cancel_sync
https://lore.kernel.org/r/20260312-create-workqueue-v4-0-ea39c351c38f@google.com
The reference branch also carries Boqun Feng's counted interrupt disabling
series, which SpinLockIrq needs. One patch of it is already in tip locking/core
as e901c1510e24
Danilo Krummrich's OwnedQueue, ScopedQueue and ScopedWork series supersedes part
of the workqueue work carried here, and is the better answer: Vino calls
Work::cancel_sync() in seven places to make teardown wait for its own work
items, and ScopedWork cancels on drop, which is that idiom done properly
https://lore.kernel.org/r/20260807165252.3849875-1-dakr@kernel.org
It was still moving when this was cut, so this uses what is available today.
When it lands the swap goes in as one commit moving the prerequisites and the
call sites together, since either half alone leaves the tree not building
These patches were written with the assistance of Claude (Anthropic), used
through Claude Code as an interactive coding assistant, across the design, the
implementation and the tests. Every patch it contributed to carries an
Assisted-by trailer. The Signed-off-by is mine: I have reviewed and tested what
is here and I stand behind it
Mike Lothian (9):
rust: sync: completion: add single-shot and timed operations
rust: hrtimer: add ArcHrTimerHandle::restart
rust: random: add a safe get_random_bytes wrapper
rust: xxhash: add a safe xxh64 wrapper
rust: workqueue: make OwnedQueue thread-safe
rust: io: add checked offset copy helpers
rust: hrtimer: expose interrupt state in hard callbacks
rust: error: expose EPROTO
rust: time: add ktime_get_real_seconds
11 files changed, 243 insertions(+), 2 deletions(-)
base-commit: 4c9ba407018e8deb06dbc643112bac8f40404f95
prerequisite-message-id: <20260312-create-workqueue-v4-0-ea39c351c38f@google.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/9] rust: sync: completion: add single-shot and timed operations
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-26 16:28 ` [PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart Mike Lothian
` (8 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Boqun Feng, Gary Guo, Alice Ryhl, Lyude Paul,
Daniel Almeida, Onur Özkan, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Tamir Duberstein,
Alexandre Courbot, linux-kernel
Expose complete() and wait_for_completion_timeout() so Rust drivers
can coordinate asynchronous completions without open-coding access
to struct completion.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/sync/completion.rs | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/sync/completion.rs b/rust/kernel/sync/completion.rs
index 35ff049ff078..df4f6e11ef37 100644
--- a/rust/kernel/sync/completion.rs
+++ b/rust/kernel/sync/completion.rs
@@ -6,7 +6,12 @@
//!
//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
-use crate::{bindings, prelude::*, types::Opaque};
+use crate::{
+ bindings,
+ prelude::*,
+ time::Jiffies,
+ types::Opaque, //
+};
/// Synchronization primitive to signal when a certain task has been completed.
///
@@ -90,6 +95,15 @@ fn as_raw(&self) -> *mut bindings::completion {
self.inner.get()
}
+ /// Signal one task waiting for this completion.
+ ///
+ /// If no task is waiting, the signal is retained and consumed by a future waiter.
+ #[inline]
+ pub fn complete(&self) {
+ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
+ unsafe { bindings::complete(self.as_raw()) };
+ }
+
/// Signal all tasks waiting on this completion.
///
/// This method wakes up all tasks waiting on this completion; after this operation the
@@ -111,4 +125,13 @@ pub fn wait_for_completion(&self) {
// SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
unsafe { bindings::wait_for_completion(self.as_raw()) };
}
+
+ /// Wait at most `timeout` jiffies for one completion signal.
+ ///
+ /// Returns `true` after consuming a signal and `false` when the timeout expires.
+ #[inline]
+ pub fn wait_for_completion_timeout(&self, timeout: Jiffies) -> bool {
+ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
+ unsafe { bindings::wait_for_completion_timeout(self.as_raw(), timeout) != 0 }
+ }
}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
2026-08-26 16:28 ` [PATCH 1/9] rust: sync: completion: add single-shot and timed operations Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-27 13:27 ` Andreas Hindborg
2026-08-26 16:28 ` [PATCH 3/9] rust: random: add a safe get_random_bytes wrapper Mike Lothian
` (7 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Andreas Hindborg, Boqun Feng, FUJITA Tomonori,
Frederic Weisbecker, Lyude Paul, Thomas Gleixner,
Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
Gary Guo, Björn Roy Baron, Benno Lossin, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, linux-kernel
Restarting an already-started timer through the safe API means dropping
its handle and calling `HrTimerPointer::start()` again. Dropping the
handle cancels, and cancelling blocks until a running callback returns,
so this is unavailable to any caller that cannot sleep -- a driver
re-arming its timer from a callback invoked with interrupts disabled,
say. Such drivers fall back to the unsafe `HasHrTimer::start()`
on a raw pointer.
Add `restart()` on the handle. It re-queues the timer in place without
cancelling first. It is safe because the handle already owns the
`Arc` that keeps the timer alive and still cancels it on drop, which
is exactly what `HasHrTimer::start()` requires of its caller.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/time/hrtimer/arc.rs | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/rust/kernel/time/hrtimer/arc.rs b/rust/kernel/time/hrtimer/arc.rs
index 7be82bcb352a..f7cd46dbd3d3 100644
--- a/rust/kernel/time/hrtimer/arc.rs
+++ b/rust/kernel/time/hrtimer/arc.rs
@@ -39,6 +39,29 @@ fn cancel(&mut self) -> bool {
}
}
+impl<T> ArcHrTimerHandle<T>
+where
+ T: HasHrTimer<T>,
+{
+ /// Restart the timer with a new expiry time, without cancelling it first.
+ ///
+ /// If the timer is queued it is removed and re-inserted at the new expiry; if it has already
+ /// expired it is queued again. Unlike dropping the handle and calling
+ /// [`HrTimerPointer::start`] again, this never blocks waiting for a running callback, so it
+ /// can be used from contexts that cannot sleep -- re-arming a timer from a driver callback
+ /// invoked with interrupts disabled, for instance.
+ ///
+ /// This handle keeps its timer alive and still cancels it on drop, so the timer cannot outlive
+ /// the restart.
+ pub fn restart(&self, expires: <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Expires) {
+ // SAFETY:
+ // - `self.inner` is a live `Arc<T>` held by this handle, so the pointer is valid.
+ // - The caller cannot leak past the timer's death: this handle owns the `Arc` and cancels
+ // the timer when dropped, which is the requirement `HasHrTimer::start` places on us.
+ unsafe { T::start(Arc::as_ptr(&self.inner), expires) };
+ }
+}
+
impl<T> Drop for ArcHrTimerHandle<T>
where
T: HasHrTimer<T>,
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/9] rust: random: add a safe get_random_bytes wrapper
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
2026-08-26 16:28 ` [PATCH 1/9] rust: sync: completion: add single-shot and timed operations Mike Lothian
2026-08-26 16:28 ` [PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-26 16:28 ` [PATCH 4/9] rust: xxhash: add a safe xxh64 wrapper Mike Lothian
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Joel Fernandes, linux-kernel
Expose a slice-based wrapper around get_random_bytes() so Rust callers
can fill key, nonce, and other random buffers without touching raw
pointers.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/lib.rs | 1 +
rust/kernel/random.rs | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
create mode 100644 rust/kernel/random.rs
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 08e5730753eb..f39648246271 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -116,6 +116,7 @@
pub mod ptr;
#[cfg(CONFIG_RUST_PWM_ABSTRACTIONS)]
pub mod pwm;
+pub mod random;
pub mod rbtree;
pub mod regulator;
pub mod revocable;
diff --git a/rust/kernel/random.rs b/rust/kernel/random.rs
new file mode 100644
index 000000000000..5f2288969dbf
--- /dev/null
+++ b/rust/kernel/random.rs
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Random number generation.
+//!
+//! C header: [`include/linux/random.h`](srctree/include/linux/random.h)
+
+use crate::bindings;
+
+/// Fills `buf` with cryptographically secure random bytes from the kernel's CSPRNG.
+///
+/// This is the in-kernel equivalent of reading from `/dev/urandom`, and is suitable for generating
+/// keys, nonces and other secrets. It never blocks: once the CSPRNG has been seeded during boot it
+/// stays seeded, and callers running that early should use
+/// [`wait_for_random_bytes()`] instead of assuming otherwise.
+///
+/// [`wait_for_random_bytes()`]: srctree/include/linux/random.h
+///
+/// # Examples
+///
+/// ```
+/// use kernel::random;
+///
+/// let mut key = [0u8; 16];
+/// random::fill_bytes(&mut key);
+///
+/// // A zero-length request is valid and does nothing.
+/// random::fill_bytes(&mut []);
+/// ```
+#[inline]
+pub fn fill_bytes(buf: &mut [u8]) {
+ // SAFETY: `buf` is a valid slice, so its pointer is valid for writes of `buf.len()` bytes, and
+ // `get_random_bytes()` writes exactly that many.
+ unsafe { bindings::get_random_bytes(buf.as_mut_ptr().cast(), buf.len()) };
+}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/9] rust: xxhash: add a safe xxh64 wrapper
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (2 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 3/9] rust: random: add a safe get_random_bytes wrapper Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-26 16:28 ` [PATCH 5/9] rust: workqueue: make OwnedQueue thread-safe Mike Lothian
` (5 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Lyude Paul,
Greg Kroah-Hartman, Asahi Lina, Lorenzo Stoakes, Joel Fernandes,
linux-kernel
Expose xxh64() through a slice-based Rust API for non-cryptographic
hashing such as framebuffer damage detection.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/bindings/bindings_helper.h | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/xxhash.rs | 68 +++++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+)
create mode 100644 rust/kernel/xxhash.rs
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 1124785e210b..2d079f278a04 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -93,6 +93,7 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/xarray.h>
+#include <linux/xxhash.h>
#include <trace/events/rust_sample.h>
/*
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index f39648246271..d7ced2a4c11f 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -141,6 +141,7 @@
pub mod usb;
pub mod workqueue;
pub mod xarray;
+pub mod xxhash;
#[doc(hidden)]
pub use bindings;
diff --git a/rust/kernel/xxhash.rs b/rust/kernel/xxhash.rs
new file mode 100644
index 000000000000..fca24cddef46
--- /dev/null
+++ b/rust/kernel/xxhash.rs
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! xxHash, a fast non-cryptographic hash function.
+//!
+//! C header: [`include/linux/xxhash.h`](srctree/include/linux/xxhash.h)
+
+use core::mem::MaybeUninit;
+
+use crate::{bindings, error::to_result, prelude::*};
+
+/// Incremental xxHash64 state.
+///
+/// Use this when the input is split across several buffers. Calling
+/// [`update`](Self::update) for each buffer produces the same digest as hashing
+/// their concatenation with [`xxh64`].
+pub struct Xxh64(bindings::xxh64_state);
+
+impl Xxh64 {
+ /// Start a new hash with `seed`.
+ pub fn new(seed: u64) -> Self {
+ let mut state = MaybeUninit::uninit();
+ // SAFETY: `xxh64_reset()` initializes every byte of the state before
+ // returning.
+ unsafe {
+ bindings::xxh64_reset(state.as_mut_ptr(), seed);
+ Self(state.assume_init())
+ }
+ }
+
+ /// Add `data` to the hash.
+ pub fn update(&mut self, data: &[u8]) -> Result {
+ // SAFETY: `self.0` is initialized and exclusively borrowed; `data` is
+ // valid for reads of `data.len()` bytes.
+ to_result(unsafe { bindings::xxh64_update(&mut self.0, data.as_ptr().cast(), data.len()) })
+ }
+
+ /// Return the current digest without consuming the state.
+ pub fn digest(&self) -> u64 {
+ // SAFETY: `self.0` was initialized by `xxh64_reset()` and remains live.
+ unsafe { bindings::xxh64_digest(&self.0) }
+ }
+}
+
+/// Returns the 64-bit xxHash of `data`, starting from `seed`.
+///
+/// This is a non-cryptographic hash: use it for change detection, bucketing and similar, never for
+/// anything security-relevant.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::xxhash::xxh64;
+///
+/// // The same input and seed always produce the same hash.
+/// assert_eq!(xxh64(b"hello", 0), xxh64(b"hello", 0));
+///
+/// // Different seeds produce different hashes.
+/// assert_ne!(xxh64(b"hello", 0), xxh64(b"hello", 1));
+///
+/// // Hashing the empty slice is well-defined.
+/// let _ = xxh64(&[], 0);
+/// ```
+#[inline]
+pub fn xxh64(data: &[u8], seed: u64) -> u64 {
+ // SAFETY: `data` is a valid slice, so its pointer is valid for reads of `data.len()` bytes,
+ // and `xxh64()` only reads from it for the duration of the call.
+ unsafe { bindings::xxh64(data.as_ptr().cast(), data.len(), seed) }
+}
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 5/9] rust: workqueue: make OwnedQueue thread-safe
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (3 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 4/9] rust: xxhash: add a safe xxh64 wrapper Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-26 16:28 ` [PATCH 6/9] rust: io: add checked offset copy helpers Mike Lothian
` (4 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Tejun Heo, Lai Jiangshan, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, Daniel Almeida,
Tamir Duberstein, Alexandre Courbot, Onur Özkan,
linux-kernel
OwnedQueue only owns a pointer to Queue, whose operations are already
Send and Sync. Propagate those guarantees so drivers can keep an
owned queue in shared device state.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/workqueue/mod.rs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/rust/kernel/workqueue/mod.rs b/rust/kernel/workqueue/mod.rs
index e30c21214a81..000a29c9dc1a 100644
--- a/rust/kernel/workqueue/mod.rs
+++ b/rust/kernel/workqueue/mod.rs
@@ -380,6 +380,12 @@ pub struct OwnedQueue {
queue: NonNull<Queue>,
}
+// SAFETY: `Queue` operations are thread-safe and ownership may be transferred
+// between threads.
+unsafe impl Send for OwnedQueue {}
+// SAFETY: Shared access only exposes the thread-safe `Queue` API.
+unsafe impl Sync for OwnedQueue {}
+
impl Deref for OwnedQueue {
type Target = Queue;
fn deref(&self) -> &Queue {
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 6/9] rust: io: add checked offset copy helpers
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (4 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 5/9] rust: workqueue: make OwnedQueue thread-safe Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-26 16:28 ` [PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks Mike Lothian
` (3 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Danilo Krummrich, Alice Ryhl, Daniel Almeida,
Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, driver-core, linux-kernel
I/O mappings often need to copy a bounded byte range rather than
the complete mapping. Add checked helpers that project the requested
range before using the backend copy operation. This keeps raw backend
pointers out of consumers and reports invalid ranges instead.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/io.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index 95f46bb75f9e..aea346b8b79e 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -225,6 +225,30 @@ fn io_view<'a, IO: Io<'a>, U>(
Ok(unsafe { IO::Backend::project_view(view, projected_ptr) })
}
+/// Returns a byte-slice view for a given range, performing runtime bounds checks.
+#[inline]
+fn io_byte_slice<'a, IO>(
+ this: IO,
+ offset: usize,
+ len: usize,
+) -> Result<<IO::Backend as IoBackend>::View<'a, [u8]>>
+where
+ IO: Io<'a, Target = [u8]>,
+{
+ let view = this.as_view();
+ let ptr = IO::Backend::as_ptr(view);
+ let end = offset.checked_add(len).ok_or(EINVAL)?;
+
+ if end > ptr.len() {
+ return Err(EINVAL);
+ }
+
+ let projected_ptr =
+ core::ptr::slice_from_raw_parts_mut(ptr.cast::<u8>().wrapping_add(offset), len);
+ // SAFETY: The bounds check above proves that `projected_ptr` is a sub-slice of `ptr`.
+ Ok(unsafe { IO::Backend::project_view(view, projected_ptr) })
+}
+
/// I/O backends.
///
/// This is an abstract representation to be implemented by arbitrary I/O
@@ -640,6 +664,32 @@ fn copy_to_slice(self, data: &mut [u8])
}
}
+ /// Copy bytes from `data` to a range of I/O memory.
+ ///
+ /// Returns [`EINVAL`] if `offset..offset + data.len()` is outside the I/O region.
+ #[inline]
+ fn try_copy_from_slice(self, offset: usize, data: &[u8]) -> Result
+ where
+ Self::Backend: IoCopyable,
+ Self: Io<'a, Target = [u8]>,
+ {
+ io_byte_slice(self, offset, data.len())?.copy_from_slice(data);
+ Ok(())
+ }
+
+ /// Copy a range of I/O memory to `data`.
+ ///
+ /// Returns [`EINVAL`] if `offset..offset + data.len()` is outside the I/O region.
+ #[inline]
+ fn try_copy_to_slice(self, offset: usize, data: &mut [u8]) -> Result
+ where
+ Self::Backend: IoCopyable,
+ Self: Io<'a, Target = [u8]>,
+ {
+ io_byte_slice(self, offset, data.len())?.copy_to_slice(data);
+ Ok(())
+ }
+
/// Fallible 8-bit read with runtime bounds check.
#[inline(always)]
fn try_read8(self, offset: usize) -> Result<u8>
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (5 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 6/9] rust: io: add checked offset copy helpers Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-27 13:34 ` Andreas Hindborg
2026-08-26 16:28 ` [PATCH 8/9] rust: error: expose EPROTO Mike Lothian
` (2 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Andreas Hindborg, Boqun Feng, FUJITA Tomonori,
Frederic Weisbecker, Lyude Paul, Thomas Gleixner,
Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
Gary Guo, Björn Roy Baron, Benno Lossin, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, linux-kernel
Hard hrtimer modes guarantee that their callbacks run with local
interrupts disabled. Carry that guarantee through HrTimerCallbackContext
so users of IRQ-aware locks do not need to assert the callback
context themselves.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/time/hrtimer.rs | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 2d7f1131a813..a55b3ce53735 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -404,7 +404,7 @@
//! [`Arc`]: kernel::sync::Arc
use super::{ClockSource, Delta, Instant};
-use crate::{prelude::*, types::Opaque};
+use crate::{interrupt::LocalInterruptDisabled, prelude::*, types::Opaque};
use core::{marker::PhantomData, ptr::NonNull};
use pin_init::PinInit;
@@ -900,6 +900,11 @@ pub trait HrTimerMode: private::Sealed {
type Expires: HrTimerExpires;
}
+/// A timer mode whose callback runs with local interrupts disabled.
+///
+/// This trait is sealed by [`HrTimerMode`].
+pub trait HardHrTimerMode: HrTimerMode {}
+
/// Timer that expires at a fixed point in time.
pub struct AbsoluteMode<C: ClockSource>(PhantomData<C>);
@@ -982,6 +987,7 @@ impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> {
type Clock = C;
type Expires = Instant<C>;
}
+impl<C: ClockSource> HardHrTimerMode for AbsoluteHardMode<C> {}
/// Timer with relative expiration, handled in hard irq context.
pub struct RelativeHardMode<C: ClockSource>(PhantomData<C>);
@@ -991,6 +997,7 @@ impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> {
type Clock = C;
type Expires = Delta;
}
+impl<C: ClockSource> HardHrTimerMode for RelativeHardMode<C> {}
/// Timer with absolute expiration, pinned to CPU and handled in hard irq context.
pub struct AbsolutePinnedHardMode<C: ClockSource>(PhantomData<C>);
@@ -1000,6 +1007,7 @@ impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> {
type Clock = C;
type Expires = Instant<C>;
}
+impl<C: ClockSource> HardHrTimerMode for AbsolutePinnedHardMode<C> {}
/// Timer with relative expiration, pinned to CPU and handled in hard irq context.
pub struct RelativePinnedHardMode<C: ClockSource>(PhantomData<C>);
@@ -1009,6 +1017,7 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {
type Clock = C;
type Expires = Delta;
}
+impl<C: ClockSource> HardHrTimerMode for RelativePinnedHardMode<C> {}
/// Privileged smart-pointer for a [`HrTimer`] callback context.
///
@@ -1065,6 +1074,16 @@ pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64 {
pub fn forward_now(&mut self, duration: Delta) -> u64 {
self.forward(HrTimerInstant::<T>::now(), duration)
}
+
+ /// Returns proof that local interrupts are disabled for a hard timer callback.
+ pub fn local_interrupt_disabled(&self) -> &LocalInterruptDisabled
+ where
+ T::TimerMode: HardHrTimerMode,
+ {
+ // SAFETY: `Self` can only be constructed while running this timer's callback, and the
+ // `HardHrTimerMode` bound guarantees that the callback runs in hard interrupt context.
+ unsafe { LocalInterruptDisabled::assume_disabled() }
+ }
}
/// Use to implement the [`HasHrTimer<T>`] trait.
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 8/9] rust: error: expose EPROTO
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (6 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-26 16:34 ` Miguel Ojeda
2026-08-26 16:28 ` [PATCH 9/9] rust: time: add ktime_get_real_seconds Mike Lothian
2026-08-26 16:54 ` [PATCH 0/9] rust: core abstractions for a USB display driver Miguel Ojeda
9 siblings, 1 reply; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Mirko Adzic, Eliot Courtney,
Daniel del Castillo, Alistair Francis, linux-kernel
Add the named protocol-error constant so Rust protocol drivers
can return the same specific errno as their C counterparts without
constructing it from a raw integer.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/error.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index a56ba6309594..9492471c2677 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -64,6 +64,7 @@ macro_rules! declare_err {
declare_err!(EPIPE, "Broken pipe.");
declare_err!(EDOM, "Math argument out of domain of func.");
declare_err!(ERANGE, "Math result not representable.");
+ declare_err!(EPROTO, "Protocol error.");
declare_err!(EOVERFLOW, "Value too large for defined data type.");
declare_err!(EMSGSIZE, "Message too long.");
declare_err!(ETIMEDOUT, "Connection timed out.");
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 9/9] rust: time: add ktime_get_real_seconds
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (7 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 8/9] rust: error: expose EPROTO Mike Lothian
@ 2026-08-26 16:28 ` Mike Lothian
2026-08-27 13:39 ` Andreas Hindborg
2026-08-26 16:54 ` [PATCH 0/9] rust: core abstractions for a USB display driver Miguel Ojeda
9 siblings, 1 reply; 15+ messages in thread
From: Mike Lothian @ 2026-08-26 16:28 UTC (permalink / raw)
To: rust-for-linux
Cc: Mike Lothian, Andreas Hindborg, Boqun Feng, FUJITA Tomonori,
Frederic Weisbecker, Lyude Paul, Thomas Gleixner,
Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
Gary Guo, Björn Roy Baron, Benno Lossin, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, linux-kernel
Reading an `Instant<RealTime>` is the wrong tool for a caller that only
wants a calendar time in seconds: it takes a full nanosecond timestamp and
then needs a 64-bit division to get back to what the timekeeping core
already maintains as a plain seconds field.
Wrap `ktime_get_real_seconds()`, which is that field. Document the property
that matters at the call site and that the type cannot express: the value
follows CLOCK_REALTIME, so it is not monotonic and can move in either
direction.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/time.rs | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 363e93cbb139..a9922f1b493d 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -129,6 +129,20 @@ fn ktime_get() -> bindings::ktime_t {
}
}
+/// Returns the coarse wall-clock time in whole seconds since the Unix epoch.
+///
+/// This is the cheap counterpart to reading an [`Instant<RealTime>`]: it reads the seconds field
+/// the timekeeping core maintains, with no 64-bit division, and is what a caller that only needs a
+/// calendar time should use.
+///
+/// The value follows CLOCK_REALTIME, so it is not monotonic: settimeofday(2), NTP steps and leap
+/// second handling can move it in either direction.
+pub fn ktime_get_real_seconds() -> i64 {
+ // SAFETY: reading the timekeeping core's seconds field has no preconditions and is safe from
+ // any context.
+ unsafe { bindings::ktime_get_real_seconds() }
+}
+
/// A monotonic that ticks while system is suspended.
///
/// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 8/9] rust: error: expose EPROTO
2026-08-26 16:28 ` [PATCH 8/9] rust: error: expose EPROTO Mike Lothian
@ 2026-08-26 16:34 ` Miguel Ojeda
0 siblings, 0 replies; 15+ messages in thread
From: Miguel Ojeda @ 2026-08-26 16:34 UTC (permalink / raw)
To: Mike Lothian
Cc: rust-for-linux, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Mirko Adzic, Eliot Courtney,
Daniel del Castillo, Alistair Francis, linux-kernel
On Wed, Aug 26, 2026 at 6:29 PM Mike Lothian <mike@fireburn.co.uk> wrote:
>
> Add the named protocol-error constant so Rust protocol drivers
> can return the same specific errno as their C counterparts without
> constructing it from a raw integer.
>
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
This is already in mainline, please see commit b93fb6e76ec1 ("rust:
error: add remaining error codes").
Cheers,
Miguel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 0/9] rust: core abstractions for a USB display driver
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
` (8 preceding siblings ...)
2026-08-26 16:28 ` [PATCH 9/9] rust: time: add ktime_get_real_seconds Mike Lothian
@ 2026-08-26 16:54 ` Miguel Ojeda
9 siblings, 0 replies; 15+ messages in thread
From: Miguel Ojeda @ 2026-08-26 16:54 UTC (permalink / raw)
To: Mike Lothian
Cc: rust-for-linux, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Nathan Chancellor,
Nick Desaulniers, Bill Wendling, Justin Stitt, llvm
On Wed, Aug 26, 2026 at 6:29 PM Mike Lothian <mike@fireburn.co.uk> wrote:
>
> Core Rust abstractions a USB display driver needs. They are separated from the
> driver because none of them are display specific: each one covers a kernel
> facility that has C callers today and no Rust binding
> The rest of the posting, which is one series per subsystem:
>
> rust-core, 9 patches, this one
Just in case it helps: these patches touch different subsystems, not
only one -- some of them may want that you split things up
accordingly.
I hope that clarifies.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart
2026-08-26 16:28 ` [PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart Mike Lothian
@ 2026-08-27 13:27 ` Andreas Hindborg
0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2026-08-27 13:27 UTC (permalink / raw)
To: Mike Lothian, rust-for-linux
Cc: Mike Lothian, Boqun Feng, FUJITA Tomonori, Frederic Weisbecker,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Miguel Ojeda, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, linux-kernel
"Mike Lothian" <mike@fireburn.co.uk> writes:
> Restarting an already-started timer through the safe API means dropping
> its handle and calling `HrTimerPointer::start()` again. Dropping the
> handle cancels, and cancelling blocks until a running callback returns,
> so this is unavailable to any caller that cannot sleep -- a driver
> re-arming its timer from a callback invoked with interrupts disabled,
> say. Such drivers fall back to the unsafe `HasHrTimer::start()`
> on a raw pointer.
>
> Add `restart()` on the handle. It re-queues the timer in place without
> cancelling first. It is safe because the handle already owns the
> `Arc` that keeps the timer alive and still cancels it on drop, which
> is exactly what `HasHrTimer::start()` requires of its caller.
The intention is that handlers use the `forward` method on the context
object in combination with return value `HrTimerRestart::Restart` to re
arm the timer.
However, we found a data race in the face of concurrent `start`
operations, so we are solving that over at [1].
Best regards,
Andreas Hindborg
[1] https://lore.kernel.org/rust-for-linux/20260825-expires-v2-v1-0-90411c6217c7@kernel.org/T/#t
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks
2026-08-26 16:28 ` [PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks Mike Lothian
@ 2026-08-27 13:34 ` Andreas Hindborg
0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2026-08-27 13:34 UTC (permalink / raw)
To: Mike Lothian, rust-for-linux
Cc: Mike Lothian, Boqun Feng, FUJITA Tomonori, Frederic Weisbecker,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Miguel Ojeda, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, linux-kernel
"Mike Lothian" <mike@fireburn.co.uk> writes:
> Hard hrtimer modes guarantee that their callbacks run with local
> interrupts disabled. Carry that guarantee through HrTimerCallbackContext
> so users of IRQ-aware locks do not need to assert the callback
> context themselves.
This looks good to me. We were pondering on removing the context type
though [1]. We might have to keep it around for this to work.
Best regards,
Andreas Hindborg
[1] https://lore.kernel.org/rust-for-linux/20260825-expires-v2-v1-3-90411c6217c7@kernel.org/
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 9/9] rust: time: add ktime_get_real_seconds
2026-08-26 16:28 ` [PATCH 9/9] rust: time: add ktime_get_real_seconds Mike Lothian
@ 2026-08-27 13:39 ` Andreas Hindborg
0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2026-08-27 13:39 UTC (permalink / raw)
To: Mike Lothian, rust-for-linux
Cc: Mike Lothian, Boqun Feng, FUJITA Tomonori, Frederic Weisbecker,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Miguel Ojeda, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
Onur Özkan, linux-kernel
"Mike Lothian" <mike@fireburn.co.uk> writes:
> Reading an `Instant<RealTime>` is the wrong tool for a caller that only
> wants a calendar time in seconds: it takes a full nanosecond timestamp and
> then needs a 64-bit division to get back to what the timekeeping core
> already maintains as a plain seconds field.
>
> Wrap `ktime_get_real_seconds()`, which is that field. Document the property
> that matters at the call site and that the type cannot express: the value
> follows CLOCK_REALTIME, so it is not monotonic and can move in either
> direction.
We recently added the concept of `TimeUnit`. For now it is exposed via
`Delta<U: TimeUnit>`. We could extend this to `Instant` as well to have
a seconds based `Instant`.
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-08-28 7:26 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 16:28 [PATCH 0/9] rust: core abstractions for a USB display driver Mike Lothian
2026-08-26 16:28 ` [PATCH 1/9] rust: sync: completion: add single-shot and timed operations Mike Lothian
2026-08-26 16:28 ` [PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart Mike Lothian
2026-08-27 13:27 ` Andreas Hindborg
2026-08-26 16:28 ` [PATCH 3/9] rust: random: add a safe get_random_bytes wrapper Mike Lothian
2026-08-26 16:28 ` [PATCH 4/9] rust: xxhash: add a safe xxh64 wrapper Mike Lothian
2026-08-26 16:28 ` [PATCH 5/9] rust: workqueue: make OwnedQueue thread-safe Mike Lothian
2026-08-26 16:28 ` [PATCH 6/9] rust: io: add checked offset copy helpers Mike Lothian
2026-08-26 16:28 ` [PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks Mike Lothian
2026-08-27 13:34 ` Andreas Hindborg
2026-08-26 16:28 ` [PATCH 8/9] rust: error: expose EPROTO Mike Lothian
2026-08-26 16:34 ` Miguel Ojeda
2026-08-26 16:28 ` [PATCH 9/9] rust: time: add ktime_get_real_seconds Mike Lothian
2026-08-27 13:39 ` Andreas Hindborg
2026-08-26 16:54 ` [PATCH 0/9] rust: core abstractions for a USB display driver Miguel Ojeda
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox