fix(renaser): mapeador MMIO en el kernel — la causa real del colapso
El `-global pci-hole64-size=0` del commit anterior NO movía los BAR: verifiqué con `info pci` que OVMF seguía alojando el BAR4 prefetchable 64-bit del virtio-blk en `0xc000000000` (mi Proxmox) o `0x800000000` (la laptop del usuario). El cargador `bootloader_api` 0.11 mapea la memoria física pero no extiende su mapeo hasta la ventana PCI de 64 bits, y `KernelHal::mmio_phys_to_virt` devolvía `phys + offset` a ciegas — un puntero a memoria sin tabla de páginas, al primer registro MMIO leído → #PF. La solución: un mapeador MMIO propio del kernel. - `memory::mmio`: envuelve la tabla L4 activa (vía CR3 + el mapeo de memoria física del cargador) en un `OffsetPageTable`. Su función `mapear(fisica, tam)` abre, para cada página de la región, una entrada en la L4 con `PRESENT | WRITABLE | NO_CACHE | WRITE_THROUGH` — las banderas habituales del MMIO. - Los marcos para tablas intermedias salen del banco DMA del disco (`drivers::disco::asignar_marco_para_tabla`, sin pánico). Se ponen a cero antes de cederlos: las tablas empiezan vacías. - Tratamos `PageAlreadyMapped` y `ParentEntryHugePage` como éxito: la región ya estaba cubierta por el cargador (con páginas 4 KiB o hugepages 2 MiB / 1 GiB) y el acceso ya funciona. Solo abortamos el mapeo si se nos agota la arena DMA. - `KernelHal::mmio_phys_to_virt` llama a `memory::mmio::mapear` antes de devolver el puntero virtual. virtio-drivers lo invoca con la base y el tamaño exactos de cada BAR; el kernel asegura que cada uno sea accesible antes de devolverlo. - `kernel_main` funda el mapeador justo después del heap (paso 4.5), antes del disco. Necesita `physical_memory_offset` para alcanzar la L4 activa. Quito el `-global q35-pcihost.pci-hole64-size=0` que añadí antes: no movía los BAR (verificado con `info pci`) y solo confundía la descripción del fix. Esta solución es la robusta: el kernel sabe mapear sus propios MMIOs y deja de depender del firmware. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -323,13 +323,6 @@ fn lanzar_qemu(imagen: &Path, ovmf: &str) -> Result<(), String> {
|
||||
.arg("-vga").arg("std")
|
||||
.arg("-serial").arg("stdio")
|
||||
.arg("--no-reboot")
|
||||
// El cargador `bootloader` 0.11 mapea la memoria fisica que ve, pero NO
|
||||
// las regiones MMIO en el agujero PCI de 64 bits (por encima de 4 GiB),
|
||||
// donde OVMF coloca los BAR de virtio-blk en QEMU q35 modernos con
|
||||
// KVM. Sin mapeo, leer un registro MMIO del disco era un #PF
|
||||
// inevitable. Apagar `pci-hole64-size` fuerza a OVMF a alojar todos
|
||||
// los BAR en los primeros 4 GiB, que el cargador si mapea.
|
||||
.arg("-global").arg("q35-pcihost.pci-hole64-size=0")
|
||||
// El disco de objetos, como dispositivo virtio-blk sobre el bus PCI.
|
||||
.arg("-drive").arg(format!("format=raw,file={NOMBRE_DISCO},if=none,id=drv0"))
|
||||
.arg("-device").arg("virtio-blk-pci,drive=drv0");
|
||||
|
||||
Reference in New Issue
Block a user