From fd4ca5ae6aced86b49988c0ef24b168ac11cbd1a Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 07:55:28 +0200 Subject: [PATCH 1/6] The T14's root-bridge list is committed as decoded values, not as its bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The owner ruled on 2026-10-04 ("Local only; decode the 186 bytes"): "Full tables stay out of the repo (a copy you hold); the 186-byte fixture on main is replaced by decoded values, as 'Extracts only' says." `toyos-acpi/fixtures/thinkpad-t14/root-bridge-0.bin` was the 186 bytes the T14's firmware answered through `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL:: Configuration`, off the loader log of metal run 33. It goes, with its `SOURCE` and its `src/licence.rs` entry. In its place, `tests/common::t14_root_bridge` lays the same list out of its decoded fields: four QWORD Address Space Descriptors (I/O 0x3000..=0x3fff; memory 0xa2000000..=0xbcffffff and 0x4000000000..=0x603dbfffff, granularities 0x20 and 0x40; bus 0..=0x79) and the End Tag. Before the file went, a test asserting the builder's output equal to the file's bytes ran green, so the two tests that read the list run over the identical 186 bytes. The descriptor builder moves into `tests/common` beside the table builders, taking every field; `tests/resource.rs`'s well-formed `qword` is a call into it. The OVMF list is QEMU's and stays as captured. Mutations, each applied, built, run and reverted: - the decoder's length truncated to 32 bits: the T14 decode test red (101), the OVMF decode test green (0) — only the T14's numbers reach it; - the zero-length guard dropped: the corpus sweep red (101); - the T14 list's bus descriptor dropped: the corpus sweep red (101) on its mutation count. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- src/licence.rs | 6 ---- toyos-acpi/fixtures/thinkpad-t14/SOURCE | 11 ------ .../fixtures/thinkpad-t14/root-bridge-0.bin | Bin 186 -> 0 bytes toyos-acpi/tests/common/mod.rs | 34 ++++++++++++++++++ toyos-acpi/tests/corpus.rs | 9 ++--- toyos-acpi/tests/fixtures.rs | 7 ++-- toyos-acpi/tests/resource.rs | 33 +++-------------- 7 files changed, 44 insertions(+), 56 deletions(-) delete mode 100644 toyos-acpi/fixtures/thinkpad-t14/SOURCE delete mode 100644 toyos-acpi/fixtures/thinkpad-t14/root-bridge-0.bin diff --git a/src/licence.rs b/src/licence.rs index cc0b165562c..bdc30429c02 100644 --- a/src/licence.rs +++ b/src/licence.rs @@ -276,12 +276,6 @@ pub const COMMITTED_FILES: &[(&str, &str, &str, Terms)] = &[ "ours: OVMF's answer on a q35 guest, read off that boot's own loader log", Terms::Spdx("MIT OR Apache-2.0"), ), - ( - "toyos-acpi/fixtures/thinkpad-t14/root-bridge-0.bin", - "a734078ed9ca3971ce804fd9ecc97b7794f816058f9ae17e47e0d2bcb63af0f3", - "ours: the T14's answer, read off that boot's own loader log on the stick", - Terms::Spdx("MIT OR Apache-2.0"), - ), // A bcachefs volume upstream's own tools wrote, gzipped. The bytes inside // it are this repository's test material; `NOTICE` carries the raw digest, // the commands, and the fsck that called it clean. diff --git a/toyos-acpi/fixtures/thinkpad-t14/SOURCE b/toyos-acpi/fixtures/thinkpad-t14/SOURCE deleted file mode 100644 index 760885c5900..00000000000 --- a/toyos-acpi/fixtures/thinkpad-t14/SOURCE +++ /dev/null @@ -1,11 +0,0 @@ -The ACPI resource descriptors `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration` -answered with on the one root bridge of the ThinkPad T14 this repository is -tested on, off that machine's own firmware. - - root-bridge-0.bin 186 bytes, off the `Root bridge: 0 (segment 0) 186 bytes:` - line in the `loader.log` the stick came back with from - metal run 33 (`tests/metalcase`). - -The bootloader printed the bytes and nothing decoded them on the way. What says -the length was right is the file itself: four descriptors whose own declared -lengths tile it exactly, then the End Tag. diff --git a/toyos-acpi/fixtures/thinkpad-t14/root-bridge-0.bin b/toyos-acpi/fixtures/thinkpad-t14/root-bridge-0.bin deleted file mode 100644 index f675c5b5b72141fcb0a8cf8dc361f7368b1f4511..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeCuW?*DM00Ri~zdb?-%o2d`yR<>H0)zu17lDZX|Nrj+(MUiV#D=JLKoSPA|Nq}_ dn}8(7z;M7;0muicW Vec { body.extend_from_slice(entries); sdt(b"APIC", 5, &body) } + +/// ACPI 6.5 Table 6.44's resource types. +pub const MEMORY: u8 = 0; +pub const IO: u8 = 1; +pub const BUS: u8 = 2; + +/// One QWORD Address Space Descriptor (ACPI 6.5 §6.4.3.5.1), field by field, +/// its General and Type Specific Flags clear. +pub fn qword_descriptor(kind: u8, granularity: u64, min: u64, max: u64, translation: u64, length: u64) -> Vec { + let mut d = vec![0x8A, 0x2B, 0x00, kind, 0x00, 0x00]; + for field in [granularity, min, max, translation, length] { + d.extend_from_slice(&field.to_le_bytes()); + } + d +} + +/// `descriptors`, then the End Tag over its checksum byte (ACPI 6.5 §6.4.2.9). +pub fn resource_list(descriptors: &[Vec]) -> Vec { + let mut bytes = descriptors.concat(); + bytes.extend_from_slice(&[0x79, 0x00]); + bytes +} + +/// What the ThinkPad T14's firmware answers for its root bridge 0 through +/// `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration`, decoded: its I/O range, +/// two memory windows and its bus range. +pub fn t14_root_bridge() -> Vec { + resource_list(&[ + qword_descriptor(IO, 0, 0x3000, 0x3fff, 0, 0x1000), + qword_descriptor(MEMORY, 0x20, 0xa200_0000, 0xbcff_ffff, 0, 0x1b00_0000), + qword_descriptor(MEMORY, 0x40, 0x40_0000_0000, 0x60_3dbf_ffff, 0, 0x20_3dc0_0000), + qword_descriptor(BUS, 0, 0, 0x79, 0, 0x7a), + ]) +} diff --git a/toyos-acpi/tests/corpus.rs b/toyos-acpi/tests/corpus.rs index 1b4ad4ec520..148536cbd7c 100644 --- a/toyos-acpi/tests/corpus.rs +++ b/toyos-acpi/tests/corpus.rs @@ -8,7 +8,7 @@ mod common; -use common::{declare_len, entry, madt, rsdp, sdt, xsdt, Machine}; +use common::{declare_len, entry, madt, rsdp, sdt, t14_root_bridge, xsdt, Machine}; use toyos_abi::boot::RootBridgeWindow; use toyos_acpi::{ dsdt_address, ecam_base, find_table, hpet_base, iapc_boot_arch, madt_entries, memory_windows, @@ -566,10 +566,7 @@ fn a_fadt_that_ends_before_arm_boot_arch_is_short() { /// Where the two firmwares' descriptor lists sit for the sweep below. const ROOT_BRIDGE_AT: u64 = 0x4_0000; -const ROOT_BRIDGES: &[(&str, &[u8])] = &[ - ("ovmf", include_bytes!("../fixtures/ovmf-pure-efi/root-bridge-0.bin")), - ("thinkpad-t14", include_bytes!("../fixtures/thinkpad-t14/root-bridge-0.bin")), -]; +const OVMF_BRIDGE: &[u8] = include_bytes!("../fixtures/ovmf-pure-efi/root-bridge-0.bin"); /// **No panic and no unbounded walk, over every byte of both firmwares' real /// descriptor lists.** Each byte takes each of its 255 other values in turn and @@ -579,7 +576,7 @@ const ROOT_BRIDGES: &[(&str, &[u8])] = &[ fn no_single_byte_mutation_of_a_firmwares_descriptor_list_panics_or_runs_away() { let mut mutations = 0u64; let mut refused = 0u64; - for (which, original) in ROOT_BRIDGES { + for (which, original) in [("ovmf", OVMF_BRIDGE.to_vec()), ("thinkpad-t14", t14_root_bridge())] { for offset in 0..original.len() { for value in 0..=255u8 { if original[offset] == value { diff --git a/toyos-acpi/tests/fixtures.rs b/toyos-acpi/tests/fixtures.rs index 608ccc12113..be40862d9ca 100644 --- a/toyos-acpi/tests/fixtures.rs +++ b/toyos-acpi/tests/fixtures.rs @@ -3,7 +3,7 @@ mod common; -use common::Machine; +use common::{t14_root_bridge, Machine}; use toyos_abi::boot::RootBridgeWindow; use toyos_acpi::{ century_of, dsdt_address, ecam_base, find_table, hpet_base, iapc_boot_arch, madt_entries, @@ -164,9 +164,8 @@ fn the_xsdt_walk_reaches_every_entry() { const ROOT_BRIDGE: u64 = 0x7f00_0000; const OVMF_BRIDGE: &[u8] = include_bytes!("../fixtures/ovmf-pure-efi/root-bridge-0.bin"); -const T14_BRIDGE: &[u8] = include_bytes!("../fixtures/thinkpad-t14/root-bridge-0.bin"); -fn bridge_windows(bytes: &'static [u8]) -> Vec { +fn bridge_windows(bytes: &[u8]) -> Vec { let regions: &[(u64, &[u8])] = &[(ROOT_BRIDGE, bytes)]; let mut out = [RootBridgeWindow::default(); 8]; let count = memory_windows(Machine { regions }, ROOT_BRIDGE, &mut out).expect("bytes a firmware answered with"); @@ -193,7 +192,7 @@ fn the_windows_a_boot_printed_are_what_that_firmwares_own_bytes_say() { #[test] fn a_second_firmwares_bytes_decode_to_that_machines_own_windows() { assert_eq!( - bridge_windows(T14_BRIDGE), + bridge_windows(&t14_root_bridge()), [ RootBridgeWindow { base: 0xa200_0000, length: 0x1b00_0000 }, RootBridgeWindow { base: 0x40_0000_0000, length: 0x20_3dc0_0000 }, diff --git a/toyos-acpi/tests/resource.rs b/toyos-acpi/tests/resource.rs index 298a97ec326..2a32804ce75 100644 --- a/toyos-acpi/tests/resource.rs +++ b/toyos-acpi/tests/resource.rs @@ -3,42 +3,17 @@ mod common; -use common::Machine; +use common::{qword_descriptor, resource_list as list, Machine, BUS, IO, MEMORY}; use toyos_abi::boot::RootBridgeWindow; use toyos_acpi::{memory_windows, ResourceError, MAX_LIST_BYTES}; /// Where a firmware pool allocation sits in the crafted machines below. const AT: u64 = 0x7f00_1234; -/// ACPI 6.5 Table 6.44's resource types. -const MEMORY: u8 = 0; -const IO: u8 = 1; -const BUS: u8 = 2; - -/// One QWORD Address Space Descriptor (ACPI 6.5 §6.4.3.5.1), well formed. +/// A well-formed descriptor: no granularity, its maximum its minimum plus its +/// length. fn qword(kind: u8, min: u64, length: u64, translation: u64) -> Vec { - let max = min + length - 1; - let mut d = vec![0x8A, 0x2B, 0x00, kind, 0x00, 0x00]; - d.extend_from_slice(&0u64.to_le_bytes()); - d.extend_from_slice(&min.to_le_bytes()); - d.extend_from_slice(&max.to_le_bytes()); - d.extend_from_slice(&translation.to_le_bytes()); - d.extend_from_slice(&length.to_le_bytes()); - d -} - -/// ACPI 6.5 §6.4.2.9, over its checksum byte. -fn end_tag() -> Vec { - vec![0x79, 0x00] -} - -fn list(descriptors: &[Vec]) -> Vec { - let mut bytes = Vec::new(); - for d in descriptors { - bytes.extend_from_slice(d); - } - bytes.extend_from_slice(&end_tag()); - bytes + qword_descriptor(kind, 0, min, min + length - 1, translation, length) } /// One walk of `bytes`, in a machine holding `bytes` at [`AT`] and nothing From 27b7753e3a3dacd8d691a61d7ceef286b36b7155 Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 07:58:11 +0200 Subject: [PATCH 2/6] The owner's rulings of 2026-10-04 go into the tracks they change Each is quoted as the option text he chose; what surrounds it is marked the orchestrator's or the design's. - The IOMMU track takes "Refuse external, record reflash", and for stage 2 "Display and USB only", "Accept and file" and "Allow it". The reflash weakness is filed as its own defect, owner the orchestrator, exit a ruled and built firmware verification held by a row. - The kernel heap's SLUB-hardening defect takes "Change the goal": its exit is the allocator's kernel front under the goal put to him, and the allocator track owns it. The allocator track takes "Yes, that bar" into its exit. - The tooling track takes "Design pass, then re-cut" on #629. - The latency and trace tracks take "Both in parallel". His text's "latency step 1 (interrupts on in system calls)" is the latency track's step 2; both files say so, as the orchestrator's mapping. - The ACPI track takes "Local only; decode the 186 bytes", which the previous commit carries out. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- ...-is-a-review-prompt-and-three-workflows.md | 6 ++++ ...-in-the-machine-can-read-the-trace-ring.md | 9 ++++++ ...lashes-its-device-escapes-its-isolation.md | 31 +++++++++++++++++++ .../kernel/the-iommu-refuses-nothing-yet.md | 29 +++++++++++++++++ ...kernel-heap-has-none-of-slubs-hardening.md | 22 ++++++++----- .../toyos-beats-linuxs-latency-on-the-t14.md | 10 ++++++ issues/kernel/toyos-has-its-own-allocator.md | 17 ++++++++-- ...ine-in-acpi-mode-and-interprets-its-aml.md | 4 +++ 8 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md diff --git a/issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md b/issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md index 3240514790e..e79d36b56f6 100644 --- a/issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md +++ b/issues/build/the-tooling-is-a-review-prompt-and-three-workflows.md @@ -37,3 +37,9 @@ and the gates that held them go. - The nine workflows become three — `pr`, `nightly`, `publish`; then `a5b25a75^:src/mergehealth.rs` goes, and the ABI-lands-alone rule moves into the review prompt. + +**Ruled** (owner, 2026-10-04), on #629, which builds the content-addressed +toolchain item, **"Design pass, then re-cut"**: "A short design pass against +today's main (it would also ease the one-shared-fork-branch ordering +problem), roasted, then rebuilt as a fresh PR; #629 is closed in favour of +it." diff --git a/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md b/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md index 0a346c25365..e88fc27e2ce 100644 --- a/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md +++ b/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md @@ -43,6 +43,15 @@ anything more is built on it. `issues/kernel/the-supervisors-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md` need. +**Ruled** (owner, 2026-10-04), on when these steps start, **"Both in +parallel"**: "Start the trace diary's first steps now, beside latency step 1 +(interrupts on in system calls). Step 1 is already measured by existing T14 +rows. The tail delays are only worked on once the diary shows their cause." +The step he names is step 2 of +`issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md`, +`issues/kernel/syscall-preemption-is-incidental.md`; that mapping is the +orchestrator's, not his. + Behind that judgement, and not before it: interrupt enter and exit records with a noise reader, the profiling sample, and the censuses moved onto the ring. diff --git a/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md b/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md new file mode 100644 index 00000000000..af7fd048861 --- /dev/null +++ b/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md @@ -0,0 +1,31 @@ +--- +status: open +kind: defect +opened: 2026-10-04 +--- + +# A driver that reflashes its device escapes its isolation + +A userland driver holds its device's registers, and through them many +devices take new firmware (NVMe's Firmware Image Download and Commit, for +one). Nothing in ToyOS refuses that or checks what a device runs. The IOMMU +confines a device by the requester ID its requests carry, so it confines a +reflashed one only as far as that ID is the device's own: ACS Source +Validation at a port refuses another bus's ID from below it, but nothing +stands between a root-complex-integrated endpoint, or one function of a +multi-function device, and an ID beside it. And the firmware outlives the +driver: the next holder, and the next boot's firmware before any IOMMU is +on, drive what the last holder wrote. That reach is the IOMMU design's +reading (its roasts, 2026-10-03 and 2026-10-04), not a measurement. + +**Ruled** (owner, 2026-10-04, "Refuse external, record reflash"): +"External-port devices can't be claimed by userland drivers for now; +reflashing is a recorded weakness with an exit (firmware verification) to +design later." + +Owner: the orchestrator, under `issues/kernel/the-iommu-refuses-nothing-yet.md`. + +**Exit**: a design for verifying a device's firmware is put to the owner +and ruled, and built; a device whose firmware fails that verification is +refused its claim by name, and a test or T14 row reads the refusal and its +negative control. diff --git a/issues/kernel/the-iommu-refuses-nothing-yet.md b/issues/kernel/the-iommu-refuses-nothing-yet.md index 5f7eed6a77c..7097c09f2f4 100644 --- a/issues/kernel/the-iommu-refuses-nothing-yet.md +++ b/issues/kernel/the-iommu-refuses-nothing-yet.md @@ -28,3 +28,32 @@ What the harness cannot measure: - **Cost.** The 2× bar is answerable only on hardware, in a same-session A/B; so are cache-snooping walks, real access-control enforcement, and mid-DMA function reset on a real device. + +**Ruled** (owner, 2026-10-04), on the threat model, **"Refuse external, +record reflash"**: "External-port devices can't be claimed by userland +drivers for now; reflashing is a recorded weakness with an exit (firmware +verification) to design later." The weakness is +`issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md`. +On the T14 the external ports are the Thunderbolt root ports `00:07.0` and +`00:07.2`, under units 1 and 2 (the orchestrator's reading of that machine's +`iommu:` lines). + +**Ruled** (owner, 2026-10-04), on stage 2, the default-deny root and the +hand-over of a unit firmware left translating: + +- **"Display and USB only"**: "Allowed only for display and USB controllers + whose reserved region belongs to them alone; that memory is mapped into the + driver's own isolated space. Everything else with reserved memory is + refused." Reserved memory is a DMAR RMRR; on the T14 the one RMRR, + `0x9c000000..0xa07fffff`, names the iGPU `00:02.0` alone. +- **"Accept and file"**: "Allow the one-moment gap on those machines, log it, + and file it as a known weakness with a fix (older protection registers) as + its exit." The gap, as put to him: a unit firmware left translating in + scalable or abort-DMA mode, with `CAP.ESRTPS` clear, may not have its root + table switched under translation (VT-d Rev. 4.1 §6.6), so translation goes + off for that one switch. The older protection registers are `PMEN`'s + protected memory regions (§11.4.8.1). The T14's units report `ESRTPS`, + `SMTS` and `ADMS` clear, so it is not one of those machines. +- **"Allow it"**, on the T14 row in which a test program claims the iGPU and + its reserved region is mapped into its domain: "One test boot with a blank + panel, only in that row; normal boots are unaffected." diff --git a/issues/kernel/the-kernel-heap-has-none-of-slubs-hardening.md b/issues/kernel/the-kernel-heap-has-none-of-slubs-hardening.md index 8a03007abb6..8cbc2c93b61 100644 --- a/issues/kernel/the-kernel-heap-has-none-of-slubs-hardening.md +++ b/issues/kernel/the-kernel-heap-has-none-of-slubs-hardening.md @@ -19,10 +19,18 @@ free list (`mm/slub.c:2228,2290`), and `CONFIG_RANDOM_KMALLOC_CACHES` spreads each size over 16 caches chosen by call site and a per-boot seed (`include/linux/slab.h:340-341,398-401`). -**Exit**: a free-list link is stored encoded with a per-boot secret and -checked on every unlink, a size class's allocation order is drawn per boot, -and one size is spread over 16 caches by call site and a per-boot seed. Host -tests on the allocator: a corrupted link panics at the next unlink, and -storing it plain passes it and reds; two seeds give two allocation orders, and -a fixed order reds; 1000 call sites of one size use all 16 caches, and one -cache reds. +**Ruled** (owner, 2026-10-04, "Change the goal"): "Close the issue with the +allocator's first stage under that stronger, ToyOS-shaped goal instead of +copying Linux's SLUB features one by one." The goal, as put to him: no +allocator bookkeeping stored inside objects, every free checked, and data +kept apart from pointers. The first stage is the kernel's front of +`issues/kernel/toyos-has-its-own-allocator.md`, which owns this issue. + +**Exit**: the kernel heap is that front, and its host tests hold the goal: +no free-list link or size is stored in memory an object occupies, so a write +past one object into a freed neighbour is followed by an allocation that +returns sound memory; a free of a pointer the heap did not hand out, and a +second free of one, each panic; and an allocation holding pointers never +shares a page with one holding only data. Each of those tests reds against +`dlmalloc`, or against the front with that property removed. The tests are +the orchestrator's reading of the goal, not his. diff --git a/issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md b/issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md index 09b21cc81db..da53316a20d 100644 --- a/issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md +++ b/issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md @@ -34,6 +34,16 @@ It samples: a window under 1 ms is seen only when a tick falls in it. **Ruled** (owner, 2026-10-03): **"131 µs"**. ToyOS must beat Linux's worst delay on the other seven CPUs, 131 µs, not cpu4's one-off 2.9 ms event. +**Ruled** (owner, 2026-10-04), on the order of the trace work, **"Both in +parallel"**: "Start the trace diary's first steps now, beside latency step 1 +(interrupts on in system calls). Step 1 is already measured by existing T14 +rows. The tail delays are only worked on once the diary shows their cause." +The step his text names is step 2 here, +`issues/kernel/syscall-preemption-is-incidental.md`, whose exit the +`mask_windows` row reads; the diary is +`issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md`. That +mapping is the orchestrator's, not his. + **Exit**: each step's exit is met, in the file the step names, and on the T14, with every CPU spawning a program that exits at once, as under Linux's 131 µs reading, the longest lateness of a 1 kHz timer's interrupt on each CPU reads under 131 µs, diff --git a/issues/kernel/toyos-has-its-own-allocator.md b/issues/kernel/toyos-has-its-own-allocator.md index ca62befbde8..1625a8ac13b 100644 --- a/issues/kernel/toyos-has-its-own-allocator.md +++ b/issues/kernel/toyos-has-its-own-allocator.md @@ -22,11 +22,24 @@ scans the page bitmap and zeroes the whole 2 MiB page before it returns, so every CPU that allocates from the heap meanwhile spins on its lock. How long that takes on the T14 is unmeasured. +**Ruled** (owner, 2026-10-04, "Yes, that bar"): "Within 10% of mimalloc +for time and peak memory on a pinned benchmark set; faster than dlmalloc +everywhere. The benchmarks get a portable Rust runner so they run on ToyOS +itself." + +The kernel's front closes +`issues/kernel/the-kernel-heap-has-none-of-slubs-hardening.md`, under the +goal the owner chose there (2026-10-04): no allocator bookkeeping inside +objects, every free checked, data apart from pointers. + Owner: the orchestrator. **Exit**: no heap growth allocates or zeroes a 2 MiB page inside the kernel heap's lock; the kernel allocates through ToyOS's allocator, and `dlmalloc`, `libc`, `windows-sys` and `windows-link` are gone from `kernel/Cargo.toml` and `kernel/Cargo.lock`, with `build::tests::the_kernel_resolves_no_libc_for_either_target` -(`src/build.rs`) deleted in the same pull request; and ToyOS's std allocates -through the std front, measured against `dlmalloc` before it is swapped in. +(`src/build.rs`) deleted in the same pull request; ToyOS's std allocates +through the std front, measured against `dlmalloc` before it is swapped in; +and the ruled bar holds, read by the benchmarks' portable Rust runner, which +runs on ToyOS: the allocator within 10% of mimalloc for time and peak memory +on the pinned benchmark set, and faster than `dlmalloc` everywhere. diff --git a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md index 0bd119348e7..b276ca71779 100644 --- a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md +++ b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md @@ -50,6 +50,10 @@ writes its own, and the battery comes first (his direction of `0ee814f5a`). - **"Extracts only"**: the repository holds small decoded extracts of the T14's ACPI tables; the whole tables stay out of the tree, read only by a check run outside it. +- **"Local only; decode the 186 bytes"** (2026-10-04): "Full tables stay out + of the repo (a copy you hold); the 186-byte fixture on main is replaced by + decoded values, as 'Extracts only' says." The T14's root-bridge list is + `t14_root_bridge` in `toyos-acpi/tests/common/mod.rs`. - **"full clean room write with the spec"**: the AML interpreter is written from the ACPI specification. From 77408f574a56095264118c1f9bb675bc69555f60 Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 08:41:11 +0200 Subject: [PATCH 3/6] Four more of the owner's rulings of 2026-10-04 go into their tracks - The ACPI track takes "Like Windows, not Linux" on `_OSI`, quoted as far as the option's text was relayed, with the orchestrator's note that the answers are fixed before the first table loads; and "Yes, one path" on power-off, which applies from the interpreter's power-off stage on. - The IOMMU track's stage 2 takes "Apply it at hand-over" on reserved memory, and his answer on the undriven-NVMe row: "You can do with the t14 what you want", so the row is allowed on its own boot. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- issues/kernel/the-iommu-refuses-nothing-yet.md | 9 +++++++++ ...-machine-in-acpi-mode-and-interprets-its-aml.md | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/issues/kernel/the-iommu-refuses-nothing-yet.md b/issues/kernel/the-iommu-refuses-nothing-yet.md index 7097c09f2f4..187920ee0b0 100644 --- a/issues/kernel/the-iommu-refuses-nothing-yet.md +++ b/issues/kernel/the-iommu-refuses-nothing-yet.md @@ -54,6 +54,15 @@ hand-over of a unit firmware left translating: off for that one switch. The older protection registers are `PMEN`'s protected memory regions (§11.4.8.1). The T14's units report `ESRTPS`, `SMTS` and `ADMS` clear, so it is not one of those machines. +- **"Apply it at hand-over"**, on reserved memory: "From the hand-over on, + only display and USB controllers keep access to their reserved region; any + other device's access is refused. A device that firmware was still using + then faults, which is logged and the device is stopped; the machine keeps + running." - **"Allow it"**, on the T14 row in which a test program claims the iGPU and its reserved region is mapped into its domain: "One test boot with a blank panel, only in that row; normal boots are unaffected." +- On the row that aims the T14's undriven NVMe `04:00.0` at memory nobody + gave it, asked whether to allow a single read-only Identify on its own + boot, he answered: "You can do with the t14 what you want." The row is + allowed, on its own boot. diff --git a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md index b276ca71779..57b78ac840f 100644 --- a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md +++ b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md @@ -57,6 +57,20 @@ writes its own, and the battery comes first (his direction of `0ee814f5a`). - **"full clean room write with the spec"**: the AML interpreter is written from the ACPI specification. +**Ruled** (owner, 2026-10-04), on the interpreter: + +- **"Like Windows, not Linux"**, on `_OSI`: "Yes to every published Windows + version string, no to 'Linux' and 'FreeBSD', as Linux itself answers. The + T14 then runs the path it was tested on..." (the option's text as relayed + to this record, cut there). The answers are fixed before the first table + loads, since an SSDT queries `_OSI` while it loads (the orchestrator's + note). +- **"Yes, one path"**, on power-off: "Power-off always goes through the ACPI + server; the kernel's power-off table reader is deleted. If the server is + broken, power-off fails loudly in every test." It applies from the + interpreter's power-off stage on (the orchestrator's placement); the + kernel's reader is `toyos-acpi/src/dsdt.rs`. + The orchestrator's reading of the clean-room ruling, not his: uACPI and ACPICA are run only as black-box oracles, and whoever writes the interpreter never reads their source. From 21ddf46c0e39def6f6baa8a90da529708dd95a24 Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 09:17:37 +0200 Subject: [PATCH 4/6] Answer review round 1: the rulings are quoted whole, and every track they bind has an owner and an exit - The "Like Windows, not Linux" option is quoted whole; the orchestrator's note that the answers are fixed before the first table loads goes (a track carries no rationale). - "Yes, one path" gets a named stage, the orchestrator's placement, whose exit is the kernel's \_S5_ reader (toyos-acpi/src/dsdt.rs and its caller in kernel/src/arch/x86_64/power.rs) deleted and a test red on a broken server. - The IOMMU track loses its "stage 2" label, which pointed at nothing, and gains an owner (the orchestrator) and an exit that reads each ruled refusal. - "Accept and file": the gap is filed now, as issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md, with PMEN's protected memory regions as its exit. - "You can do with the t14 what you want" stands as his words, and the record says the grant goes beyond the question asked. - The reflash defect drops its citation of roasts nothing in reach carries. - resource.rs's header loses the line about committed bytes, now false of the T14's list. - The OVMF root-bridge list is one OVMF_ROOT_BRIDGE in tests/common, read by corpus.rs and fixtures.rs. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- ...lashes-its-device-escapes-its-isolation.md | 2 +- ...s-translation-for-its-root-table-switch.md | 31 +++++++++++++++++++ .../kernel/the-iommu-refuses-nothing-yet.md | 25 ++++++++++++--- ...ine-in-acpi-mode-and-interprets-its-aml.md | 16 +++++----- toyos-acpi/src/resource.rs | 1 - toyos-acpi/tests/common/mod.rs | 4 +++ toyos-acpi/tests/corpus.rs | 5 ++- toyos-acpi/tests/fixtures.rs | 5 ++- 8 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md diff --git a/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md b/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md index af7fd048861..2da9225428d 100644 --- a/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md +++ b/issues/kernel/a-driver-that-reflashes-its-device-escapes-its-isolation.md @@ -16,7 +16,7 @@ stands between a root-complex-integrated endpoint, or one function of a multi-function device, and an ID beside it. And the firmware outlives the driver: the next holder, and the next boot's firmware before any IOMMU is on, drive what the last holder wrote. That reach is the IOMMU design's -reading (its roasts, 2026-10-03 and 2026-10-04), not a measurement. +reading, not a measurement. **Ruled** (owner, 2026-10-04, "Refuse external, record reflash"): "External-port devices can't be claimed by userland drivers for now; diff --git a/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md b/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md new file mode 100644 index 00000000000..1cb358218c5 --- /dev/null +++ b/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md @@ -0,0 +1,31 @@ +--- +status: open +kind: defect +opened: 2026-10-04 +--- + +# A unit in scalable or abort mode loses translation for its root-table switch + +A unit firmware leaves translating with a root table in scalable or abort-DMA +mode (`RTADDR_REG.TTM` not `00`) and `CAP.ESRTPS` clear may not have its root +table pointer set while translation is on (VT-d Rev. 4.1 §6.6). Handing such a +unit over to this kernel's root table therefore turns translation off for that +one switch, and for that moment every function behind the unit reaches all of +memory. `issues/kernel/a-unit-left-translating-passes-dma-untranslated-while-programmed.md` +removes the gap where the switch may stay translating; on these units it may +not. + +Evidence: the specification alone. No machine here has such a unit: every unit of the +T14 reports `CAP` bit 63 (`ESRTPS`), `ECAP` bit 43 (`SMTS`) and bit 52 +(`ADMS`) clear. + +**Ruled** (owner, 2026-10-04, "Accept and file"): "Allow the one-moment gap on +those machines, log it, and file it as a known weakness with a fix (older +protection registers) as its exit." + +Owner: the orchestrator, under `issues/kernel/the-iommu-refuses-nothing-yet.md`. + +**Exit**: on such a unit, `PMEN`'s protected memory regions (§11.4.8.1) cover +all of memory before translation goes off for the switch and are released +only once it is back on; a test reads that order, and is red with the `PMEN` +step removed. diff --git a/issues/kernel/the-iommu-refuses-nothing-yet.md b/issues/kernel/the-iommu-refuses-nothing-yet.md index 187920ee0b0..8e91edc8d61 100644 --- a/issues/kernel/the-iommu-refuses-nothing-yet.md +++ b/issues/kernel/the-iommu-refuses-nothing-yet.md @@ -38,8 +38,8 @@ On the T14 the external ports are the Thunderbolt root ports `00:07.0` and `00:07.2`, under units 1 and 2 (the orchestrator's reading of that machine's `iommu:` lines). -**Ruled** (owner, 2026-10-04), on stage 2, the default-deny root and the -hand-over of a unit firmware left translating: +**Ruled** (owner, 2026-10-04), on the default-deny root and the hand-over of +a unit firmware left translating: - **"Display and USB only"**: "Allowed only for display and USB controllers whose reserved region belongs to them alone; that memory is mapped into the @@ -53,7 +53,8 @@ hand-over of a unit firmware left translating: table switched under translation (VT-d Rev. 4.1 §6.6), so translation goes off for that one switch. The older protection registers are `PMEN`'s protected memory regions (§11.4.8.1). The T14's units report `ESRTPS`, - `SMTS` and `ADMS` clear, so it is not one of those machines. + `SMTS` and `ADMS` clear, so it is not one of those machines. The weakness is + `issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md`. - **"Apply it at hand-over"**, on reserved memory: "From the hand-over on, only display and USB controllers keep access to their reserved region; any other device's access is refused. A device that firmware was still using @@ -64,5 +65,19 @@ hand-over of a unit firmware left translating: panel, only in that row; normal boots are unaffected." - On the row that aims the T14's undriven NVMe `04:00.0` at memory nobody gave it, asked whether to allow a single read-only Identify on its own - boot, he answered: "You can do with the t14 what you want." The row is - allowed, on its own boot. + boot, he answered: "You can do with the t14 what you want." The grant goes + beyond the question asked. + +Owner: the orchestrator. + +**Exit**: a test or a T14 row reads each ruled refusal, each with its +negative control: + +- a userland claim of a function below an external port (on the T14, + `00:07.0` or `00:07.2`) is refused by name; +- a claim of a function an RMRR names is refused unless it is a display or USB + controller that RMRR names alone, whose region is then mapped into its + driver's domain (the T14's iGPU row); +- from the hand-over on, a device reaching reserved memory not its own faults, + is logged and stopped, and the machine keeps running; +- a unit with the hand-over gap logs it. diff --git a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md index 57b78ac840f..b27df18c259 100644 --- a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md +++ b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md @@ -61,15 +61,11 @@ writes its own, and the battery comes first (his direction of `0ee814f5a`). - **"Like Windows, not Linux"**, on `_OSI`: "Yes to every published Windows version string, no to 'Linux' and 'FreeBSD', as Linux itself answers. The - T14 then runs the path it was tested on..." (the option's text as relayed - to this record, cut there). The answers are fixed before the first table - loads, since an SSDT queries `_OSI` while it loads (the orchestrator's - note). + T14 then runs the path it was tested on: Modern Standby, CPU performance + tables, 101-step backlight, thermal profiles, all devices present." - **"Yes, one path"**, on power-off: "Power-off always goes through the ACPI server; the kernel's power-off table reader is deleted. If the server is - broken, power-off fails loudly in every test." It applies from the - interpreter's power-off stage on (the orchestrator's placement); the - kernel's reader is `toyos-acpi/src/dsdt.rs`. + broken, power-off fails loudly in every test." The orchestrator's reading of the clean-room ruling, not his: uACPI and ACPICA are run only as black-box oracles, and whoever writes the interpreter @@ -85,3 +81,9 @@ power-off path (`SYS_SHUTDOWN`), and the boot's log records the press and that stop, and each EC query number once with its count: a T14 row reads them there. A second T14 row kills the server and reads `SCI_EN` clear in `PM1_CNT` afterwards, the kernel having written `ACPI_DISABLE` to `SMI_CMD`. + +**Stage: power-off through the server** (the orchestrator's placement of "Yes, +one path"). The ACPI server evaluates `\_S5` and powers the machine off. +**Exit**: the kernel's `\_S5_` reader, `toyos-acpi/src/dsdt.rs`, and its caller +in `kernel/src/arch/x86_64/power.rs` are deleted, and a test that powers off +through a broken server is red. diff --git a/toyos-acpi/src/resource.rs b/toyos-acpi/src/resource.rs index 80304260c28..26273cce3bc 100644 --- a/toyos-acpi/src/resource.rs +++ b/toyos-acpi/src/resource.rs @@ -10,7 +10,6 @@ //! //! Input is firmware-supplied and untrusted: no path panics, the walk //! terminates on every input, and every refusal is a [`ResourceError`]. -//! `tests/corpus.rs` holds that claim over both firmwares' committed bytes. use crate::Phys; use toyos_abi::boot::RootBridgeWindow; diff --git a/toyos-acpi/tests/common/mod.rs b/toyos-acpi/tests/common/mod.rs index 5c4ec15334f..7df0a8162df 100644 --- a/toyos-acpi/tests/common/mod.rs +++ b/toyos-acpi/tests/common/mod.rs @@ -139,6 +139,10 @@ pub fn resource_list(descriptors: &[Vec]) -> Vec { bytes } +/// What OVMF's firmware answered for its root bridge 0 through +/// `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration`, as captured. +pub const OVMF_ROOT_BRIDGE: &[u8] = include_bytes!("../../fixtures/ovmf-pure-efi/root-bridge-0.bin"); + /// What the ThinkPad T14's firmware answers for its root bridge 0 through /// `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration`, decoded: its I/O range, /// two memory windows and its bus range. diff --git a/toyos-acpi/tests/corpus.rs b/toyos-acpi/tests/corpus.rs index 148536cbd7c..6378bee937f 100644 --- a/toyos-acpi/tests/corpus.rs +++ b/toyos-acpi/tests/corpus.rs @@ -8,7 +8,7 @@ mod common; -use common::{declare_len, entry, madt, rsdp, sdt, t14_root_bridge, xsdt, Machine}; +use common::{declare_len, entry, madt, rsdp, sdt, t14_root_bridge, xsdt, Machine, OVMF_ROOT_BRIDGE}; use toyos_abi::boot::RootBridgeWindow; use toyos_acpi::{ dsdt_address, ecam_base, find_table, hpet_base, iapc_boot_arch, madt_entries, memory_windows, @@ -566,7 +566,6 @@ fn a_fadt_that_ends_before_arm_boot_arch_is_short() { /// Where the two firmwares' descriptor lists sit for the sweep below. const ROOT_BRIDGE_AT: u64 = 0x4_0000; -const OVMF_BRIDGE: &[u8] = include_bytes!("../fixtures/ovmf-pure-efi/root-bridge-0.bin"); /// **No panic and no unbounded walk, over every byte of both firmwares' real /// descriptor lists.** Each byte takes each of its 255 other values in turn and @@ -576,7 +575,7 @@ const OVMF_BRIDGE: &[u8] = include_bytes!("../fixtures/ovmf-pure-efi/root-bridge fn no_single_byte_mutation_of_a_firmwares_descriptor_list_panics_or_runs_away() { let mut mutations = 0u64; let mut refused = 0u64; - for (which, original) in [("ovmf", OVMF_BRIDGE.to_vec()), ("thinkpad-t14", t14_root_bridge())] { + for (which, original) in [("ovmf", OVMF_ROOT_BRIDGE.to_vec()), ("thinkpad-t14", t14_root_bridge())] { for offset in 0..original.len() { for value in 0..=255u8 { if original[offset] == value { diff --git a/toyos-acpi/tests/fixtures.rs b/toyos-acpi/tests/fixtures.rs index be40862d9ca..8b829878a09 100644 --- a/toyos-acpi/tests/fixtures.rs +++ b/toyos-acpi/tests/fixtures.rs @@ -3,7 +3,7 @@ mod common; -use common::{t14_root_bridge, Machine}; +use common::{t14_root_bridge, Machine, OVMF_ROOT_BRIDGE}; use toyos_abi::boot::RootBridgeWindow; use toyos_acpi::{ century_of, dsdt_address, ecam_base, find_table, hpet_base, iapc_boot_arch, madt_entries, @@ -163,7 +163,6 @@ fn the_xsdt_walk_reaches_every_entry() { } const ROOT_BRIDGE: u64 = 0x7f00_0000; -const OVMF_BRIDGE: &[u8] = include_bytes!("../fixtures/ovmf-pure-efi/root-bridge-0.bin"); fn bridge_windows(bytes: &[u8]) -> Vec { let regions: &[(u64, &[u8])] = &[(ROOT_BRIDGE, bytes)]; @@ -177,7 +176,7 @@ fn bridge_windows(bytes: &[u8]) -> Vec { #[test] fn the_windows_a_boot_printed_are_what_that_firmwares_own_bytes_say() { assert_eq!( - bridge_windows(OVMF_BRIDGE), + bridge_windows(OVMF_ROOT_BRIDGE), [ RootBridgeWindow { base: 0xc000_0000, length: 0x0010_0000 }, RootBridgeWindow { base: 0x8_0000_0000, length: 0x0010_0000 }, From bad9f2f2dfdcee42b028470601461ef5df54344f Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 09:48:02 +0200 Subject: [PATCH 5/6] Answer review round 2: the IOMMU exit reads both halves of the hand-over ruling and the scope refusal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The hand-over bullet reads both halves of "Apply it at hand-over": a device that is neither display nor USB faults on its own RMRR region, is logged and stopped, and the machine keeps running; a display or USB controller its RMRR names alone keeps that region. Each half has its own negative control. The old bullet read only access to another device's region, which default-deny already faults. - The exit also reads the track's own headline refusal, the isolation-scope rule, which the kernel does not build yet. - The PMEN exit is bounded to units reporting CAP.PLMR and CAP.PHMR (VT-d Rev. 4.1 §11.4.8.1 treats PMEN_REG as read-only otherwise and plans it for deprecation); a unit without them is recorded as having no fix under this exit. The test is a host test: QEMU 11's unit always reports ESRTPS and defines PMEN_REG read-only zero, and the T14's units support neither mode. - The power-off stage names its blocker: the interpreter's evaluation of \_S5. - The track's sentence on the T14's ESRTPS/SMTS/ADMS bits is removed; the defect file carries it. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- ...ses-translation-for-its-root-table-switch.md | 17 +++++++++++++---- issues/kernel/the-iommu-refuses-nothing-yet.md | 12 ++++++++---- ...chine-in-acpi-mode-and-interprets-its-aml.md | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md b/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md index 1cb358218c5..2b85c5e0a2f 100644 --- a/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md +++ b/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md @@ -25,7 +25,16 @@ protection registers) as its exit." Owner: the orchestrator, under `issues/kernel/the-iommu-refuses-nothing-yet.md`. -**Exit**: on such a unit, `PMEN`'s protected memory regions (§11.4.8.1) cover -all of memory before translation goes off for the switch and are released -only once it is back on; a test reads that order, and is red with the `PMEN` -step removed. +**Exit**: on such a unit that reports `CAP.PLMR` (bit 5) and `CAP.PHMR` +(bit 6), `PMEN`'s protected memory regions (§11.4.8.1) cover all of memory +before translation goes off for the switch and are released only once it is +back on; a host test reads that order, and is red with the `PMEN` step +removed. It is a host test because no machine reaches the path: QEMU's unit +always reports `ESRTPS` and implements `PMEN_REG` as read-only zero, and the +T14's units report `ESRTPS` clear but support neither mode. + +A unit that reports either bit clear has no fix under this exit: §11.4.8.1 +treats `PMEN_REG` as read-only there, and the same section plans the +protected memory registers for deprecation, pointing new software at +abort-DMA mode. Such a unit keeps the gap, logged, until a fix that does not +rest on `PMEN` is found. diff --git a/issues/kernel/the-iommu-refuses-nothing-yet.md b/issues/kernel/the-iommu-refuses-nothing-yet.md index 8e91edc8d61..8de27f35c1f 100644 --- a/issues/kernel/the-iommu-refuses-nothing-yet.md +++ b/issues/kernel/the-iommu-refuses-nothing-yet.md @@ -52,8 +52,7 @@ a unit firmware left translating: scalable or abort-DMA mode, with `CAP.ESRTPS` clear, may not have its root table switched under translation (VT-d Rev. 4.1 §6.6), so translation goes off for that one switch. The older protection registers are `PMEN`'s - protected memory regions (§11.4.8.1). The T14's units report `ESRTPS`, - `SMTS` and `ADMS` clear, so it is not one of those machines. The weakness is + protected memory regions (§11.4.8.1). The weakness is `issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md`. - **"Apply it at hand-over"**, on reserved memory: "From the hand-over on, only display and USB controllers keep access to their reserved region; any @@ -73,11 +72,16 @@ Owner: the orchestrator. **Exit**: a test or a T14 row reads each ruled refusal, each with its negative control: +- the isolation-scope rule: a non-singleton scope is refused by name for a + function behind a PCIe switch, and admitted for a root-complex-integrated + function; - a userland claim of a function below an external port (on the T14, `00:07.0` or `00:07.2`) is refused by name; - a claim of a function an RMRR names is refused unless it is a display or USB controller that RMRR names alone, whose region is then mapped into its driver's domain (the T14's iGPU row); -- from the hand-over on, a device reaching reserved memory not its own faults, - is logged and stopped, and the machine keeps running; +- from the hand-over on, a device that is neither a display nor a USB + controller faults on its own RMRR region, is logged and stopped, and the + machine keeps running; and a display or USB controller its RMRR names alone + keeps that region. Each half has its own negative control; - a unit with the hand-over gap logs it. diff --git a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md index b27df18c259..a7acea8bbff 100644 --- a/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md +++ b/issues/kernel/toyos-runs-the-machine-in-acpi-mode-and-interprets-its-aml.md @@ -84,6 +84,6 @@ afterwards, the kernel having written `ACPI_DISABLE` to `SMI_CMD`. **Stage: power-off through the server** (the orchestrator's placement of "Yes, one path"). The ACPI server evaluates `\_S5` and powers the machine off. -**Exit**: the kernel's `\_S5_` reader, `toyos-acpi/src/dsdt.rs`, and its caller +Blocked on the interpreter's evaluation of `\_S5`. **Exit**: the kernel's `\_S5_` reader, `toyos-acpi/src/dsdt.rs`, and its caller in `kernel/src/arch/x86_64/power.rs` are deleted, and a test that powers off through a broken server is red. From 1d2eee6c39c2af1123ad71bfe65976d2e1582e58 Mon Sep 17 00:00:00 2001 From: japabu Date: Sun, 4 Oct 2026 09:59:50 +0200 Subject: [PATCH 6/6] Answer review round 3: the PMEN reason, the residual's exit and the shared-RMRR display case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The scalable-mode defect gives §11.4.8.1's actual reason: with PLMR or PHMR clear that region's base and limit are read-only, so PMEN cannot cover all of memory (PMEN_REG is read-only only with both clear). - The defect stays open for units with either bit clear once the PMEN exit is met, and carries an exit of its own for them. - The IOMMU track's hand-over exit also reads a display or USB controller whose RMRR names another device: it faults on that region. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8 --- ...loses-translation-for-its-root-table-switch.md | 15 ++++++++++----- issues/kernel/the-iommu-refuses-nothing-yet.md | 6 ++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md b/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md index 2b85c5e0a2f..c1cf20d37d3 100644 --- a/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md +++ b/issues/kernel/a-unit-in-scalable-or-abort-mode-loses-translation-for-its-root-table-switch.md @@ -33,8 +33,13 @@ removed. It is a host test because no machine reaches the path: QEMU's unit always reports `ESRTPS` and implements `PMEN_REG` as read-only zero, and the T14's units report `ESRTPS` clear but support neither mode. -A unit that reports either bit clear has no fix under this exit: §11.4.8.1 -treats `PMEN_REG` as read-only there, and the same section plans the -protected memory registers for deprecation, pointing new software at -abort-DMA mode. Such a unit keeps the gap, logged, until a fix that does not -rest on `PMEN` is found. +A unit that reports either bit clear has no fix under this exit: with either +clear, that region's base and limit are read-only (§11.4.8.1), so `PMEN` +cannot cover all of memory; the same section plans the protected memory +registers for deprecation, pointing new software at abort-DMA mode. Such a +unit keeps the gap, logged, and this file stays open for it once the `PMEN` +exit is met. + +**Exit for a unit with `PLMR` or `PHMR` clear**: on such a unit no function +behind it reaches memory while translation is off for the switch; a host test +reads that, and is red with the fix removed. diff --git a/issues/kernel/the-iommu-refuses-nothing-yet.md b/issues/kernel/the-iommu-refuses-nothing-yet.md index 8de27f35c1f..9b55f359003 100644 --- a/issues/kernel/the-iommu-refuses-nothing-yet.md +++ b/issues/kernel/the-iommu-refuses-nothing-yet.md @@ -82,6 +82,8 @@ negative control: driver's domain (the T14's iGPU row); - from the hand-over on, a device that is neither a display nor a USB controller faults on its own RMRR region, is logged and stopped, and the - machine keeps running; and a display or USB controller its RMRR names alone - keeps that region. Each half has its own negative control; + machine keeps running; a display or USB controller whose RMRR also names + another device faults on that region the same way; and a display or USB + controller its RMRR names alone keeps that region. Each case has its own + negative control; - a unit with the hand-over gap logs it.