Skip to content

Commit 89f584c

Browse files
authored
Merge pull request #55 from osteffenrh/custom-mmio-backend
Add custom MMIO backend
2 parents caa638e + 8471ff5 commit 89f584c

7 files changed

Lines changed: 581 additions & 4 deletions

File tree

.github/workflows/rust.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ jobs:
1919
run: cargo build
2020
- name: Test
2121
run: cargo test
22+
- name: Test with custom-mmio
23+
run: cargo test --features=custom-mmio
2224
- name: Run clippy
2325
uses: actions-rs/clippy-check@v1
2426
with:

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Improvements
6+
7+
- Added `custom-mmio` feature to allow the user of the crate to override how the underlying MMIO
8+
operations are done. This may be useful for faking devices for driver tests, or for virtual
9+
platforms where MMIO requires co-ordination with the hypervisor.
10+
311
## 0.3.0
412

513
### Breaking changes

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,12 @@ keywords = ["mmio"]
1010
categories = ["embedded", "no-std"]
1111
rust-version = "1.85"
1212

13+
[features]
14+
custom-mmio = []
15+
1316
[dependencies]
1417
zerocopy = { version = "0.8.50", features = ["derive"] }
18+
19+
[package.metadata.docs.rs]
20+
features = ["custom-mmio"]
21+
rustdoc-args = ["--cfg", "docsrs"]

README.md

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ unsafe {
2626
}
2727
```
2828

29-
Depending on your platform this will either use `write_volatile` or some platform-dependent inline
30-
assembly to perform the MMIO write.
29+
Depending on your platform this will either use `write_volatile`, some platform-dependent inline
30+
assembly, or a [custom backend](#custom-mmio-backend) to perform the MMIO write.
3131

3232
### Safe MMIO methods
3333

@@ -92,6 +92,53 @@ should never be more than one `PhysicalInstance` pointer to the same device. Thi
9292
table management code can take a `PhysicalInstance<T>` and return a `UniqueMmioPointer<T>` when a
9393
device is mapped into the page table.
9494

95+
### Custom MMIO backend
96+
97+
Some environments need to intercept MMIO accesses instead of letting them hit
98+
hardware directly. The `custom-mmio` feature lets the consuming project inject
99+
its own read/write implementations, even across the dependency chain, while
100+
keeping the rest of the safe-mmio API unchanged.
101+
102+
Enable the feature in your `Cargo.toml`:
103+
104+
```toml
105+
[dependencies]
106+
safe-mmio = { version = "0.3.0", features = ["custom-mmio"] }
107+
```
108+
109+
Then implement the `MmioOps` trait and register it with `set_mmio_ops!`:
110+
111+
```rust
112+
use safe_mmio::custom_mmio::MmioOps;
113+
114+
struct MyBackend;
115+
116+
// SAFETY: Each method performs a single MMIO access of the indicated width.
117+
unsafe impl MmioOps for MyBackend {
118+
unsafe fn read_u8(src: *const u8) -> u8 { /* ... */ }
119+
unsafe fn read_u16(src: *const u16) -> u16 { /* ... */ }
120+
unsafe fn read_u32(src: *const u32) -> u32 { /* ... */ }
121+
unsafe fn read_u64(src: *const u64) -> u64 { /* ... */ }
122+
unsafe fn write_u8(dst: *mut u8, value: u8) { /* ... */ }
123+
unsafe fn write_u16(dst: *mut u16, value: u16) { /* ... */ }
124+
unsafe fn write_u32(dst: *mut u32, value: u32) { /* ... */ }
125+
unsafe fn write_u64(dst: *mut u64, value: u64) { /* ... */ }
126+
}
127+
128+
safe_mmio::set_mmio_ops!(MyBackend);
129+
```
130+
131+
The `set_mmio_ops!` macro generates `#[no_mangle]` functions that the library resolves via
132+
`extern "Rust"` declarations. Exactly one call must exist in the final binary; linking fails
133+
otherwise.
134+
135+
When `custom-mmio` is enabled it replaces both the default `volatile` backend and the `aarch64`
136+
inline-assembly backend.
137+
138+
**Testing note:** Unit tests (`cargo test --lib --features custom-mmio`) work because the library
139+
includes a volatile-based `MmioOps` implementation gated on `#[cfg(test)]`. Doc tests build as
140+
separate binaries and cannot see `#[cfg(test)]` items, so use `--lib` to skip them.
141+
95142
## Comparison with other MMIO crates
96143

97144
There are a number of things that distinguish this crate from other crates providing abstractions

0 commit comments

Comments
 (0)