Cada app tiene ahora su propia ranura de estado en el Manifiesto de Génesis (EntradaApp.estado): guarda y recobra lo suyo, sobrevive al reinicio, y no pisa a ninguna otra app. - apps/memoriosa: app WASM interactiva nueva. Cuenta las teclas pulsadas y persiste el recuento; al reiniciar despierta con su cuenta intacta. Reemplaza la 2a instancia de hola en la genesis. - kernel: capacidades sys_estado_cargar / sys_estado_guardar. El kernel custodia un manifiesto VIVO (Mutex<Manifiesto>); fijar_estado lo muta, lo re-graba en el grafo y lo re-ancla. ContextoCapacidades.indice_app da a cada app su identidad — su ranura, jamas la de otra. - cargar_userspace instala el manifiesto vivo antes de instanciar las apps: el init de una app ya consulta su estado al despertar. Verificado en QEMU (screendump + sendkey): disco virgen -> memoriosa con 0 celdas, testigo verde; 5 pulsaciones -> 5 celdas; reinicio -> 5 celdas intactas, testigo ambar (init releyo el estado del grafo). Cierra la Fase 7 — el userspace nace del grafo, completa. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
7.2 KiB
renaser — Hoja de ruta
Estado de las fases del proyecto. Para la arquitectura, ver ARCHITECTURE.md.
Fases completadas
Todas verificadas en QEMU (captura de pantalla incluida en su momento).
Fase 1 — el primer microsegundo
Arranque UEFI, adopción del framebuffer GOP, lienzo de doble búfer y la baliza
de pánico (franja roja al colapsar). Punto de entrada con bootloader_api.
Fase 1.5 — empaquetado y arranque
Miembro boot/: constructor de la imagen de disco UEFI (crate bootloader
0.11, vía dependencia de artefacto) y lanzador de QEMU. cargo run pasa a
compilar, forjar la imagen y arrancar, todo de un gesto.
Fase 2.0 — cimientos del manejo de fallos
GDT propia + TSS con stack de emergencia (IST) para el doble fallo. IDT con manejadores de excepción de CPU. El breakpoint es recuperable; el resto de excepciones encienden la baliza.
Fase 2.1 — interrupciones de hardware
Remapeo del PIC 8259 fuera del rango de las excepciones. Temporizador (PIT) a 100 Hz e IRQ1 de teclado. El kernel pasa de "pintar una vez" a un bucle de render despertado por el hardware.
Fase 3 — memoria dinámica y reactor asíncrono
Heap de 64 MiB con linked_list_allocator como asignador global; manejador
propio de OOM (franja naranja). Reactor cooperativo: Executor, Task,
Waker. Texto vectorial con fontdue: el texto deja de ser mapa de bits.
Fase 4 — el escudo de aislamiento WASM
Runtime wasmi no_std. Matriz de capacidades con dos funciones de host
(sys_render_frame, sys_get_scancode) y validación infranqueable de límites
de la memoria lineal. Primera app del userspace: apps/hello_wasm, un módulo
wasm32 aislado que pinta y responde al teclado.
Fase 5 — multitarea cooperativa, fuel y reloj
Unificación del reactor (Fase 3) y el runtime WASM (Fase 4). El ABI del
userspace pasa a init/tick: cada tick es un punto de cesión cooperativa.
async_system::reloj convierte la IRQ0 en el Future EsperaFrame, que marca
el compás de los fotogramas. Cada app es una AplicacionWasm persistente y una
tarea del reactor. Escudo de combustible (fuel): cada tick corre con un
presupuesto estricto; agotarlo desaloja la app sin tocar al kernel. Capacidades
ampliadas — regiones de dibujo por app y canal de teclado por app. Verificado
en QEMU con tres apps concurrentes, una de ellas díscola y desalojada en vivo.
Fase 6.0 — cuotas de memoria y ciclo de vida
Completa el aislamiento espacial del userspace. Cada AplicacionWasm instancia
su Store con un StoreLimits (techo de memoria lineal de 4 MiB, vía
Store::limiter); rebasarlo es una trampa que desaloja la app con baliza
amarilla — gemela de la púrpura del desalojo por combustible. Drop para
AplicacionWasm reconcilia el ciclo de vida: da de baja el canal de teclado de
la difusión de la IRQ1. Verificado en QEMU con cuatro apps — una díscola
(desalojo temporal) y una glotona (desalojo espacial), ambas en vivo.
Fase 6.1 — sustrato de almacenamiento (completada)
Estrategia incremental para el almacenamiento, frente al riesgo del hardware:
- 6.1a — Sonda PCI (hecha) —
drivers/pci.rsenumera el bus PCI por0xCF8/0xCFCy localiza el disco virtio-blk;bootforja el disco de pruebas y lo adjunta comovirtio-blk-pci. El muro del descubrimiento de hardware queda derribado. - 6.1b — HAL y lectura de sector (hecha) —
drivers/disco.rs: asignador de marcos «bump»,KernelHal(eltrait Haldevirtio-drivers: DMA y traducción de direcciones) ymontar_y_leer_sector0, que lee el sector 0 por sondeo. Verificado por una firma que viaja del anfitrión al disco y vuelve. - 6.1c — Grafo de objetos (hecha) —
almacen.rs: el almacenamiento como DAG direccionado por contenido —la identidad de un objeto es el hash BLAKE3 de su forma serializada (postcard); el disco se organiza como un log con superbloque e índice—, y las cinco capacidadessys_object_*que lo exponen al userspace.drivers/disco.rsgana un asignador de marcos con liberación real (mapa de bits), escritura de sectores y unVirtIOBlkpersistente. La appcronistalleva la cuenta de los arranques en el grafo: la cuenta perdura entre reinicios.
Fase 6.2 — E/S de disco asíncrona por interrupción (completada)
La Fase 6.1 hizo hablar al disco, pero por sondeo: el procesador se quedaba en espera activa vigilando el used ring de virtio. La 6.2 libera el planificador cooperativo — la E/S de bloques pasa a ser reactiva:
EsperaDisco— una transferencia de bloques comoFuturenativo, sobre la API no bloqueante devirtio-drivers(read_blocks_nb/peek_used/complete_*). Cede la CPU mientras el disco trabaja.- La IRQ del disco —
montardescubre la línea de IRQ legada del dispositivo (registro «Interrupt Line» del espacio de configuración PCI), la enruta por el 8259 y registra su manejador;atender_irqreconoce la interrupción y despierta a la tarea que aguardaba el bloque. bloquear_en— el puente para los contextos síncronos (el arranque, las capacidades WASM): duerme la CPU conhlten vez de sondear.
Decisión de ingeniería: las IRQ se enrutan por el PIC 8259 que el kernel ya gobierna, no por el IOAPIC — basta leer la línea que el firmware ya asignó. Verificado en QEMU: el disco se enruta a la IRQ 11; una tarea-sonda del reactor lee un bloque de forma asíncrona mientras las apps siguen pintando.
Fase 7 — el userspace nace del Grafo de Objetos (completada)
Hasta la Fase 6, el userspace venía empotrado en el binario del kernel:
cuatro include_bytes! de .wasm y regiones escritas a mano. La Fase 7 lo
destierra — las aplicaciones pasan a ser objetos del grafo, gobernadas por un
Manifiesto de Génesis que también vive en el grafo. Plan completo en
FASE7.md.
- 7a — el Manifiesto (completada).
manifiesto.rs: tiposManifiesto/EntradaAppy carga desde el grafo. El superbloque gana el anclamanifiesto(VERSION 1→2).kernel_mainlee el manifiesto e instancia cada app recuperando su bytecode del grafo, verificado por su hash. - 7b — la imagen sembrada por
boot(completada). Nace la crateformato, un núcleono_stdcon el formato del grafo en disco, COMPARTIDO por el kernel y el constructor de imagenboot.bootsiembra el disco virgen con el grafo ya poblado —bytecode y manifiesto—; el kernel pierde todoinclude_bytes!del userspace. Su binario ya no carga ni un.wasm. - 7c — persistencia inter-sesión (completada). La app
memoriosagraba su estado como un objeto del grafo; el kernel lo ancla en la ranuraEntradaApp.estadoy re-graba el manifiesto. Al despertar,initlo relee y la app retoma donde quedó. Capacidadessys_estado_cargar/sys_estado_guardar; el kernel custodia un manifiesto VIVO y mutable.
Líneas abiertas posteriores: más capacidades del host (temporización, audio);
la Fase 8 — el compositor sobre mirada-layout.
Principios que persisten entre fases
- Reutilizar infraestructura madura de la comunidad antes que reinventar.
unsafemínimo, confinado y justificado.- Verificar cada fase en QEMU antes de cerrarla.
git commit+git pushtras cada iteración.