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
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ shared boot waiting for its next command is parked at almost every sample.
`SYS_THREAD_JOIN` whose wake was lost: it parks on the target thread's own watch
at `Deadline::never()` (`kernel/src/syscall/proc.rs:171`), and nothing else
would leave a whole boot idle straight after a sibling thread's clean exit.
`issues/thread-exits-completion-post-is-the-second-one.md` owns that
path's two posts.
That wake is the one post `process::thread_exit` makes on the thread's own
watch before its exit pass.

**Exit condition.** A capture taken from a boot that has actually stopped, which
names the first waiter and the subject it waits on — that boot's trace diary
Expand Down
37 changes: 37 additions & 0 deletions issues/std-net-maps-every-other-syscall-error-to-other.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
status: open
kind: defect
opened: 2026-09-01
---

# std's net backend still maps every other `SyscallError` to `ErrorKind::Other`

Making a broken pipe reach a Rust caller as `BrokenPipe` put one exhaustive
`SyscallError -> ErrorKind` map in `sdk/std/sys/pal/mod.rs` and pointed
`sys/pipe`, `sys/stdio` and `sys/fs` at it. `sdk/std/sys/net/connection.rs`
keeps a map of its own with a `_ => Other` arm:

```rust
fn syscall_err(e: SyscallError) -> io::Error {
match e {
SyscallError::WouldBlock => io::ErrorKind::WouldBlock.into(),
_ => io::Error::new(io::ErrorKind::Other, "syscall error"),
}
}
```

A TCP stream no longer goes through it: `TcpStream` reads and writes through
`toyos::net::stream`, whose refusals `stream_refused` maps by name. What still
does is `UdpSocket`'s `recv_from` and `send_to`, which read and write the
socket's pipes to netstack, and the listener's notification reads. So a `UdpSocket::send_to` after netstack has gone
answers `ErrorKind::Other` where the pipe path answers `BrokenPipe`, by reading
the code, and a new `SyscallError` variant is absorbed there silently rather
than failing to compile until somebody decides its kind.

## What closing it takes

Pointing `syscall_err`'s callers at `sys::to_io_error` and deleting the local
map, as the three modules already moved were; and a test that a datagram
socket's write to a departed netstack answers `BrokenPipe`, against libc's
`sendto` on the same shape. `netstack_gone_mid_bind` is the boot that already
stages a departed netstack.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Guest binaries in `tests/guest/rust-tests/src/bin/` that make several claims:
- `std_process.rs`: eight std process behaviours.
- `std_sync.rs`: mutex, condvar, park and rwlock.
- `sched_stress.rs`: io_uring acceptor isolation, the post-wake vruntime lag, and a connect storm.
- `toybox_file_tools.rs`: `cp`, `mv` and `hexdump`.
- `std_fs.rs`: listing, a self-read, NotFound, and file types.

Owner: the orchestrator, which dispatches the reshape.
Expand Down
2 changes: 1 addition & 1 deletion issues/t14-desktop-froze-at-64s.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ ruled it out.

**What the next boot should capture.** Nothing new, which is the point: the
compositor now names every client it drops and why. A recurrence with no
`compositor: dropping pid` line and no telemetry is a mechanism none of the
`compositor: dropping client` line and no telemetry is a mechanism none of the
four closed ones covers, and that is itself the finding.

**Nothing replaces the 2 s report as a heartbeat.** It left the log (#891),
Expand Down
82 changes: 0 additions & 82 deletions issues/t14-keyboard-will-not-report-its-scancode-set.md

This file was deleted.

52 changes: 25 additions & 27 deletions issues/t14-lost-every-integrated-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,22 @@ packets — `0x08` is a resting head and `0x06` is a `dx` of +6. **The pointer w
framing perfectly.** The arithmetic is forced and no reader would do it.

Closed, therefore: the decoder did not desync, and no fix for a desync was
needed. What was wrong is the instrument, and it is now fixed (`647c3c0`,
`toyos-ps2`) — `MouseOutcome` could not distinguish a byte held inside a packet
from a byte thrown away at a boundary, so two of every three bytes of a healthy
pointer stream were reported as suspects. `i8042_mouse` now runs three thousand bytes of
clean packets and requires the driver to name none of them; reverting the split
reds it with the T14's own line shape.
needed. What was wrong is the instrument, and it is fixed (`647c3c0`) —
`MouseOutcome` could not distinguish a byte held inside a packet from a byte
thrown away at a boundary, so two of every three bytes of a healthy pointer
stream were reported as suspects. `toyos-ps2`'s
`a_healthy_stream_discards_nothing_and_leaves_no_byte_unaccounted`
(`system/ps2server/ps2/tests/decode.rs`) holds that with the T14's two packets.

The kernel driver that logged this session is gone: `/system/bin/ps2server`
drives the i8042 from userland (#899) and resets both devices itself
(`system/ps2server/src/probe.rs`). Nothing since has read a T14 session long
enough to see whether the loss recurs under it.

**What remains open is the actual question, and the log cannot answer it.**
The tally counts in the ISR before any decoding, so 6 interrupts is hardware truth
— but it is truth *as of 6.609 s*, which is when the driver stopped speaking.
`HEALTH_DONE` was terminal. For the remaining 54 s the log cannot separate:
— but it is truth *as of 6.609 s*, which is when the driver stopped speaking:
that driver's health line was said once. For the remaining 54 s the log cannot separate:

- **the pin stopped asserting** — a wedged controller, a lost edge, an EC that
stopped scanning, an RTE that got masked; from
Expand All @@ -48,16 +53,17 @@ keyboard produced no byte at all in 58 s** — not "stopped at 6.6 s", never. Th
same machine's earlier boots drove a shell off that keyboard
(`c7efcd30d^:specs/reference/metal-hardware-inventory.md`), so it is not a routing fault.

The cadence fix is what makes the next session decisive rather than a guess:
after the verdict the counters repeat, at most once per 10 s and **only when the
pin has asserted since the last line**. That gating is the point — past the
first repeat, no line means no interrupt, so silence becomes evidence instead of
absence of evidence.
ps2server's counters line is what makes the next session decisive rather
than a guess: it repeats at most once per 10 s and **only when an interrupt has
come since the last line** (`Stream::counters`, `system/ps2server/src/stream.rs`).
Past the first line, no line means no interrupt, so silence becomes evidence
instead of absence of evidence.

**What the next boot should capture.** A repeat line dated after 6.6 s, or none.
If bytes are arriving, `undecoded`/`discarded` name the fault in this driver. If
no line appears at all, the pin is not asserting and the next suspect is the
controller or the EC — and nothing in `toyos-ps2` can be responsible.
**What the next session should capture.** A `ps2server:` counters line dated
after the inputs go dead, or none. If bytes are arriving, `undecoded` and
`discarded` name the fault in the decoder. If no line appears at all, the pin is
not asserting and the next suspect is the controller or the EC — and nothing in
`toyos-ps2` can be responsible.

Two things deliberately not concluded:

Expand All @@ -67,15 +73,7 @@ Two things deliberately not concluded:
`0xF2` with id `0x00` — a plain 3-byte mouse — so the driver's 3-byte frame is
what the wire carries, and the 4-byte IntelliMouse mismatch usually blamed for
a PS/2 desync is not available here.
- **The USB mouse plugged in at 30.4 s produced no motion either**, which is the
xHCI HID completion-requeue item in this section and not this one.

The endowment table stays indistinguishable here even after the presence gate
landed (#342): on this machine the i8042 is present and both claims still mint
whether the devices answer or not — the gate keys `declare_source()` on
`aux_line.is_some()` / the GSI existing, while `unmasked`/`aux_unmasked`, both
computed one line above (i8042/mod.rs:1320,1323), go unread. Gating the two
declarations on those is the one-line fix direction the #342 review named; it
needs this machine to prove.
- **The USB mouse plugged in at 30.4 s produced no motion either**, which is
`issues/the-t14-mouse-may-be-another-defect.md` and not this one.

`i8042_mouse` is deleted; `issues/i8042-mouse-ends-four-packets-short-with-a-clean-exit.md` records the commit that restores it.
9 changes: 5 additions & 4 deletions issues/t14-rows-hold-toyos-to-linuxs-choice-or-copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ setting must be, and its copy of a fact a primary source states is never an orac
rows in `tests/toyos.rs` used one. `counters_on_metal`'s, the request Linux's governor chose,
went in #915; the other remains:

- `acpi_tables_on_metal` holds the number of definition blocks the server loaded to
`T14_DEFINITION_BLOCKS`, the 14 Linux reports loading. The firmware's XSDT and FADT, which the
kernel already reads, are the primary source of that count.
- `acpi_tables_on_metal` holds the number of definition blocks the server loaded to a
constant per bench, `Bench::blocks` in `tests/toyos.rs`: the T14's 14, the count Linux
reported loading, and the AMD bench's 17. The firmware's XSDT and FADT, which the kernel
already reads, are the primary source of that count.

Owner: the orchestrator, which dispatches the reshape.

**Exit condition**: `acpi_tables_on_metal` holds the count to the definition blocks
the same boot's firmware tables list, and `T14_DEFINITION_BLOCKS` is deleted.
the same boot's firmware tables list, and `Bench::blocks` is deleted.
27 changes: 14 additions & 13 deletions issues/test-runner-holds-logread-where-no-log-builtin-runs.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ opened: 2026-09-28

# test-runner holds `logread` where no log builtin runs

`logread` in a `[programs.test-runner]` row is authority for the builtins that
read the log inside test-runner (`log-gate`, `log-storm`, `log-close`,
`tests/guest/test-runner/src/main.rs`'s `BUILTINS`). Every boot that runs one is a
`tests/images/testcases.toml` boot (`tests/common/logread.rs` boots the machine tests' config;
`tests/toyos.rs`'s one job list naming `log-close` is `tests/images/testcases.toml`). Seven
other manifests grant it anyway: `tests/partclaimcase`, `tests/blockdcase`,
`tests/doommusiccase`, `tests/logrotatecase`, `tests/images/metalcase.toml`, `tests/images/netcase.toml`
and `tests/sshdcase`.
test-runner has no builtin that reads the log any more: `log-gate`,
`log-storm` and `log-close` are gone from `tests/guest/test-runner`. Its
`logread` is used only by the children it hands a `SysCap` duplicate to, and
it hands one only where its row also grants `dup` (`run_one`,
`tests/guest/test-runner/src/main.rs`).

`partclaimcase` and `blockdcase` also grant `dup`, so there every child
test-runner spawns receives a `SysCap` duplicate carrying `LOG` as well.
- `tests/images/testcases.toml`'s row grants `dup` beside `logread`, and its
children `disk_backtrace` and `inbox_log_post` read the log through the
duplicate. Its comment still gives "the log gate" as the reason.
- `tests/images/metalcase.toml`'s row grants `logread` and no `dup`, so no
child receives it and test-runner reads no log itself: nothing on that boot
uses it.

**Evidence:** `rg -n '"log-gate"|"log-storm"|"log-close"' tests userland`, and
`rg -n logread -g system.toml tests`.
**Evidence:** `rg -n logread tests/images` and `rg -n 'log_read|cursor_words'
tests/guest`.

**Exit:** every `logread` in a test manifest is one a program on that boot
uses, or the row says which use it is for.
uses, and the row's comment says which use it is for.
31 changes: 0 additions & 31 deletions issues/the-ack-delay-abi-doc-names-one-cpu.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ opened: 2026-10-04

# The ACPI server's holder drives the embedded controller unfiltered

The `acpi` claim (`kernel/src/arch/x86_64/acpi_mode.rs`) opens the embedded
controller's command and data ports to `/system/bin/acpiserver` through the
TSS I/O permission bitmap, which grants a port or refuses it and cannot see
the value written. Stage 1 sends the controller nothing but queries, but the
same two ports take `WR_EC` (ACPI 6.5 §12.3), which writes any byte of the
controller's space: on a laptop that is where fan control, charge thresholds
and the controller's own thermal limits live. So a bug in that one program can
reach whatever the machine's controller lets its host write, which the kernel
never sees.
The holder of the `acpi` claim, `/system/bin/acpiserver`, reaches the
embedded controller's command and data ports through the kernel's mediated
access, one byte each (`access`, `kernel/src/arch/x86_64/acpi_mode.rs`;
`system/acpiserver/src/host.rs`). No row names those ports, and the fence
(`toyos_userbound::firmware`) refuses a port only for whose it is, never for
the value written. The server sends queries and, for the AML's accesses to
the controller's space, `RD_EC` and `WR_EC` (`system/acpiserver/src/ec.rs`).
`WR_EC` (ACPI 6.5 §12.3) writes any byte of the controller's space: on a
laptop that is where fan control, charge thresholds and the controller's own
thermal limits live. So a bug in that one program, or in the AML it runs, can
reach whatever the machine's controller lets its host write, and the kernel
makes the write without judging it.

The command port also takes any byte, and §12.3 defines five commands
(0x80–0x84); every other is the controller's maker's. Whether one of them puts
Expand Down
Loading