Currently, I see 23 targets supported by microkit. Each of them has 3 different modes (benchmark
, debug
& release
). So overall, there are quite some variants of the API offered. To add upon that, the header files itself are polymorphic, as in they themselves contain macros to adapt for different target platforms, i. e. like this:
#if defined(CONFIG_RISCV_HYPERVISOR_SUPPORT)
I'm currently trying to make Rust bindings for microkit, as to support implementation of protection domains in Rust. While it is possible to just embrace this high adaptability of the API, I see a real danger that this will (and has in the past!) seriously hindered solid Rust support of microkit (and seL4 in the grander picture). In order to make my life easier (and the programming in Rust for microkit story nicer), I have a wishlist. I present various options, starting with the easy-to-implement-but-not-so-nice to the more-complex-to-implement-but-way-nicer-to-use.
- Keep everything like it is on microkit side. On Rust side
- Detect the
$MICROKIT_SDK
path
- Ignore benchmark config, but
- translate debug/release from Rust to debug/release header files in microkit
- Run rust-bindgen in
build.rs
to dynamically generate the bindings
- Have a Cargo feature per each officially supported target board, use that feature to pick the target board
- Change microkit to one set of header-files per processor architecture. On Rust side
- Detect the
$MICROKIT_SDK
path
- Ignore benchmark config, but
- translate debug/release from Rust to debug/release header files in microkit
- Run rust-bindgen in
build.rs
to dynamically generate the bindings
- Change microkit to one set of header-files per processor architecture. On Rust side
- Detect the
$MICROKIT_SDK
path
- Ignore benchmark config, but
- translate debug/release from Rust to debug/release header files in microkit
- Run rust-bindgen in
build.rs
to dynamically generate the bindings
- Change microkit to one set of header-files per processor architecture and commit to a stable ABI. On Rust side
- Ignore benchmark config, but
- translate debug/release from Rust to debug/release header files in microkit
- Run rust-bindgen in once when publishing the crate generate the bindings
- Change microkit to one set of header-files per processor architecture and commit to a stable ABI. On Rust side
- Ignore benchmark config, but
- translate debug/release from Rust to debug/release header files in microkit
- Manually write bindings down to the syscalls. No microkit header files required.
From a user point of view, 4. and 5. are by far the most preferable ones. Its the only option where a pure Rust toolchain, without any libclang/binding generator stuff gets executed on the end-developers machine. They just use the microkit
/ microkit-sys
crate offered on https://crates.io/ . Its also the only option if we want a robust ecoystem to be built on top of microkit
, because only with a stable API & ABI we can avoid spurious type change problems.
With Option 4. however, considering that a significant portion of the microkit API is header only, we still would have to involve a C compiler to get a final ELF for the protection domain. Option 5. on the other hand takes C tooling completely out of the equation, we could then compile pure Rust code down to an ELF that is usable in microkit. Of course Option 5. is more work when the ABI changes, these change would have to be ported over to the Rust code by hand.
If offering a stable API & ABI is not possible (or not yet possible), option 3. is preferable. While we do force binding generation on to the end-developer, we can automate quite some stuff. This way we can get away with all the fuzz about different target boards and associated header files. Instead, the combination of the Rust profile (debug vs release) and the Rust target (i.e. aarch64-unknown-none
) completely determine which header files to pick.
I totally understand, that likely asking for Option 5. is quite the ask at this early stage of microkit. However, getting at least to Option 3. would already considerable ease my pain in providing initial Rust support (and more significantly, ease the pain on making Rust libraries on top of microkit).
I'm looking forward for your feedback!