Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Shared Memory

This chapter covers interacting with shared memory from protection domains written in Rust. Navigate to and run the example:

cd workspaces/microkit/shared-memory
make simulate

The example system description specifies two protection domains which share two memory regions:

The Microkit tool will inject memory region virtual addresses into protection domain images according to the setvar_vaddr attribute values. For example, the virtual address of the mapping of region_a into the client protection domain will be injected into the microkit-shared-memory-client.elf image at the location specified by then region_a_vaddr symbol.

In the case of Rust, declaring a symbol that the Microkit tool can patch requires a bit more intentionality than in the C case. The sel4_microkit::var! macro is provided to declare such symbols.

The var! macro's implementation is just a few lines of code. We want to express this symbol as a global variable that does not change at runtime, but which cannot be assumed to have the value we assign it at compile time, and which must not be optimized away. The near-trivial sel4_immutable_cell::ImmutableCell type encapsulates this pattern. The #[no_mangle] attribute instructs the compiler to use the name of the variable as the name of the symbol. This is the default in C, but not Rust. We direct the compiler to put this symbol in the .data section with #[link_section = ".data"] to ensure that space is allocated for it in the ELF file itself, not just the program image it describes.

So far, the example protection domains just store pointers to the shared memory regions in their handler state:

Step 11.A       

Let's assign types to these shared memory regions. We can define our types in a crate that both the client and server can use:

Suppose region_a: [u8; REGION_A_SIZE] and region_b: RegionB. You could just turn the virtual addresses we get in our var! symbols into pointers and start interacting with the shared memory regions with unsafe ptr::* operations, but we can leverage the Rust type system to come up with a solution that only requires unsafe at initialization time.

Step 11.B       

The sel4-shared-memory crate provides a way for you to declare a memory region's type and bounds, along with the memory access operations that can safely be used on it, so that you can access it without unsafe code. That initial declaration is, however, unsafe.

The sel4-shared-memory is a thin wrapper around the sel4_abstract_ptr crate, instantiating its abstract pointer types with memory access operations suitable for memory that is shared with another protection domain.

The sel4_microkit::memory_region_symbol! macro is like the sel4_microkit::var! macro, except specialized for shared memory region virtual address symbols. For one, the underlying symbol is always of type usize and the macro returns a value of type NonNull<_>. memory_region_symbol! has a few additional features. For example, memory_region_symbol!(foo: *mut [u8] n = BAR) returns a NonNull<[u8]> with a runtime slice length of BAR.

See this step's diff for how to put this all together.