1# renaser — Hoja de ruta
2
3Estado de las fases del proyecto. Para la arquitectura, ver `ARCHITECTURE.md`.
4
5## Fases completadas
6
7Todas verificadas en QEMU (captura de pantalla incluida en su momento).
8
9### Fase 1 — el primer microsegundo
10Arranque UEFI, adopción del framebuffer GOP, lienzo de doble búfer y la baliza
11de pánico (franja roja al colapsar). Punto de entrada con `bootloader_api`.
12
13### Fase 1.5 — empaquetado y arranque
14Miembro `boot/`: constructor de la imagen de disco UEFI (crate `bootloader`
150.11, vía dependencia de artefacto) y lanzador de QEMU. `cargo run` pasa a
16compilar, forjar la imagen y arrancar, todo de un gesto.
17
18### Fase 2.0 — cimientos del manejo de fallos
19GDT propia + TSS con stack de emergencia (IST) para el doble fallo. IDT con
20manejadores de excepción de CPU. El breakpoint es recuperable; el resto de
21excepciones encienden la baliza.
22
23### Fase 2.1 — interrupciones de hardware
24Remapeo del PIC 8259 fuera del rango de las excepciones. Temporizador (PIT) a
25100 Hz e IRQ1 de teclado. El kernel pasa de "pintar una vez" a un bucle de
26render despertado por el hardware.
27
28### Fase 3 — memoria dinámica y reactor asíncrono
29Heap de 64 MiB con `linked_list_allocator` como asignador global; manejador
30propio de OOM (franja naranja). Reactor cooperativo: `Executor`, `Task`,
31`Waker`. Texto vectorial con `fontdue`: el texto deja de ser mapa de bits.
32
33### Fase 4 — el escudo de aislamiento WASM
34Runtime `wasmi` `no_std`. Matriz de capacidades con dos funciones de host
35(`sys_render_frame`, `sys_get_scancode`) y validación infranqueable de límites
36de la memoria lineal. Primera app del userspace: `apps/hello_wasm`, un módulo
37`wasm32` aislado que pinta y responde al teclado.
38
39### Fase 5 — multitarea cooperativa, fuel y reloj
40Unificación del reactor (Fase 3) y el runtime WASM (Fase 4). El ABI del
41userspace pasa a `init`/`tick`: cada `tick` es un punto de cesión cooperativa.
42`async_system::reloj` convierte la IRQ0 en el `Future` `EsperaFrame`, que marca
43el compás de los fotogramas. Cada app es una `AplicacionWasm` persistente y una
44tarea del reactor. Escudo de combustible (`fuel`): cada `tick` corre con un
45presupuesto estricto; agotarlo desaloja la app sin tocar al kernel. Capacidades
46ampliadas — regiones de dibujo por app y canal de teclado por app. Verificado
47en QEMU con tres apps concurrentes, una de ellas díscola y desalojada en vivo.
48
49### Fase 6.0 — cuotas de memoria y ciclo de vida
50Completa el aislamiento espacial del userspace. Cada `AplicacionWasm` instancia
51su `Store` con un `StoreLimits` (techo de memoria lineal de 4 MiB, vía
52`Store::limiter`); rebasarlo es una trampa que desaloja la app con baliza
53amarilla — gemela de la púrpura del desalojo por combustible. `Drop` para
54`AplicacionWasm` reconcilia el ciclo de vida: da de baja el canal de teclado de
55la difusión de la IRQ1. Verificado en QEMU con cuatro apps — una díscola
56(desalojo temporal) y una glotona (desalojo espacial), ambas en vivo.
57
58## Fase 6.1 — sustrato de almacenamiento (completada)
59
60Estrategia incremental para el almacenamiento, frente al riesgo del hardware:
61
62- **6.1a — Sonda PCI** *(hecha)* — `drivers/pci.rs` enumera el bus PCI por
63 `0xCF8`/`0xCFC` y localiza el disco virtio-blk; `boot` forja el disco de
64 pruebas y lo adjunta como `virtio-blk-pci`. El muro del descubrimiento de
65 hardware queda derribado.
66- **6.1b — HAL y lectura de sector** *(hecha)* — `drivers/disco.rs`: asignador
67 de marcos «bump», `KernelHal` (el `trait Hal` de `virtio-drivers`: DMA y
68 traducción de direcciones) y `montar_y_leer_sector0`, que lee el sector 0 por
69 sondeo. Verificado por una firma que viaja del anfitrión al disco y vuelve.
70- **6.1c — Grafo de objetos** *(hecha)* — `almacen.rs`: el almacenamiento como
71 DAG direccionado por contenido —la identidad de un objeto es el hash BLAKE3
72 de su forma serializada (`postcard`); el disco se organiza como un log con
73 superbloque e índice—, y las cinco capacidades `sys_object_*` que lo exponen
74 al userspace. `drivers/disco.rs` gana un asignador de marcos con liberación
75 real (mapa de bits), escritura de sectores y un `VirtIOBlk` persistente. La
76 app `cronista` lleva la cuenta de los arranques en el grafo: la cuenta
77 perdura entre reinicios.
78
79## Fase 6.2 — E/S de disco asíncrona por interrupción (completada)
80
81La Fase 6.1 hizo hablar al disco, pero por **sondeo**: el procesador se quedaba
82en espera activa vigilando el *used ring* de virtio. La 6.2 libera el
83planificador cooperativo — la E/S de bloques pasa a ser **reactiva**:
84
85- `EsperaDisco` — una transferencia de bloques como `Future` nativo, sobre la
86 API no bloqueante de `virtio-drivers` (`read_blocks_nb` / `peek_used` /
87 `complete_*`). Cede la CPU mientras el disco trabaja.
88- La **IRQ del disco** — `montar` descubre la línea de IRQ legada del
89 dispositivo (registro «Interrupt Line» del espacio de configuración PCI), la
90 enruta por el 8259 y registra su manejador; `atender_irq` reconoce la
91 interrupción y despierta a la tarea que aguardaba el bloque.
92- `bloquear_en` — el puente para los contextos síncronos (el arranque, las
93 capacidades WASM): duerme la CPU con `hlt` en vez de sondear.
94
95Decisión de ingeniería: las IRQ se enrutan por el **PIC 8259** que el kernel ya
96gobierna, no por el IOAPIC — basta leer la línea que el firmware ya asignó.
97Verificado en QEMU: el disco se enruta a la IRQ 11; una tarea-sonda del reactor
98lee un bloque de forma asíncrona mientras las apps siguen pintando.
99
100## Fase 7 — el userspace nace del Grafo de Objetos (completada)
101
102Hasta la Fase 6, el userspace venía **empotrado en el binario del kernel**:
103cuatro `include_bytes!` de `.wasm` y regiones escritas a mano. La Fase 7 lo
104destierra — las aplicaciones pasan a ser objetos del grafo, gobernadas por un
105**Manifiesto de Génesis** que también vive en el grafo. Plan completo en
106`FASE7.md`.
107
108- **7a — el Manifiesto (completada).** `manifiesto.rs`: tipos `Manifiesto` /
109 `EntradaApp` y carga desde el grafo. El superbloque gana el ancla
110 `manifiesto` (VERSION 1→2). `kernel_main` lee el manifiesto e instancia cada
111 app recuperando su bytecode del grafo, verificado por su hash.
112- **7b — la imagen sembrada por `boot` (completada).** Nace la crate
113 `formato`, un núcleo `no_std` con el formato del grafo en disco, COMPARTIDO
114 por el kernel y el constructor de imagen `boot`. `boot` siembra el disco
115 virgen con el grafo ya poblado —bytecode y manifiesto—; el kernel pierde
116 todo `include_bytes!` del userspace. Su binario ya no carga ni un `.wasm`.
117- **7c — persistencia inter-sesión (completada).** La app `memoriosa` graba
118 su estado como un objeto del grafo; el kernel lo ancla en la ranura
119 `EntradaApp.estado` y re-graba el manifiesto. Al despertar, `init` lo relee
120 y la app retoma donde quedó. Capacidades `sys_estado_cargar` /
121 `sys_estado_guardar`; el kernel custodia un manifiesto VIVO y mutable.
122
123Líneas abiertas posteriores: más capacidades del host (temporización, audio);
124la Fase 8 — el compositor sobre `mirada-layout`.
125
126## Principios que persisten entre fases
127
128- Reutilizar infraestructura madura de la comunidad antes que reinventar.
129- `unsafe` mínimo, confinado y justificado.
130- Verificar cada fase en QEMU antes de cerrarla.
131- `git commit` + `git push` tras cada iteración.
ROADMAP.md
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.rs enumera el bus PCI por
0xCF8/0xCFC y localiza el disco virtio-blk; boot forja el disco de
pruebas y lo adjunta como virtio-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 (el trait Hal de virtio-drivers: DMA y
traducción de direcciones) y montar_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 capacidades sys_object_* que lo exponen
al userspace. drivers/disco.rs gana un asignador de marcos con liberación
real (mapa de bits), escritura de sectores y un VirtIOBlk persistente. La
app cronista lleva 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 como Future nativo, sobre la
API no bloqueante de virtio-drivers (read_blocks_nb / peek_used /
complete_*). Cede la CPU mientras el disco trabaja.
- La IRQ del disco —
montar descubre 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_irq reconoce 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 con hlt en 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: tipos Manifiesto /
EntradaApp y carga desde el grafo. El superbloque gana el ancla
manifiesto (VERSION 1→2). kernel_main lee el manifiesto e instancia cada
app recuperando su bytecode del grafo, verificado por su hash.
- 7b — la imagen sembrada por
boot (completada). Nace la crate
formato, un núcleo no_std con el formato del grafo en disco, COMPARTIDO
por el kernel y el constructor de imagen boot. boot siembra el disco
virgen con el grafo ya poblado —bytecode y manifiesto—; el kernel pierde
todo include_bytes! del userspace. Su binario ya no carga ni un .wasm.
- 7c — persistencia inter-sesión (completada). La app
memoriosa graba
su estado como un objeto del grafo; el kernel lo ancla en la ranura
EntradaApp.estado y re-graba el manifiesto. Al despertar, init lo relee
y la app retoma donde quedó. Capacidades sys_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.
unsafe mínimo, confinado y justificado.
- Verificar cada fase en QEMU antes de cerrarla.
git commit + git push tras cada iteración.