ReviewOS

home-lang/home-os

A3: volatile MMIO load/store semantics and barrier intrinsics in the Home language (dmb/dsb/isb, ldar/stlr, `*volatile T` lowering on aarch64)

#53
Open chris opened this 8 days ago ·
8 days ago

Epic: #113 · Milestone: MC1 — Toolchain: aarch64

Why

MASTER_PLAN names A3 as "the prerequisite for ever un-stubbing arm64.home honestly". On x86 a plain pointer dereference to MMIO mostly works because the memory model is strong; on ARMv8 it does not: the compiler may reorder or merge accesses, and device memory needs dmb/dsb around DMA hand-offs. Today kernel/src/drivers/bcm_emmc.home, gpio.home, i2c.home, spi.home do MMIO through core/memory.home's read_u32/write_u32 — raw @ptrFromInt derefs, no barriers — so closing S8 alone would not make them correct.

Language surface (proposed)

  • *volatile T already exists per CLAUDE.md; define its semantics precisely: every read/write is a single access of the natural size, never elided, merged, or reordered with other volatile accesses.
  • Intrinsics: @mmio_read(u8|u16|u32|u64, addr), @mmio_write(...), @barrier(.{ .kind = .dmb|.dsb|.isb, .domain = .sy|.ish|.osh|.ld|.st }), @wfe/@wfi/@sev, @read_sysreg("CurrentEL"), @write_sysreg("HCR_EL2", v).
  • Lowering on aarch64: ldr/str on a register-addressed pointer for volatile; dmb ish on @barrier; mrs/msr for sysregs. On x86: mov + mfence/lfence/sfence mapping.

Tasks

  • Spec section in the Home language reference; tests that assert instruction sequences in the codegen test suite.
  • Implement in both kernel codegen paths so drivers stay arch-neutral.
  • kernel/src/core/memory.home: make read_u32/write_u32 wrappers over the intrinsics (with explicit barrier variants read_u32_relaxed, write_u32_release).

Acceptance

Codegen tests green on both arches; a QEMU virt kernel toggles a PL011 register through *volatile and the emitted asm contains no merged/elided accesses (asserted by grep on the .s).

Size: M · Depends on: #51 (rung 1–4) · Blocks: #60

8 days ago

Compiler-side work mirrored to home-lang/home#584.

8 days ago

Partially landed: MMIO barriers and architecture-neutral barrier intrinsics

home-lang/home@29b9eb740.

What works now. mmio_read{8,16,32,64} and mmio_write{8,16,32,64} lower to real sized loads and stores on both architectures, with the barrier discipline this issue asked for:

x86-64aarch64
after an MMIO read(nothing)dmb oshld
before an MMIO write(nothing)dmb oshst

The x86 column is empty on purpose and is documented as such: that memory model already orders loads with loads and stores with stores, so a fence there would be cost without meaning. On aarch64 they are mandatory — without them a driver's register writes can reach the device out of order, which is the classic silent Pi driver bug.

New architecture-neutral intrinsics, alongside the x86 spellings which still work so existing kernel source keeps building: barrier_full (dsb sy / mfence), barrier_loads (dmb ld / lfence), barrier_stores (dmb st / sfence), barrier_sync (isb / cpuid).

CPU-state intrinsics are now named for their effect and lower per architecture: hlt → hlt / wfi, cli/sti → cli/sti / msr daifset,#2 and msr daifclr,#2, pause → pause / yield.

Port I/O is refused on aarch64, with a diagnostic naming the replacement:

# ERROR: outb() needs a port I/O address space, which aarch64 does not have.
# ERROR: use mmio_read8/mmio_write8 against the device's register address instead.

That matters more than it looks: emitting nothing, or an approximation, would leave a driver that reads as correct and touches no hardware — precisely the failure mode of stub S8 in the OS tree.

Still open in this issue

  • The language-level surface: *volatile T semantics written into the language reference, and @mmio_read/@mmio_write/@barrier/@read_sysreg/@write_sysreg as first-class intrinsics rather than the current name-matched function forms.
  • msr/mrs system-register access, needed by MMU, GIC and exception-vector setup (rung 11 of #582).
  • Making kernel/src/core/memory.home's read_u32/write_u32 wrappers over these, with explicit relaxed/release variants — that is the OS-side half, home-lang/home-os#60.

Sign in to comment on this issue.