Add a helper to copy `len` bytes from `src` to `dst` using byte-wise atomic memory operations. This is the concurrent-safe counterpart of `core::ptr::copy_nonoverlapping()` (the equivalent of standard C's `memcpy()`). Because of the atomicity at byte level, when the copy races with another concurrent atomic access (or when a normal read races with an atomic read), or with an external access (from DMA or userspace), the behavior of this function is defined: the memory is copied at (at least) byte granularity. The helper is the building block for higher-level copy operations that need to remain defined under racing accesses, such as the `SysMem` I/O backend, which copies to and from memory that may be shared with hardware or user space. The implementation forwards to the kernel's `memcpy()`, which is implemented in a way that byte-wise atomic memory load/store instructions are used. Signed-off-by: Andreas Hindborg --- rust/kernel/sync/atomic.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs index 6d27898add42..d25627fa6557 100644 --- a/rust/kernel/sync/atomic.rs +++ b/rust/kernel/sync/atomic.rs @@ -848,3 +848,39 @@ pub unsafe fn cmpxchg( // per LKMM. unsafe { Atomic::from_ptr(ptr) }.cmpxchg(old, new, o) } + +/// Copy `len` bytes from `src` to `dst` using byte-wise atomic operations. +/// +/// This is the concurrent-safe counterpart of `core::ptr::copy_nonoverlapping()` (the equivalent +/// of standard C's `memcpy()`). Because of the atomicity at byte level, when racing with another +/// concurrent atomic access (or when a normal read races with an atomic read), or with an external +/// access (from DMA or userspace), the behavior of this function is defined: the memory is copied +/// at (at least) byte granularity. +/// +/// Implementation note: this is currently implemented by the kernel's `memcpy()`, which is +/// implemented in a way such that byte-wise atomic memory load/store instructions are used. +/// +/// # Safety +/// +/// Callers must ensure that: +/// +/// - `src` is valid for atomic reads for `len` bytes for the duration of the call. +/// - `dst` is valid for atomic writes for `len` bytes for the duration of the call. +/// - The memory regions `src .. src + len` and `dst .. dst + len` do not overlap. +#[inline] +pub unsafe fn memcpy(src: *const u8, dst: *mut u8, len: usize) { + // SAFETY: By the safety requirements of this function, the following operation will not: + // - Trap. + // - Invalidate any reference invariants. + // - Race with any operation by the Rust AM, as `bindings::memcpy` is a byte-wise atomic + // operation and all operations by the Rust AM to the involved memory areas use byte-wise + // atomic semantics. + // - Copy between overlapping regions, which `memcpy()` does not support. + unsafe { + bindings::memcpy( + dst.cast::(), + src.cast::(), + len, + ) + }; +} -- 2.54.0