Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions issues/an-amd-vi-machine-isolates-no-device.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
status: assigned
kind: track
opened: 2026-10-10
---

# An AMD-Vi machine isolates no device

Held by the orchestrator's AMD laptop track: its stage 5, amdvi-translate, builds
translation, and its stage 6, amdvi-intremap, interrupt remapping.

On a machine whose IVRS describes AMD-Vi units, `kernel/src/arch/x86_64/amdvi/`
switches every unit off, so every device's DMA reaches all of memory and every
message-signalled interrupt is delivered as written. `DeviceSpace::create`
answers `Untranslated`, and a function a process would drive is refused its
claim (`iommu::remapping` is `NotRemapped`), so no userland driver runs there.

What remains is translation, then interrupt remapping:

- **Translation.** A device table blocking by default, every one of the 65,536
entries `V=1, TV=1` with `IR=IW=0` — an entry left `V=0` passes its
requester's DMA untranslated — identity domains for kernel drivers, a
command buffer whose `COMPLETION_WAIT` is waited on under a `Tripwire`, and
the event log feeding `iommu::fault`.
- **Interrupt remapping.** Interrupt remapping tables, the I/O APIC's and the
HPET's requester ids from the IVRS's special entries, and `claim_msi`.

Constraints a reader would otherwise pay to re-derive:

- QEMU 11.1.1's `amd-iommu` translates a function only with `dma-remap=on`,
and only once an `INVALIDATE_DEVTAB_ENTRY` names it; it takes a device table
entry of `Mode` 0 as pass-through whatever `IR` and `IW` say, where the
specification blocks it (`hw/i386/amd_iommu.c` at v11.1.1).
- No AMD machine is in reach of the metal suite.

**Exit:** a guest boot on `Profile::MetalAmdVi` in which a kernel driver's
DMA goes through a domain of its own, a DMA outside it is recorded as a
fault, and a claimed function's message is delivered through its own
remapping entry.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
status: open
kind: tooling
opened: 2026-10-10
---

# The host gate aborts with no message when a destructor panics during unwinding

`cargo run -- --ci host > <file> 2>&1` at `d242c7f05` (branch `wt/toyos-amdvi`)
exited 134. Its log stops mid-step, at the `failures:` header of the
`mutate-landed-child-retires-nothing` control, with no panic message and no
verdict. The rerun at the same head, nothing changed, exited 0.

macOS crash reports show five processes aborting within 0.7 s of each other,
from three different binaries, each with
`SIGABRT` from `abort()`. In every one the faulting thread is
`core::panicking::panic_in_cleanup`, a destructor panicking while another
panic unwound, directly under:

- `toyos_build::ci::host`, called from `ci::dispatch` and `main`: three
`toyos-build` processes, two of them one binary.
- `toyos_build::build::build_test_parts`, under `build_test_image`,
`common::qemu::build_boot_image_with`, `QemuInstance::boot_with_options`
and `virt_selftest`, on a `run_tasks` worker: one guest-suite process.
- `common::lane::Run::exit`, called from the guest suite's `main`: one
guest-suite process.

Right after the abort the data volume holding every worktree, its `target/`
and the gate's redirected log was 99% full: 926 GiB, 887 GiB used, 12 GiB
available. Eight minutes later it read 82%, 169 GiB available.

What reading shows, not yet measured: every one of those frames reaches a
`Drop` that writes to stderr (`build::Building`, `lane::Run`), and
`eprintln!` panics when its write fails. A full volume under a redirected
stderr is one way for all five to fail inside the same second. The trigger is
unconfirmed; the system log for that minute was not readable.

Whatever the trigger, a gate that dies without saying why is a defect of its
own: a destructor reached while unwinding must not panic.

**Exit:** a host test in which `Building`'s and `Run`'s destructors run during
an unwinding panic with stderr refusing every write, and the process exits non-zero by
its own exit code, never by `SIGABRT`.
8 changes: 5 additions & 3 deletions kernel/src/actuator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,11 @@ actuators! {
/// Withhold `VIRTIO_F_ACCESS_PLATFORM` from every virtio device but the console, staging a function whose addresses the unit never translates.
virtio_no_access_platform = "virtio-no-access-platform";

/// Leave every IOMMU unit queueing, translating and remapping through
/// tables of its own, as firmware may hand one over, just before this
/// kernel programs it. Judged by `iommu_firmware_left`.
/// Leave every IOMMU unit as firmware may hand one over, just before this
/// kernel takes it: a VT-d unit queueing, translating and remapping
/// through tables of its own, an AMD-Vi unit blocking every device's DMA
/// with its command buffer and event log running. Judged by
/// `iommu_firmware_left` and `amdvi_firmware_left`.
iommu_firmware_left = "iommu-firmware-left";

/// Read the DMAR's flags with `INTR_REMAP` clear, as on a platform whose
Expand Down
Loading
Loading