Repository navigation
Raspberry Pi 5: native kernel for BCM2712 and RP1 - #1046
Merged
Merged
Conversation
The native kernel on a Pi 5 Model B rev 1.0 (8GB). No emulator models one, so this went to the board first: os/bcm2712/loader is a serial loader that reports what the firmware left, and each step asked the hardware. On that board: all four cores through PSCI, the Dis JIT, the SD card, read and written; gigabit Ethernet on RP1's GEM, 927 Mbit/s in and 903 out, a 45-round half-hour run clean; USB host on RP1's DWC3s; Wi-Fi joined with WPA2; Bluetooth inquiry; GPIO; RP1 MSI-X; the external PCIe connector and an NVMe drive as #S/nvme0; the real-time clock as #r; fan, temperature, ACT LED, power button level in #P. The console is on RP1's UART0 and UART4 both, because an M.2 board sits on header pins 1-12. Not done, or not proved: the display (no monitor yet); GPIO edges never fired; PCIe gen 2, where the link drops 1.6s in, under Linux too, so gen 1 is the default; NVMe writes are fenced to the last 2GB of the disk; audio; memory above 4GB; no long soak. os/bcm2712/INVENTORY.md has all of it. Changes to shared code are under compile-time flags: bcm2837 and bcm2711 kernels were byte-identical against master with the shared files reverted, before the last additions to devarch.c, devcons.c and devsd.c, also gated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
RP1's UART0 and UART4 take their input by MSI-X now, which ends the polling on RP1. The firmware answers a 32-bit framebuffer request with 16 unless config.txt says framebuffer_depth=32, and says nothing, so the kernel checks the pitch it was given, and the card's config sets it. With that Lucifer draws on HDMI, and a keyboard and a mouse work on it. The screen's size comes from the display's EDID where the firmware has it. On the Pi 5 it does not: it reports 1920x1080 whatever is attached, and a 1024x768 monitor overflows. That is not solved. GPIO edges fired for the first time, across a jumper. INVENTORY.md says where each of these stands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
A Pi 5's firmware sends 1920x1080 whatever is attached and ignores hdmi_group, hdmi_mode and framebuffer_width, because the OS is expected to set the mode. So the kernel does, through the tags Linux's firmware-KMS driver uses: the EDID by the tag that names a display, its first detailed timing to SET_TIMING, and then SET_PLANE on the framebuffer, because setting the timing takes the firmware's plane off the screen and leaves it lit and black. The bench monitor is 1024x768 and was being sent 1080p, which it scaled past its edges. It now shows Lucifer at its own size. The buffer keeps the firmware's 1920-wide pitch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The inventory and README say so. The firmware calls them displays 2 and 7, and offers 640x480 on the second; the EDID path set 1024x768 on both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The write fence is gone; the drive is a test device. nvmewrite now checks writes at the start, middle and end of the disk. #S's named ranges work on NVMe too, with nvmepart on sdctl, so a file system can have part of it. kfs in a 4GB range holds a tree across a reboot. On the whole 2TB it does not finish reaming in any useful time, so it is not the file system for the whole disk. devsd.c's changes are all under NVME0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
#J, #Q and #W, the letters the device registry in #1036 reserves for them; its rows are to be marked in use when that lands. All polled. Timed on the board: an I2C address byte through a jumper at 10.0us a bit (the block adds nothing to its counts, so the first values ran at 115kHz); 8192 bytes through SPI's loopback intact at 1 and 10MHz; PWM at 10ms and 2.5ms to the microsecond at the pin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Asked to advertise less (ether100, ether10), the link came up at 1000 with nothing received: the speed came from what the partner offers, not what both do. 95 in and 94 out at 100, 10 and 9 at 10, wired, with Wi-Fi off: with both on one subnet, outbound takes the radio. The MAC divides its own tx clock, as Linux's CLK_HW_CHG says. Dividing RP1's clock too counts frames out that nothing receives. uart10 carries the console's output. No input: with nothing plugged in its receiver fills with noise. etherusb no longer says the clock stays at 1970, which on a board with a clock it does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
CMD6 to 50MHz, gated to this board: 19 MB/s read off a card that gave 9.3 at 25MHz, and a 64MB stable region of it hashes the same from here as from Linux on the same card. No QEMU models a Pi 5, so the workflow only builds it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
What a driver owes a disk that is going to hold something. A command with no answer, a controller fatal status or a dropped link resets the controller and tries the transfer again: shown with a lost command. A process killed with a command under way used to leave its completion to answer the next one; proved over five kills, the same hash after. The drive is shut down on the way down, and its unsafe-shutdown count stayed still. The transfer size honours the drive's. Partitions come from the disk's GPT or MBR, as nvme0p1 and on. #S/nvmestat is what it says of itself. Data moves through a cached buffer, not uncached memory: reads through dd go from 52 to 161 MB/s. kfs at 16KB blocks reams the whole 1.8TB in 30 seconds and survives a reboot. With nvmeroot, or no card, init takes /n/dos from nvme0p1, and #S attaches without a card when there is a drive. Linux's FAT there reads, and the system ran from it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The link drops once about 1.6s after training and comes back, and the reset in nvme.c catches that: proved on the real thing, then six minutes of SD, NVMe, kfs, SPI, I2C, PWM, Bluetooth LE and Ethernet at once with no further reset, no failed compare and a flat heap. Reads at 370 MB/s against 191. A link that keeps dropping goes to gen 1 after four resets; pciegen1 asks for that, and nvmeslow in sdctl does it by hand. Retraining down under a running drive is proved. MBR tables read too. An unmounted kfs comes back clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Firmware boot from NVMe, BOOT_ORDER 0xf416 and no PCIE_PROBE, reaches a shell in 16s with userland from nvme0p1, and a tryboot reset returns to Linux from a kernel on the same partition, which is how the test got home without hands. A shutdown after the link's first drop with no I/O since found a drive that had reset: it now says so and goes on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
…it was Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Forcing each write to the medium cost kfs nearly half its speed: 18 MB/s against 10, and raw writes 214 against 167. A process flushes every two seconds instead, and at shutdown; nvmefua asks for the old way. halt is PSCI SYSTEM_OFF here, after shutting the drive down. Init reads #P/button and halts on a press, the kernel saying what happened and init what it means. Written; a press is still to come. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The third time this has come up, so nothing in the build says any more. The firmware's device tree lists the banks; each gigabyte above 4GB is one level-1 block, needing no tables of its own, so a bigger board costs no constant; poolsize takes a ulong, the ceilings being fractions of what was found. The revision code stands in for a missing tree. On the 8GB board: 7.1GB free, ceilings of 2, 4 and 2GB, 3.76GB of Dis heap touched and read back, jitbench unchanged. memlimit=N runs as a smaller board: 4, 2 and 1GB each boot to network, drive and shell from one image. The BCM2711 takes the same path and has not run it above 4GB: the bench Pi 4 has no such memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
D0 keeps the pin mux in other registers with other functions; both tables are generated from Linux's pinctrl-bcm2712.c, and the device tree says which applies. A dry run on this C1 board with D0's tree writes what Linux's table says; it has not run on a D0 chip. Below 4GB the tree now overrules the revision code, whose size field cannot say 3GB and would have mapped memory that is not there. The heap ceiling was half of memory, so programs could not reach the rest however idle it was. Ceilings are not reservations, so they may overlap: three quarters, with 5.9GB touched on the 8GB board. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Network load panicked the Pi 5 with 'lock loop' on the run queue's lock, in most boots of one kernel and no boots of another that differed only in where that lock landed: 0x4685e8 failed, 0x4685d0 and 0x468600 did not. The lock was truly stuck: no free reading in 20 million, its last holder having released it, every other core waiting. The address is what matters, and this keeps it off shared lines. What exactly goes wrong on a shared line is not understood. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
…y moved to devletters.py --check failed on master: #1037 and #1039 moved the devices and #1036, landing after, had them only as planned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
… memset and memmove by words on the Pi 5 Core 0 idled in wfi and ready() wakes cores with sev, which does not end that, so a process that had to run on core 0 waited for a clock tick every time. Ethernet input ran at 300 Mbit/s with nothing lost once the IP hardening took out a lock that had been hiding it; now 946, steady, with that hardening in place and the desktop up. runproc went straight round holding and freeing the run queue lock at splhi when it found a proc still marked with a core, faster than a core spinning in ready() could win it. The lock read as held 20 million times running, every holder having released it, until lock() called it a loop and panicked. Whether that happened hung on where runq landed, so the alignment that seemed to fix it is gone: the loop now lets go, with interrupts on. 0 panics in 4 on the kernel and address that failed in most boots. memset and memmove were byte loops, whose speed moved 47% with text layout. By words where alignment allows, under WORDMEM, this board only: allocation 2.4 times as fast, NVMe writes 214 to 297 MB/s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
…t them devletters.py --check was failing on master for #X, #h and #z too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The ceilings were fractions that added up to 125%, and with one heap a VM, to 325%. main and image used about 10MB each with a desktop and every device busy; each now has an eighth of memory, within limits, and programs have the rest. No heap may grow into what those two could still need, however many VMs there are. On 8GB: 512MB, 1GB and 6.4GB. A runaway program reached 6.4GB, got "out of memory", and the system went on. Pools still keep what they grew to: after that the other VMs had none. A shutdown with a transfer under way no longer adds a command to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
By ear on the 3B+: a pure tone had a fuzz on it at any volume, the 11-bit level being the 16-bit sample cut short, an error that repeats with the waveform. First-order error feedback turns that into noise above the tone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
A fractional divider gets its average by dithering the clock, which is jitter on every pulse edge. By ear on the 3B+, that was the fuzz left after the rounding error went. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
…ks before kicking
… and routes alone
…d a dead drive tried again after 30 s
…d came back clears its memory enable
…pped (macb_tx_restart); the watchdog stays as the backstop Under 4 minutes of gigabit traffic both ways the interrupt restarted it 6884 times and the watchdog never had to; every frame given was sent; out went from ~904 to 834-944 Mbit/s.
…its module and its caller's
…file server benchmark kfscmd check printed the whole report and never returned: the read it had waiting for more was never answered when the check ended. On a Pi 5 console that looked like a frozen machine. tests/host/kfscheck_test.sh checks twice and fails on the old kfs. fsbench is the measurement kfs is held to, and gefs will be: on a Pi 5's NVMe, kfs gives 22.9 MB/s write, 47.8 read, 229 small creates/s, and 124 opens/s of the last of 5000 entries in one directory.
…es, and its hash, matching the C on 21 vectors
…eam, load, 9P server, ctl, check (compiles; untested)
…unsigned qid limits, internal errors that say where
…ader and ticker Snapshots tested hosted: snap main s1 keeps the old contents and a file removed after it, delsnap removes it, check ok, cron minute/hour/day snapshots present. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The NVMe driver flushed the drive's write cache every two seconds on its own, which gives no order: a commit protocol (gefs) needs what it wrote before a barrier on the medium before it writes what comes after. sdctl now takes "flush", which returns when it is; a recovery and retry as a transfer has; nvmestat counts them. On a card, which has no such cache, it does nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
…r recovery Power-cut tests (tests/host/gefs_crash_test.sh: a journal of every block written and every flush, -W, made into the disks a cut could leave, torn 4 KB sectors included) lost whole disks: the log's tail is rewritten in place after a commit holds it, and a cut that tears it leaves a block whose hash fails, so the commit's log cannot be read. 9front writes it the same way. Now it goes in two steps with a flush between, the new entries under the old header and then the new header, and is cut back to the commit once at mount; every mixture of neighbouring versions is a valid block. The superblocks get a flush between them, so one cut cannot tear both. Disk format unchanged. Also found by the tests: - check after a crash read the stale on-disk log tail, which chains on to blocks the lost commit allocated, and cached a free block; the next allocation of it broke the file system as a double alloc. getblk now returns the tail in memory. - ctl halt replied before its commits, so whatever ran next could see a disk mid-sync; sync and halt now finish before the reply. - a sync that fails part way leaves the file system read only, as 9front's does, rather than retrying from a half-advanced state; a failed device flush is such a failure. And: built by mk (appl/cmd/disk/gefs/mkfile), in the dis manifest, gefs(4), sdctl flush in sd(3), gefs_hash_test (MetroHash64 and ihash pinned), gefs_test.sh (ream, files, persistence, snapshots, check). 200 power cuts pass; SIGKILL during writes, 15 of 15. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
MetroHash64's loop, which every block written goes through, without the twelve calls a word it made; the pinned values (gefs_hash_test) hold under the interpreter and the JIT. fsbench adds parread1/parread4 (one reader, four at once) and statidle/statbusy (a small file's stat and read, idle and during a 128 MB write, with the longest single operation): what one serving loop costs, kfs and gefs alike. On the Pi 5's NVMe, gefs (p3) against kfs (p2): seqwrite 11.6 / 21.7 MB/s, seqread 40.8 / 45.8, smallcreate 602 / 219 files/s, smallstat 2594 / 490, bigdir 944 / 107, lookup 1439 / 115 opens/s, parread4 47.3 / 43.2 MB/s, statbusy 140 / 224 ops/s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The cuts go where blocks are written in place, the only ones a commit can depend on, and tear those more; the workload makes logs long enough to cross sectors. With the log tail fix taken out it now fails 12 cuts in 100 (it was 1 in 200); with it, 300 of 300 pass. Default 24 cuts. gefs_test and gefs_crash_test run in CI shard 2, and are in CLAUDE.md's table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Every write request hashed and wrote a new root as well as its data, and the next request replaced it, so most were never pointed at by anything on disk. A root made by fastupsert, most of them, is now only cached (dirty, so never evicted) until something is to point at it: a snapshot (tree2kv) or the superblock (packsb), both before a commit's first flush. One replaced in the meantime costs neither hash nor write. Still a fresh copy each time, never changed in place, since a scan held between requests needs blocks as they were. In-memory only; the disk is as before. Hosted: seqwrite 7.6 -> 9.7 MB/s, a small file's stat and read during a big write 85 -> 123 ops/s. 150 power cuts pass, gefs_test passes, and 150 s of writes across minute snapshots checks clean with each snapshot holding what was there at its minute. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
rootpath takes a third source, "gefs nvme0p3": osinit starts the kernel's gefs on #S/nvme0p3, mounts it where 9front has them (the file system on /n/gefs, its adm tree on /n/gefs.adm, every snapshot on /n/dump) and unions its dis/ lib/ fonts/ icons/ after the recovery root, as for the card. gefs.dis is in the recovery root, as dossrv is: the root's server must match the disk and be there to repair it whatever state the card is in (image 2.08 -> 2.21 MB). The first source with a usr/ now has /usr, so "gefs nvme0p3" then "local" keeps the disk's home with the card's trees behind it. disk/gefsroot [-r] [-s src] part copies the card's trees onto it, snapshot first (install.<seconds>), each tree whole so dropped files go, usr/ only when the disk has none. Runs in the caller's namespace (sh -n). gefsroot_test.sh: 14 checks, in CI. Pi 5, nvme0p3: install 82.6 MB from the card in 139 s; booted with rootpath gefs nvme0p3 + local: /dis is the recovery root, then /n/gefs/dis, then /n/dos/dis; /usr is the disk's; a file written there survived a reboot; snapshots on /n/dump; check clean. The card's rootpath is back to local. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
A device that drops off and returns between two of the hub watcher's looks (one a second) reads present both times, and the port it left has disabled itself, as xHCI and USB 2.0 hubs do on any disconnect: every transfer after is a Transaction Error and nothing reset the port. The Pi 5 soak lost its USB Ethernet that way 80 minutes in, for the rest of the boot (root port PORTSC 0x206e1: connected, disabled, connect change unacknowledged). On xHCI (as #679's watcher changes are), a port with a device set up on it that is present but not enabled is now that device gone and back: detached and set up again, as an attach is. baremetal_test.sh (virt): a keyboard in a root port pulled and put back within milliseconds is set up again and typed on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
wifiaddr asked DHCP twice after the radio authenticated and, with no lease, returned nil: nothing asked again, and the radio had no address for the rest of the boot. A Pi 5 soak's radio did that after re- associating mid-handshake; ip/dhcp run by hand minutes later got 192.168.1.101 at once. Authentication already keeps trying; the address now does too, every 30 seconds, and the watcher starts when it comes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
The Pi 5 half of #1051 (keys from a hardware generator alone), which integ/pi5-all took in its merge of it (462c72b) and the soaked build ran: the board's own random.c goes, the RNG200's registers are named for ../bcm/rng200.c, and the README says so. Master has #1051 but not this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
- kernelpins_test: the lock window is closed either way, interrupts off across the test-and-set (this branch's) or PriLock before it (master's #640); a lock() doing neither still fails it (checked). - wordmem_test removed, and -DWORDMEM from the Pi 5's build: master's eight-byte libkern copies (438d985) replace the WORDMEM ones, and libkern_copy_test covers them. - gefs's mkfile sets MODULES, as check-mkfile-deps.py now requires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
pdfinn
marked this pull request as ready for review
November 7, 2026 18:11
Member
Author
|
Branch rebuilt as master plus the Pi 5 work, and marked ready for review. CI is green: 36 checks pass, 1 skipped. What changed on
Checked against the soaked branch: every file that differs differs through master's own changes or styxbrick's. Evidence
Merge is yours. soak34 is the soak of exactly this build. 🤖 Generated with Claude Code |
…ll three Insecure and Verified still asked for 2xx/3xx, as TLS13 no longer does: which status comes back is the server's policy. A Pi 5 soak counted example.com's 403 to its GET, one time in about forty, as TLS failing on a handshake that had succeeded (TLS 1.3, suite 0x1301, verified); the soak's own log, which now keeps a failure's output, showed it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Conflicts: - os/bcm/audiopwm.c: master's audiostat comments on played and underruns, and this branch's rounding carries and pulse range, kept together. - man/3/i2c: one page for #J's two drivers, the Pi 5's header buses and the Pi 4's camera bus; every fact from each page kept, checked against both drivers. - docs/DEVICE-LETTERS.md: #J's row names both boards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
Master's camera (#1085) is the Pi 4's own (os/bcm2711/devcam.c) and the simulated sensor the Pi 5 served as #V is gone with os/port/devcam.c; it dropped #V from bcm2837's table, and this does from bcm2712's (the kernel did not link). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
InferNode on the Raspberry Pi 5 (BCM2712 and RP1), native, no host OS.
os/bcm2712/README.mdis the guide andos/bcm2712/INVENTORY.mdsays what is proved, feature by feature.On the bench board (Pi 5 8GB, rev 1.0): four cores, the JIT, all 8GB, multi-core Dis, SD, Ethernet at 10/100/1000, USB, Wi-Fi, Bluetooth (pairing, L2CAP, LE scan), GPIO with edges, I2C (
#J), SPI (#Q), PWM (#W), the real-time clock, the fan, the power button, NVMe at gen 2, boot from the drive, the release image, Lucifer on either HDMI port.Bugs this found in shared code
arm64: core 0 idled inwfi, andready()wakes cores withsev, which does not end that. A process that had to run on core 0 waited for a clock tick each time. The IP hardening in fix(security): complete report hardening and 9front audit #1032 removed a lock that had been hiding it: gigabit input fell to 300 Mbit/s with nothing lost. All cores nowwfe: 946, steady, with that hardening in place.runprocspun taking and freeing the run queue lock at splhi on a proc still marked with a core, starvingready(). It now lets go, with interrupts on.lock(): a proc preempted between winning a lock and raising its priority, pinned to a core with a spinner at PriLock, deadlocked (lock loop ... held by pc 0x0, within 6 to 70 minutes of the all-devices soak).lock()andcanlock()now keep interrupts off across those instructions.devletters.py --checkfailed on master for#K,#x,#X,#h,#z.Gated to this board:
NVME0,RAMDISCOVER(also BCM2711),SDCARD_HISPEED,WORDMEM,POOLBYNEED. Not gated: the two fixes above,poolsizetaking a ulong, theheapreservetest, andosinit's button watcher and drive fallback.Tests: QEMU bcm2837 + bcm2711 330/0/0 with the lock fix;
audiolevel,wordmem,kernelpinsanddevletterspass. On the Pi 5, 24 hours with every device busy on a diagnostic build of this code: 0 panics, 0 failed compares, 0 media errors, kernel memory 14-17 MB. A 24-hour run on the release kernel is in progress. No QEMU models a Pi 5, so CI only builds it. The 3B+ booted and carried traffic on these fixes before the lock change, from a USB disk, and has not soaked them; the lock change has not run on a real Pi 3 or Pi 4.Known limits
memlimit=.mainandimageceilings come from a few measured pages, not a survey; pools keep what they grow to.🤖 Generated with Claude Code
https://claude.ai/code/session_0195u6z8JjsAy9yrE5TqKxzx