|
| 1 | +--- |
| 2 | +minutes: 18 |
| 3 | +--- |
| 4 | + |
| 5 | +# Bindings and Safe Interfaces |
| 6 | + |
| 7 | +`bindgen` is used to generate low-level, unsafe bindings for C interfaces. |
| 8 | + |
| 9 | +But to reap the benefits of Rust, we want to use safe, foolproof interfaces to unsafe functionality. |
| 10 | + |
| 11 | +Subsystems are expected to implement safe interfaces on top of the low-level generated bindings. |
| 12 | +These safe interfaces are exposed as top-level modules within the [`kernel` crate](https://rust.docs.kernel.org/kernel/). |
| 13 | +The top-level `bindings` module holds the unsafe `bindgen`-generated bindings, |
| 14 | +which are generated from the C headers included by `rust/bindings/bindings_helper.h`. |
| 15 | + |
| 16 | +In Rust for Linux, unsafe `bindgen`-generated bindings should not be used outside the `kernel` crate. |
| 17 | +Drivers and other subsystems will make use of the safe abstractions from this crate. |
| 18 | + |
| 19 | +Only a subset of Linux subsystems currently have such abstractions. |
| 20 | + |
| 21 | +It's worth browsing the [list of modules](https://rust.docs.kernel.org/kernel/#modules) |
| 22 | +exposed by the `kernel` crate to see what exists currently. |
| 23 | +Many of these subsystems have only partial bindings based on the needs of consumers so far. |
| 24 | + |
| 25 | +## Adding a Module |
| 26 | + |
| 27 | +To add a module for some subsystem, first its header must be added to `bindings_helper.h`. |
| 28 | +It may be necessary to write some custom code to wrap macros or `inline` functions |
| 29 | +that are not automatically handled by `bindgen`; this code lives in the `rust/helpers/` directory. |
| 30 | + |
| 31 | +Then we need to write a safe abstraction using these bindings and exposing them to the rest of kernel Rust. |
| 32 | + |
| 33 | +Some commits from work-in-progress bindings and abstractions |
| 34 | +can provide an idea of what it looks like to expose new kernel functionality: |
| 35 | + |
| 36 | +- GPIO Consumer: [fecb4bd73f06bb2cac8e16aca7ef0e2f1b6acb50](https://github.com/Fabo/linux/commit/fecb4bd73f06bb2cac8e16aca7ef0e2f1b6acb50) |
| 37 | +- Regmap: [ec0b740ac5ab299e4c86011a0002919e5bbe5c2d](https://github.com/Fabo/linux/commit/ec0b740ac5ab299e4c86011a0002919e5bbe5c2d) |
| 38 | +- I2C: [70ed30fcdf8ec62fa91485c3c0a161a9d0194668](https://github.com/Fabo/linux/commit/70ed30fcdf8ec62fa91485c3c0a161a9d0194668) |
| 39 | + |
| 40 | +## Guidelines for Abstractions |
| 41 | + |
| 42 | +Abstractions may not be perfectly safe, but should try to be as safe as possible. |
| 43 | +Unsafe functionality exposed should have its safety conditions documented |
| 44 | +so that users have guidance on how to use the functionality and justify such use. |
| 45 | + |
| 46 | +Abstractions should also attempt to present relatively idiomatic Rust in their interfaces: |
| 47 | +- Follow Rust naming/capitalization conventions while remaining unsurprising to kernel developers. |
| 48 | +- Use RAII instead of manual resource management where possible. |
| 49 | +- Avoid raw pointers to bound kernel objects in favor of safer, more limited interfaces. |
| 50 | + |
| 51 | + When exposing types from generated bindings, code should make use of the |
| 52 | + [`Opaque<T>`](https://rust.docs.kernel.org/kernel/types/struct.Opaque.html) type |
| 53 | + along with native Rust references and the |
| 54 | + [`ARef<T>`](https://rust.docs.kernel.org/kernel/types/struct.ARef.html) type for types that are inherently reference-counted. |
| 55 | + This type links types' built-in reference count operations to the `Clone` and `Drop` traits. |
| 56 | + |
| 57 | +## Submitting the cyclic dependency |
| 58 | + |
| 59 | +We already know that drivers should not use unsafe bindings directly. |
| 60 | +But subsystem maintainers may balk if they see patches submitted that add Rust abstractions without motivation or consumers. |
| 61 | +But drivers and subsystem abstractions may have to be submitted separately to different maintainers |
| 62 | +due to the distributed nature of Linux development. |
| 63 | + |
| 64 | +So how should a developer submit a driver that requires bindings/abstractions for a subsystem not yet exposed to Rust? |
| 65 | + |
| 66 | +There are two main approaches[^1]: |
| 67 | + |
| 68 | +1. Submit the driver as an RFC before submitting the abstractions it relies upon while referencing the RFC as a potential consumer. |
| 69 | +2. Submit a stub driver and fill out non-stub functionality as subsystem abstractions land. |
| 70 | + |
| 71 | +[^1]: <https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/topic/Upstreaming.20a.20driver.20with.20unsave.20C.20API.20calls.3F/near/471677707> |
0 commit comments