- Mar 13, 2025
-
-
Daniel Almeida authored
Rust driver for ARM Mali CSF-based GPUs The skeleton is basically taken from Nova and also rust_platform_driver.rs. So far, this is just a very early-stage experiment, but it looks promissing: - We use the same uAPI as Panthor, although this needs a bit of work, since bindgen cannot translate #defines into Rust. - The DRM registration and a few IOCTLs are implemented. There is an igt branch with tests. - Basic iomem and register set implementation, so it's possible to program the device. - IRQ handling, so we can receive notifications from the device. - We can boot the firmware. - We can communicate with CSF using the global interface. We can submit requests and the MCU will appropriately respond in the ack field. - There is GEM_CREATE and VM_BIND support. - We can send a PING request to CSF, and it will acknowledge it successfully. Notably missing (apart from literally everything else): - Job subission logic through drm_scheduler and completion through dma_fences - Devfreq, pm_idle, etc. The name "Tyr" is inspired by Norse mythology, reflecting ARM's tradition of naming their GPUs after Nordic mythological figures and places. Co-developed-by:
Alice Ryhl <alice.ryhl@google.com> Signed-off-by:
Alice Ryhl <alice.ryhl@google.com> Signed-off-by:
Daniel Almeida <daniel.almeida@collabora.com>
-
Daniel Almeida authored
set_wc() doesn't really do anything. It derefs the pointer, so the value gets copied into the stack. It then sets the flag on the stack value, leaving the original unchanged. The above can be confirmed by placing a trace in, e.g., drm_shmem_vmap() after a call to set_wc(true). The underlying value in the C struct will still be 0 Fix this by introducing a mutable reborrow.
-
The XArray is an abstract data type which behaves like a very large array of pointers. Add a Rust abstraction for this data type. The initial implementation uses explicit locking on get operations and returns a guard which blocks mutation, ensuring that the referenced object remains alive. To avoid excessive serialization, users are expected to use an inner type that can be efficiently cloned (such as Arc<T>), and eagerly clone and drop the guard to unblock other users after a lookup. Future variants may support using RCU instead to avoid mutex locking. This abstraction also introduces a reservation mechanism, which can be used by alloc-capable XArrays to reserve a free slot without immediately filling it, and then do so at a later time. If the reservation is dropped without being filled, the slot is freed again for other users, which eliminates the need for explicit cleanup code. Signed-off-by:
Asahi Lina <lina@asahilina.net> --- Hi everyone! This abstraction is part of the set of dependencies for the drm/asahi Apple M1/M2 GPU driver. The branch at [1] contains the full series of patches rebased on upstream leading to the complete driver, for reference on how it is intended to be used. Thank you everyone who helped review this on GitHub [2]! I hope I didn't forget any CCs... Note that I dropped the convenience `Deref` impl for `Guard`, since I couldn't figure out how to do it safely. Suggestions welcome, or we can leave it for a future improvement ^^ [1] https://github.com/AsahiLinux/linux/tree/gpu/rebase-20230224 [2] https://github.com/Rust-for-Linux/linux/pull/952 Changes in v3: - Updated to the error v2/v3 series API. - Renamed `err` to `ret` for consistency with the other instance. - Link to v2: https://lore.kernel.org/r/20230224-rust-xarray-v2-1-4eeb0134944c@asahilina.net Changes in v2: - Added Pin requirement for all XArray operations, to close a soundness hole due to the lock in the XArray (locks are not safe to move while locked). Creation does not require pinning in place, since the lock cannot be acquired at that point. - Added safety note to Drop impl about why we don't need to do the lock unlock dance to ensure soundness in case of a dropped lock guard. - Downstream drm/asahi driver was also rebased on this version to prove it works (previously it was still on a pre-v1 version). - This still depends on the Error series (v1). v2 of that will need a trivial rename of Error::from_kernel_errno -> Error::from_errno. If this version of XArray ends up looking good, I'll send a trivial v4 of XArray with the rename, after sending the v2 of the Error series. - Link to v1: https://lore.kernel.org/r/20230224-rust-xarray-v1-1-80f0904ce5d3@asahilina.net
-
- Feb 18, 2025
-
-
Required by the asahi driver. Signed-off-by:
Janne Grunau <j@jannau.net>
-
Daniel Almeida authored
This patch is merely a stand-in for work that Abdiel is already carrying out. It's not meant to be upstreamed. Signed-off-by:
Daniel Almeida <daniel.almeida@collabora.com>
-
- Feb 17, 2025
-
-
Daniel Almeida authored
This abstraction adds a small subset of the regulator API. This is thought to be sufficient for the drivers we have now. The abstraction maintains a count of how many times `enable()` was called. This is so it can make sure that the calls to enable balance out with the calls to disable, as required by the C API. Signed-off-by:
Daniel Almeida <daniel.almeida@collabora.com>
-
Daniel Almeida authored
Signed-off-by:
Daniel Almeida <daniel.almeida@collabora.com>
-
This adds very basic bindings for the clk framework, implements only clk_get() and clk_put(). These are the bare minimum bindings required for many users and are simple enough to add in the first attempt. These will be used by Rust based cpufreq / OPP core to begin with. Signed-off-by:
Viresh Kumar <viresh.kumar@linaro.org>
-
Wait until a PHY becomes ready in the probe callback by using read_poll_timeout function. Reviewed-by:
Andrew Lunn <andrew@lunn.ch> Reviewed-by:
Alice Ryhl <aliceryhl@google.com> Reviewed-by:
Gary Guo <gary@garyguo.net> Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Add read_poll_timeout functions which poll periodically until a condition is met or a timeout is reached. The C's read_poll_timeout (include/linux/iopoll.h) is a complicated macro and a simple wrapper for Rust doesn't work. So this implements the same functionality in Rust. The C version uses usleep_range() while the Rust version uses fsleep(), which uses the best sleep method so it works with spans that usleep_range() doesn't work nicely with. Unlike the C version, __might_sleep() is used instead of might_sleep() to show proper debug info; the file name and line number. might_resched() could be added to match what the C version does but this function works without it. The sleep_before_read argument isn't supported since there is no user for now. It's rarely used in the C version. read_poll_timeout() can only be used in a nonatomic context. This requirement is not checked by these abstractions, but it is intended that klint [1] or a similar tool will be used to check it in the future. Link: https://rust-for-linux.com/klint [1] Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Add Rust TIMEKEEPING and TIMER abstractions to the maintainers entry respectively. Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Add a wrapper for fsleep(), flexible sleep functions in include/linux/delay.h which typically deals with hardware delays. The kernel supports several sleep functions to handle various lengths of delay. This adds fsleep(), automatically chooses the best sleep method based on a duration. sleep functions including fsleep() belongs to TIMERS, not TIMEKEEPING. They are maintained separately. rust/kernel/time.rs is an abstraction for TIMEKEEPING. To make Rust abstractions match the C side, add rust/kernel/time/delay.rs for this wrapper. fsleep() can only be used in a nonatomic context. This requirement is not checked by these abstractions, but it is intended that klint [1] or a similar tool will be used to check it in the future. Link: https://rust-for-linux.com/klint [1] Reviewed-by:
Gary Guo <gary@garyguo.net> Reviewed-by:
Alice Ryhl <aliceryhl@google.com> Reviewed-by:
Fiona Behrens <me@kloenk.dev> Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Introduce a type representing a specific point in time. We could use the Ktime type but C's ktime_t is used for both timestamp and timedelta. To avoid confusion, introduce a new Instant type for timestamp. Rename Ktime to Instant and modify their methods for timestamp. Implement the subtraction operator for Instant: Delta = Instant A - Instant B Reviewed-by:
Boqun Feng <boqun.feng@gmail.com> Reviewed-by:
Gary Guo <gary@garyguo.net> Reviewed-by:
Fiona Behrens <me@kloenk.dev> Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Introduce a type representing a span of time. Define our own type because `core::time::Duration` is large and could panic during creation. time::Ktime could be also used for time duration but timestamp and timedelta are different so better to use a new type. i64 is used instead of u64 to represent a span of time; some C drivers uses negative Deltas and i64 is more compatible with Ktime using i64 too (e.g., ktime_[us|ms]_delta() APIs return i64 so we create Delta object without type conversion. i64 is used instead of bindings::ktime_t because when the ktime_t type is used as timestamp, it represents values from 0 to KTIME_MAX, which is different from Delta. as_millis() method isn't used in this patchset. It's planned to be used in Binder driver. Reviewed-by:
Andrew Lunn <andrew@lunn.ch> Reviewed-by:
Alice Ryhl <aliceryhl@google.com> Reviewed-by:
Gary Guo <gary@garyguo.net> Reviewed-by:
Fiona Behrens <me@kloenk.dev> Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Add PartialEq/Eq/PartialOrd/Ord trait to Ktime so two Ktime instances can be compared to determine whether a timeout is met or not. Use the derive implements; we directly touch C's ktime_t rather than using the C's accessors because it is more efficient and we already do in the existing code (Ktime::sub). Reviewed-by:
Trevor Gross <tmgross@umich.edu> Reviewed-by:
Alice Ryhl <aliceryhl@google.com> Reviewed-by:
Gary Guo <gary@garyguo.net> Reviewed-by:
Fiona Behrens <me@kloenk.dev> Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Add __might_sleep_precision(), Rust friendly version of __might_sleep(), which takes a pointer to a string with the length instead of a null-terminated string. Rust's core::panic::Location::file(), which gives the file name of a caller, doesn't provide a null-terminated string. __might_sleep_precision() uses a precision specifier in the printk format, which specifies the length of a string; a string doesn't need to be a null-terminated. Modify __might_sleep() to call __might_sleep_precision() but the impact should be negligible. strlen() isn't called in a normal case; it's called only when printing the error (sleeping function called from invalid context). Note that Location::file() providing a null-terminated string for better C interoperability is under discussion [1]. Link: https://github.com/rust-lang/libs-team/issues/466 [1] Reviewed-by:
Alice Ryhl <aliceryhl@google.com> Co-developed-by:
Boqun Feng <boqun.feng@gmail.com> Signed-off-by:
Boqun Feng <boqun.feng@gmail.com> Signed-off-by:
FUJITA Tomonori <fujita.tomonori@gmail.com>
-
Daniel Almeida authored
-
-
Switch from being a refcount wrapper itself to a transparent wrapper around `bindings::drm_device`. The refcounted type then becomes ARef<Device<T>>. Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
-
The DRM shmem helper includes common code useful for drivers which allocate GEM objects as anonymous shmem. Add a Rust abstraction for this. Drivers can choose the raw GEM implementation or the shmem layer, depending on their needs. Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
There doesn't seem to be a way for the Rust bindings to get a compile-time constant reference to drm_gem_shmem_vm_ops, so we need to duplicate that structure in Rust... this isn't nice... Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
Daniel Almeida authored
-
drm_mm provides a simple range allocator, useful for managing virtual address ranges. Add a Rust abstraction to expose this module to Rust drivers. Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
We cannot drop ARef<GpuVmBo<T>> references within the step_*() calls, since the destructore takes the object lock but that is already locked here. Instead of providing a method that the callback can use to obtain a reference (which, when dropped, would deadlock), grab a reference ourselves and pass it explicitly into the callback as a &ref. Thus, we can drop it without locking again. Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
Daniel Almeida authored
-
-
Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
This is just for basic usage in the DRM shmem abstractions for implied locking, not intended as a full DMA Reservation abstraction yet. Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
Daniel Almeida authored
This u64/usize mismatch will probably be gone on 6.14
-
-
The io_pgtable subsystem implements page table management for various IOMMU page table formats. This abstraction allows Rust drivers for devices with an embedded MMU to use this shared code. Signed-off-by:
Asahi Lina <lina@asahilina.net>
-
Daniel Almeida authored
These accessors can be used to retrieve an IRQ from a platform device by index or name. The IRQ can then be used to request the line using irq::request::Registration::register() and irq::request::ThreadedRegistration::register(). Signed-off-by:
Daniel Almeida <daniel.almeida@collabora.com>
-
Daniel Almeida authored
Add support for registering IRQ handlers in Rust. IRQ handlers are extensively used in drivers when some peripheral wants to obtain the CPU attention. Registering a handler will make the system invoke the passed-in function whenever the chosen IRQ line is triggered. Both regular and threaded IRQ handlers are supported through a Handler (or ThreadedHandler) trait that is meant to be implemented by a type that: a) provides a function to be run by the system when the IRQ fires and, b) holds the shared data (i.e.: `T`) between process and IRQ contexts. The requirement that T is Sync derives from the fact that handlers might run concurrently with other processes executing the same driver, creating the potential for data races. Ideally, some interior mutability must be in place if T is to be mutated. This should usually be done through the in-flight SpinLockIrq type. Co-developed-by:
Alice Ryhl <aliceryhl@google.com> Signed-off-by:
Alice Ryhl <aliceryhl@google.com> Signed-off-by:
Daniel Almeida <daniel.almeida@collabora.com>
-
The semantics of various irq disabling guards match what *_irq_{disable,enable}() provide, i.e. the interrupt disabling is properly nested, therefore it's OK to switch to use *_irq_{disable,enable}() primitives. Signed-off-by:
Boqun Feng <boqun.feng@gmail.com>
-
`SpinLock`'s backend can be used for `SpinLockIrq`, if the interrupts are disabled. And it actually provides performance gains since interrupts are not needed to be disabled anymore. So add `Backend::BackendInContext` to describe the case where one backend can be used for another. Use the it to implement the `lock_with()` so that `SpinLockIrq` can avoid disabling interrupts by using `SpinLock`'s backend. Signed-off-by:
Boqun Feng <boqun.feng@gmail.com>
-
Now that we've introduced an `InterruptDisabled` token for marking contexts in which IRQs are disabled, we can have a way to avoid `SpinLockIrq` disabling interrupts if the interrupts have already been disabled. Basically, a `SpinLockIrq` should work like a `SpinLock` if interrupts are disabled. So a function: (&'a SpinLockIrq, &'a InterruptDisabled) -> Guard<'a, .., SpinLockBackend> makes senses. Note that due to `Guard` and `InterruptDisabled` has the same lifetime, interrupts cannot be enabled whiel the Guard exists. Add a `lock_with()` interface for `Lock`, and an associate type of `Backend` to describe the context. [Boqun: Change the interface a lot, now `SpinLockIrq` can use the `lock()` function, but it always disable the interrupts, reuse the `lock_with()` method to provide a way for locking if interrupts are already disabled. `lock_with()` implementation will be added later.] Signed-off-by:
Lyude Paul <lyude@redhat.com> Co-Developed-by:
Boqun Feng <boqun.feng@gmail.com> Signed-off-by:
Boqun Feng <boqun.feng@gmail.com>
-
A variant of SpinLock that is expected to be used in noirq contexts, so lock() will disable interrupts and unlock() (i.e. `Guard::drop()` will undo the interrupt disable. [Boqun: Port to use spin_lock_irq_disable() and spin_unlock_irq_enable()] Signed-off-by:
Lyude Paul <lyude@redhat.com> Co-Developed-by:
Boqun Feng <boqun.feng@gmail.com> Signed-off-by:
Boqun Feng <boqun.feng@gmail.com>
-
spin_lock_irq_disable() and spin_unlock_irq_enable() are inline functions, to use them in Rust, helpers are introduced. This is for interrupt disabling lock abstraction in Rust. Signed-off-by:
Boqun Feng <boqun.feng@gmail.com>
-