memory: UEFI reaches userspace, and the ISO grows a hierarchy
Records the four bugs between "boots to cpu0: starting" and "boots to an interactive shell", the new ioremap rule for device registers, and what the disc now contains -- including that it is still not a live CD, and what that would take. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9735279970
commit
b428a50145
4 changed files with 121 additions and 21 deletions
44
.claude/memory/schunix-ioremap-and-bars.md
Normal file
44
.claude/memory/schunix-ioremap-and-bars.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
name: schunix-ioremap-and-bars
|
||||
description: "ioremap() maps device registers; never use P2V on a BAR, because firmware may place a 64-bit BAR far above the 4 GB direct map"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: d4821aa9-2e49-40da-91e7-90ef9ed9997e
|
||||
modified: 2026-08-09T20:03:56.063Z
|
||||
---
|
||||
|
||||
**Never reach a device's registers with `P2V(bar.base)`.** Use
|
||||
`ioremap(pa, size)` from `kernel/arch/x86_64/vm.c` (declared in `include/defs.h`).
|
||||
|
||||
Every driver used to do the `P2V` thing, which silently assumes the BAR lands
|
||||
inside the 0-4 GB that `kvmalloc()` direct-maps with four 1 GB pages. Under
|
||||
SeaBIOS it always does. Under OVMF it does not — virtio-gpu's 64-bit BAR came
|
||||
back at about **768 GB**, `P2V` produced an address with no translation behind
|
||||
it, and the first register write page faulted, then double faulted, then triple
|
||||
faulted into a reboot loop. Coming out of a driver bind, that reads as broken
|
||||
hardware rather than a missing mapping.
|
||||
|
||||
## How it works
|
||||
|
||||
PDPT entries **4-511 were unused**: the direct map occupies 0-3, and `kpml4[0]`,
|
||||
`kpml4[KERNBASE]` and every process's PML4 (see `setupkvm`) all point at that
|
||||
same table. So each MMIO region takes one 1 GB page there — no page table to
|
||||
allocate, and the mapping appears in every address space at once. Entries are
|
||||
`PTE_PCD | PTE_PWT` for the same reason the top GB of the direct map is: these
|
||||
are registers, and a write sitting in a cache line is a write the device never
|
||||
sees.
|
||||
|
||||
**A physical address below 4 GB is returned unchanged, as `P2V` would have.**
|
||||
That is what makes the BIOS path — where every BAR is low — provably identical
|
||||
rather than merely tested.
|
||||
|
||||
## Where this bites next
|
||||
|
||||
Converted: virtio-gpu, e1000, xhci. xHCI had already been *refusing* to bind
|
||||
above 4 GB with a comment saying the mapping did not exist yet.
|
||||
|
||||
Any new driver that reads a BAR needs the same treatment. `grep -rn 'P2V(d->bar'
|
||||
kernel/` should stay empty.
|
||||
|
||||
See [[schos-uefi-loader]] for the boot path this unblocked.
|
||||
Loading…
Reference in a new issue