fix(console): the serial line is found, not assumed -- from the devicetree on a board, COM1 by probe on a PC
Each board has one serial line that is its console, the lowest common denominator beside the screen and keyboard. Its address was QEMU's, fixed: on a Raspberry Pi 5 the aarch64 one is ordinary RAM, written to with every character printed; on a Milk-V Mars the riscv64 one is the board's UART with registers four bytes apart, and the UEFI loader would have waited for ever on its first character; on a PC with no COM1 the prompt read 0xFF for ever. console_attach_serial(), called before anything prints: COM1 if a UART answers there; elsewhere the UART that /chosen/stdout-path names (fdt_uart.c: alias, path, the address carried up through each bus's ranges, reg-shift and reg-io-width); with no devicetree, QEMU's. A devicetree that names no usable console gives no line, not a guess. A line that does not come ready is given up, not waited on. The riscv64 loader's early serial does the same. tools/fdt_uart_test.c, run by hand, 19 checks plain and under the sanitizers: devicetrees shaped like the Mars's, the Pi 5's and QEMU's, what must find nothing, and a block cut short at every length; and the Pi 5's real devicetree gives a PL011 at 0x107d001000. Acceptance, one QEMU at a time: v3 on amd64 (logs/20261013-204436), aarch64 (-204803) and riscv64 (-205001) to the zuse prompt, no unknown word, hash 0x08873e0f44b7cb2a on all three as before. -204600 is an aarch64 run during which the disk images were restored under it by a script that had been refused a second QEMU; it passed and is kept, and was run again. v4 on the three ISAs (-211149, -211444, -211857): POST 538 of 538, dict_hash 0xe5a57f3eb72ff94a, the typed session unchanged. The Mars image through OpenSBI and U-Boot in QEMU took its line and its interrupt controller from the devicetree and passed POST. Found on the way and not mended (boards/BRINGUP.md 1.6): built with EMERGENCY_CONSOLE_ENABLED=1 the prompt floods with empty lines. -210442 shows it; the commit before this does the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f4e359859a
commit
c95191736e
+22
-10
@@ -40,15 +40,15 @@ None has been fixed: each needs your word.
|
||||
| S4 | `BYE` resets through the i8042, not the ACPI reset register. | finding 4 | `BYE` may do nothing. It does not hang. |
|
||||
| S5 | Whether the SER5 has a serial header is not known. | `FABRIC-3.md` III | Without one, and with A3, the SER5 can be watched over HDMI and not typed to. |
|
||||
|
||||
The loader probes COM1 before using it. The kernel's own console writes to port `0x3F8`
|
||||
without a probe; on a board with no COM1 the status port reads all ones and the write goes
|
||||
nowhere.
|
||||
The loader probes COM1 before using it, and since 2026-10-13 so does the kernel's console.
|
||||
Before that, on a board with no COM1 the status port read all ones: writes went nowhere, and
|
||||
the prompt was told a key was waiting on every poll and read `0xFF` for ever.
|
||||
|
||||
### 1.3 Raspberry Pi 5
|
||||
|
||||
| # | What | Where | Effect |
|
||||
|---|---|---|---|
|
||||
| R1 | **Blocks first boot.** Every character the console prints is also written to a PL011 UART at `0x09000000`, QEMU's address, after waiting on a flag read from `0x09000018`. On a Pi 5 that is ordinary RAM. | `kernel/src/hal/console.c:84-93`, `:223` | Each character overwrites a word of RAM at 144 MiB; and if the word at `0x09000018` has bit 5 set, the first character waits for ever. `rpi5_uart_base()` finds the real UART and nothing calls it. |
|
||||
| R1 | **Fixed 2026-10-13.** Every character the console printed was also written to a PL011 at `0x09000000`, QEMU's address, which on a Pi 5 is ordinary RAM. The console now finds its serial line from the devicetree's `/chosen/stdout-path`: on the Pi 5 that is `serial10`, the debug connector, a PL011 at `0x107d001000`. | `kernel/src/hal/console.c`, `kernel/src/hal/fdt_uart.c`; `tools/fdt_uart_test.c` reads the board's real devicetree | Checked off the board only. The first run is the board's. |
|
||||
| R2 | Entry is at EL2 with the MMU off. Nothing on this path has ever run. | `boards/raspi/README.md`; `FABRIC-3.md` IV.3 | Unknown. |
|
||||
| R3 | Two details of the framebuffer request are unverified: the size field of the allocate tag, and whether the address returned needs its top bits masked. The mode is fixed at 1920x1080x32. | `FABRIC-3.md` IV.3 item 3 | No picture, or a wrong one. With R1 unfixed there is then no channel at all. |
|
||||
| R4 | USB, Ethernet and GPIO are behind the RP1 chip on PCIe, which needs a Broadcom-specific driver that is not written. | `FABRIC-3.md` IV.3 item 5 | No USB on the Pi 5 whatever is done about A1. |
|
||||
@@ -58,7 +58,7 @@ nowhere.
|
||||
|
||||
| # | What | Where | Effect |
|
||||
|---|---|---|---|
|
||||
| M1 | **Likely blocks first boot; to be confirmed against the board's devicetree.** The console writes to a 16550 UART at `0x10000000` with its registers one byte apart, and waits on the status register at offset 5. The JH7110's UART is at that address, but as I recall its devicetree gives `reg-shift = <2>`: registers four bytes apart, status at offset `0x14`. | `kernel/src/hal/console.c:99-109` | If so, the first character waits for ever on a byte that is not the status register. QEMU's UART is a byte-spaced 16550, so the QEMU boot through U-Boot did not show this. |
|
||||
| M1 | **Fixed 2026-10-13.** The console, and the UEFI loader before it, wrote to a 16550 at `0x10000000` with registers one byte apart. The JH7110's UART is at that address with `reg-shift = <2>` and `reg-io-width = <4>` (mainline `jh7110.dtsi`): the loader would have waited for ever on its first character. Both now take the layout from the devicetree. | `kernel/src/hal/console.c`, `kernel/src/boot/uefi_loader.c` | Rehearsed in QEMU through U-Boot, which hands over a devicetree: "serial line is a 16550 at 0x10000000 (named by the devicetree)". QEMU's UART is byte-spaced, so the four-byte layout itself is checked by the host test only. |
|
||||
| M2 | The display depends on U-Boot offering a framebuffer to the EFI loader. | `boards/milkv/README.md` | Unknown. With M1 unfixed there is then no channel at all. |
|
||||
| M3 | USB is behind the JH7110's PCIe controller; whether that is plain ECAM has not been looked up. | `FABRIC-3.md` V.3 item 5 | No USB until it is. |
|
||||
| M4 | `FABRIC-3.md` V describes a native entry at `0x40000000`; the image built today is the UEFI loader run by U-Boot's `bootefi`. The README here is the newer and is what the build does. | `boards/milkv/README.md` | None; noted so the two are not confused on the day. |
|
||||
@@ -71,12 +71,22 @@ port, `kernel/src/arch/armv7` (entry, MMU, GIC, private timer); and the four fil
|
||||
`__int128` or have no ARMv7 branch (`boards/zynq7020/README.md` names them). It is the host for
|
||||
the v4 mesh, so it also waits on A6.
|
||||
|
||||
### 1.6 What I would close before the bench day
|
||||
### 1.6 Found in rehearsal, 2026-10-13: the bring-up build floods its prompt
|
||||
|
||||
Built with `EMERGENCY_CONSOLE_ENABLED=1` and booted with nothing typed, the Mars image prints
|
||||
`ok> ok` without end: 1.4 million times in 200 seconds, through U-Boot in QEMU. Under the
|
||||
usual QEMU firmware the first prompt waits, a typed line is answered, and then the same flood
|
||||
begins. The image built from the commit before the console change does the same, so it is
|
||||
not the serial line. **Not found yet, and it blocks a usable prompt on every board's bring-up
|
||||
build.** The production build, which waits for a login, does not show it: the three-ISA
|
||||
acceptance boots reach one `zuse@Hera` prompt and stop there.
|
||||
|
||||
### 1.7 What I would close before the bench day
|
||||
|
||||
In this order, each as a design for approval first:
|
||||
|
||||
1. R1 and M1: a console that finds its UART from the devicetree, and does nothing when there
|
||||
is none. Without them the Pi 5 and the Mars may show nothing at all.
|
||||
1. ~~R1 and M1: a console that finds its UART from the devicetree, and does nothing when
|
||||
there is none.~~ Done 2026-10-13. Then 1.6, the flood.
|
||||
2. A6: the v4 switch in the board images. The v4 node needs only a console to reach a prompt;
|
||||
it has no login, no fleet and no disk to wait for, so it is the shorter road to a first
|
||||
prompt on each board.
|
||||
@@ -123,10 +133,12 @@ make boot_image TARGET=RASPI EMERGENCY_CONSOLE_ENABLED=1
|
||||
make boot_image TARGET=MILKV EMERGENCY_CONSOLE_ENABLED=1
|
||||
```
|
||||
|
||||
- [ ] **`make clean TARGET=<board>` first.** The switch is compiled in, and objects built
|
||||
without it are not rebuilt when it changes: an image built over old objects boots
|
||||
headless (seen 2026-10-13).
|
||||
- [ ] Each ends with its image in `build/boards/<board>/`. Record `sha256sum` of each.
|
||||
- [ ] Confirm the switch took: the image booted in QEMU (3.2) shows a prompt with no
|
||||
thumbdrive attached. That the root `Makefile` passes the setting down has not been
|
||||
tried.
|
||||
thumbdrive attached. After a clean build it does (tried on `MILKV`).
|
||||
- [ ] The Pi 5 build fetches the board's DTB once from the pinned firmware release; with no
|
||||
network, pass `RPI5_DTB=/path/to/bcm2712-rpi-5-b.dtb`.
|
||||
- [ ] Put back `v3/include/version.h` and `capsules/BLOCK_MAP.md` afterwards: the build
|
||||
|
||||
Reference in New Issue
Block a user