gfx: draw the console in RAM, and write it to the card write-combined
On the first real machine with a discrete card (an RTX 3060, 800x600 from the UEFI GOP) the console was slow enough to photograph mid-scroll, and the boot died on CPU 1's "cpu1: starting": CPU 0 spun 200M times on the console lock while CPU 1 held it, scrolling, and called it a deadlock. The framebuffer is device memory in the uncached 3-4 GB page of the direct map. QEMU's stdvga is RAM underneath, so nothing showed there; on a card, gfx_scroll_up's memmove read the whole screen back across the bus one byte at a time, and every anti-aliased glyph read back each pixel it blended. So the console now draws into a copy of the screen in RAM (vmap_alloc: kalloc pages behind a page table of their own, since nothing needs it contiguous), and gfx_flush() copies the changed rectangle onto the card through an ioremap_wc() mapping -- PAT entry 4 set to write-combining on every CPU. Flushes happen where drawing ends: a message, a terminal write, an echo, a terminal switch. Scrolling moves eight bytes at a time instead of one. /dev/fb0 reads and writes the card itself, as before. The early console's fb_info now carries the physical address it always should have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
93f981c7ea
commit
60d06658f0
9 changed files with 347 additions and 8 deletions
|
|
@ -41,6 +41,27 @@ is now a second caller of one function rather than an edit to the crash screen.
|
|||
left running says so before any bus is enumerated, because the console draws
|
||||
long before PCI is walked.
|
||||
|
||||
### Drawing in RAM
|
||||
|
||||
The console does not draw on the card. Once there is a page allocator,
|
||||
`gfx_accelerate()` gives it a copy of the screen in RAM (`vmap_alloc()`, so it
|
||||
needs no contiguous memory) and maps the real framebuffer write-combined
|
||||
(`ioremap_wc()`, PAT entry 4). Every drawing routine reads and writes the copy;
|
||||
`gfx_flush()` copies the rectangle that changed onto the card, and is called
|
||||
where drawing ends — after a message, a `write()` to a terminal, an echo, a
|
||||
terminal switch, the crash screen — not where it happens.
|
||||
|
||||
On QEMU's stdvga the framebuffer is RAM, so none of this was visible. On a real
|
||||
graphics card it is device memory behind the PCI hole, uncached: a scroll is a
|
||||
`memmove` that reads the whole screen back across the bus a byte at a time,
|
||||
and an anti-aliased glyph reads every pixel it blends. Measured on an RTX 3060
|
||||
at 800×600, one scroll took long enough to photograph half done, and a second
|
||||
CPU waiting to print declared the console lock deadlocked.
|
||||
|
||||
`/dev/fb0` still reads and writes the card itself (`gfx_hw_ptr()`), and its
|
||||
`mmap` still maps the physical framebuffer, so a program drawing on the screen
|
||||
and `vgpud` mirroring it see what is on the screen.
|
||||
|
||||
### `display` — the class
|
||||
|
||||
`struct display_ops`, found with `device_find_class(DEVCLASS_DISPLAY)`.
|
||||
|
|
|
|||
Loading…
Reference in a new issue