Prep: unsafe, and Leaving std — 21r · 30k¶
Session: Fri Oct 2, 1h30 · Exercises: 21r_unsafe_bridge · 30k_kernel_basics · Prep time: ~25 min · Lecture: Week 6 · Below Rust
What you will build¶
First, on your laptop, the inner loop of a UART driver: a raw pointer to a fixed address, volatile register access at base-plus-offset, a safe wrapper that refuses a bad offset, and a plain-memory byte copy. The tests substitute a byte array for the chip's register block. Second, the first kernel crate: a Rust binary that tells the compiler no OS exists beneath it and supplies the one function demanded in return. oslings run checks that each register access lands in its own slot and nothing past the end is touched, then that the kernel builds for riscv64gc-unknown-none-elf — no QEMU yet.
Concepts you need¶
- Raw pointer vs. reference;
.add(n)scales by the pointee — Week 6 · Memory you cannot borrow: MMIO and raw pointers · Unsafe guide: Raw pointers unsafe: five operations, nothing disabled — Week 6 · Whatunsafeunlocks, and what it does not · Unsafe guide: What unsafe does not do- Safe wrapper, unsafe core — Week 6 · What
unsafeunlocks, and what it does not · Unsafe guide: Before you write unsafe - Volatile MMIO — Week 6 · Volatile: the load that never repeats
core/alloc/std— Week 6 · Whatstdis, and why a kernel cannot have it · Unsafe guide: core, alloc, and std- The
no_stdskeleton, by build error — Week 6 · The bare-metal skeleton · Unsafe guide: The no_std skeleton
Read before class¶
| What | Time |
|---|---|
Week 6 · Friday · 21r Raw pointers, unsafe, and volatile, all three sections |
4 min |
Week 6 · Friday · 30k Leaving std, both sections |
2 min |
| Unsafe guide: What unsafe does through Raw pointers | 7 min |
| Unsafe guide: The no_std skeleton and Symptoms and their causes | 4 min |
| Setup: Check your environment — target installed? | 2 min |
Mental model¶
QEMU's virt board has a "test finisher" register at 0x10_0000; storing 0x5555 there powers the machine off — how oslings ends every kernel run.
const FINISHER: *mut u32 = 0x10_0000 as *mut u32; // safe: a number with a type
pub fn power_off() -> ! { // safe wrapper; `!` = never returns
// promise: this address is the register
unsafe { core::ptr::write_volatile(FINISHER, 0x5555) }
loop {} // store did not take: spin
}
Making the pointer is safe; only the store needs unsafe, in a one-line block with its promise above it. The store is volatile because the address is a chip, not RAM: as *FINISHER = 0x5555 the compiler may reorder, merge, or delete it. Nothing mentions std; core::ptr survives #![no_std], so this compiles unchanged on bare RISC-V. Every kernel driver has this shape: a small unsafe core with a named promise, wrapped in safe Rust.
Check yourself¶
- Which of these need
unsafe:let p = 0x1000_0000 as *mut u8;,p.add(5),*p = 1? Do two&mutborrows of one element compile insideunsafe { }?Answer
The last two: making a pointer is just arithmetic;.addis anunsafe fn(an address outside the allocation is already UB); dereferencing is operation #1. The double borrow still fails withE0499—unsafenever touches the borrow checker. - A driver polls
while *LSR & 0x20 == 0 {}and hangs, though the device is ready. Why?Answer
Nothing in the loop writes*LSR, so the optimizer hoists the load out: "not ready now, spin forever".core::ptr::read_volatileforces the load on every iteration. - Under
#![no_std], which survive:Option,Vec,println!,core::ptr::write_volatile? Which error says the panic handler is missing?Answer
Optionandwrite_volatilelive incore.Vecneedsallocand an allocator you have not written;println!needs an OS. The error:`#[panic_handler]` function required, but not found.
What "done" looks like¶
oslings run is green, then oslings submit before you leave. Not green? Submit anyway — the tests that pass earn their share — then finish it at a make-up session (office hours, on the class network) for three quarters, or anywhere else for half, and submit again.
If you finish early¶
Work Week 6 · Problem 2: Which lines need unsafe?, then run the rustc --print cfg command from Week 6 · Reading riscv64gc-unknown-none-elf yourself. Then start reading next Thursday's prep page and its lecture, Week 7 · From Reset to Page Tables. Afterward, the xv6 book chapter 2 through section 2.6, and The Rustonomicon chapters 1–3.