renaser —kernel asíncrono de espacio de direcciones único, no-POSIX, `no_std` x86_64— entra al monorepo como su PROPIO workspace de Cargo, no fusionado: usa toolchain nightly, target `x86_64-unknown-none` y `panic = "abort"`, incompatibles con los perfiles globales de brahman. - `renaser/` — copia del proyecto (sin su `.git`; el repo original conserva su historia standalone). Workspace propio con su `rust-toolchain.toml` y `.cargo/`. - `exclude = ["renaser"]` en el workspace de brahman: Cargo lo trata como ajeno. - El kernel de renaser path-depende `mirada-layout` cruzando la frontera de workspace — primer núcleo compartido. Semilla de la Fase 8 (compositor): geometría de teselado compartida, framebuffer nativo de renaser; smithay se queda en el lado Linux. Verificado: `cargo build -p boot` compila kernel + imagen UEFI con mirada-layout enlazado para bare-metal. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
9.4 KiB
renaser — Arquitectura
Este documento describe la arquitectura del kernel renaser subsistema a
subsistema. Para el estado por fases, ver ROADMAP.md.
1. Filosofía
renaser es un SASOS — Single Address Space Operating System. No hay un espacio de direcciones por proceso ni cambios de contexto de hardware: todo el sistema —kernel y aplicaciones— comparte una única RAM plana.
El aislamiento NO lo da la MMU ni los anillos de privilegio de la CPU. Lo da el software: las aplicaciones se distribuyen como bytecode WebAssembly y se ejecutan dentro de un intérprete que acota matemáticamente cada acceso a memoria. Una aplicación solo puede hacer aquello para lo que el kernel le haya inyectado una capacidad (una función de host). Lo que no está importado no tiene camino físico que recorrer.
La interfaz es visual desde el primer microsegundo. No hay TTY; el texto se rasteriza como gráfico vectorial. "El texto es un caso particular del dibujo."
2. La cadena de arranque
Firmware UEFI → crate `bootloader` 0.11 → kernel::_start → kernel_main
El miembro boot/ (que corre en el anfitrión) toma el ELF del kernel,
lo fusiona con el cargador bootloader 0.11 en una imagen de disco UEFI GPT y
la lanza en QEMU con el firmware OVMF. El cargador deja la CPU en modo largo de
64 bits, mapea el kernel y le entrega una BootInfo con el framebuffer GOP.
3. Estructura del espacio de trabajo
El workspace tiene un solo miembro, boot. El kernel y las apps están
excluidos a propósito:
- El kernel es
#![no_std] #![no_main]y define su propio_start. Si fuese miembro del workspace,cargo buildintentaría compilarlo para el anfitrión y fallaría por un símbolo_startduplicado con elcrt0del sistema. - Por eso el kernel se construye solo como dependencia de artefacto
(RFC 3028) de
boot, que le fija el targetx86_64-unknown-none. - Las apps WASM tienen su propio target (
wasm32-unknown-unknown) y se compilan aparte.
El kernel usa el target nativo precompilado x86_64-unknown-none: sin
target JSON propio, sin build-std. Soft-float y sin SSE, para que las
interrupciones no corrompan registros de punto flotante.
4. Subsistemas del kernel
grafico — el sustrato visual
Color (RGB de 24 bits, independiente del hardware), Pantalla (el
framebuffer GOP físico, envuelto en seguridad) y Lienzo (el búfer intermedio
en RAM). Toda composición ocurre en el Lienzo; Pantalla::presentar lo
vuelca de un solo gesto con escrituras volátiles — doble búfer, sin
desgarros. codificar traduce un Color al formato nativo del framebuffer.
consola — la superficie de texto e imagen
Une Lienzo + Pantalla + una pluma de escritura. Rasteriza glifos con
fontdue y los funde sobre el lienzo mezclando por cobertura (anti-aliasing).
También vuelca fotogramas crudos del userspace WASM. Es global, tras un Mutex.
baliza — la red de seguridad visual
Publica de forma atómica y sin cerrojos los datos mínimos del framebuffer. Los
manejadores #[panic_handler] y #[alloc_error_handler] los usan para pintar
una franja de advertencia —roja si el sistema colapsa, naranja si el
heap se agota— escribiendo directo sobre el silicio, sin confiar en el heap ni
en estructura dinámica alguna.
gdt — cimientos del manejo de fallos
GDT propia con segmentos de código y datos del kernel, y un TSS cuyo único cometido es alojar un stack de emergencia (IST) para el doble fallo: ni un desbordamiento de la pila del kernel impide su diagnóstico.
interrupts — la tabla de reflejos
IDT con manejadores de excepción de CPU (breakpoint recuperable; el resto,
fatales → panic!) e interrupciones de hardware. El doble fallo se atiende
sobre el stack de emergencia del TSS.
pic — el latido del hardware
Remapea el par 8259 (PIC) fuera del rango de las excepciones de CPU y programa
el temporizador de intervalos (PIT). El teclado (IRQ1) deposita scancodes en
una cola lock-free. desenmascarar abre una línea de IRQ concreta —la del
disco, descubierta en tiempo de ejecución (Fase 6.2)—.
drivers — el hardware que el kernel conquista (Fases 6.1, 6.2)
A diferencia del framebuffer o el temporizador —que el firmware sirve en bandeja—, el disco hay que DESCUBRIRLO y reclamarlo.
pci—CamPuertos: acceso al espacio de configuración del bus PCI por el mecanismo #1 (puertos0xCF8/0xCFC);linea_irqlee la IRQ del dispositivo.disco— el disco virtio-blk. Un asignador de marcos por mapa de bits —con liberación real— reparte páginas físicas para el DMA;KernelHalimplementa eltrait Haldevirtio-drivers(traducción de direcciones, memoria rebote para el DMA); elVirtIOBlkse monta una vez y persiste tras unMutex. La E/S de bloques es asíncrona (Fase 6.2):EsperaDiscoes unFutureque envía la petición por la API no bloqueante devirtio-drivers, cede la CPU y se reanuda con la IRQ del disco (atender_irq).bloquear_enconduce eseFuturedesde los contextos síncronos durmiendo la CPU conhlt; sobre él,leer_sectores/escribir_sectoressirven al grafo de objetos. La IRQ del disco se enruta por el PIC 8259, no por el IOAPIC.
almacen — el grafo de objetos direccionado por contenido (Fase 6.1c)
renaser no tiene un sistema de archivos plano POSIX: tiene un DAG de objetos.
Un Objeto es una carga útil de bytes y una lista de aristas (hashes de
hijos). La identidad de un objeto es el hash BLAKE3 de su forma serializada
(postcard) — de ahí integridad (un objeto se verifica al leerlo) y
deduplicación (contenido idéntico, un solo registro). El disco es un log:
el sector 0 es el superbloque (magia, versión, cursor, raíz); tras él se anexan
los registros de objetos. Un índice hash→sector se reconstruye al arrancar
recorriendo el log. Las capacidades sys_object_* exponen el grafo al
userspace.
memory — el heap dinámico
linked_list_allocator como #[global_allocator] sobre una región estática de
64 MiB en .bss. Desbloquea alloc::* — Box, Vec, BTreeMap, Arc.
async_system — el reactor cooperativo
task—Task: unFutureanclado (Pin<Box<dyn Future>>) conTaskId.executor— elExecutor: censo de tareas, cola de listas, y unhltcontrolado cuando no hay trabajo.waker— unWakerque reinyecta elTaskIden la cola al despertar.teclado— los canales de scancodes. Cada app abre el suyo; la IRQ1 difunde cada scancode a todos, de modo que varias apps reciben la entrada en paralelo.reloj— convierte la IRQ0 (PIT, 100 Hz) en elFutureEsperaFrame, que se resuelve en el siguiente pulso. Es el compás de los fotogramas: una tarea WASM hace su trabajo de un fotograma y.await-ea el siguiente.
Las interrupciones de hardware no conmutan el contexto de la CPU: despiertan tareas. El kernel avanza cooperativamente.
texto — tipografía vectorial
Empotra un .ttf en el binario (include_bytes!) y lo rasteriza con fontdue
glifo a glifo, bajo demanda.
wasm — el escudo de aislamiento
mod— el runtime y laAplicacionWasm: una instancia persistente entre fotogramas (Store+TypedFunc<(), ()>+ región). El ABI del userspace esinit()(una vez) ytick()(un fotograma, y retorna). Dos guardarraíles acotan a cada app: el temporal —un presupuesto de combustible (fuel) portick; agotarlo la desaloja (baliza púrpura)— y el espacial —un techo de memoria lineal víaStore::limiter; rebasarlo la desaloja (baliza amarilla)—. En ambos casoswasmilanza una trampa, el kernel recupera el mando y el sistema no sufre. ElDropdeAplicacionWasmreconcilia el ciclo de vida: da de baja su canal de teclado.env— la matriz de capacidades: las funciones de host que el módulo WASM puede invocar. Hoy son siete:sys_render_frame(ptr, len)— compone un fotograma dentro de la región de pantalla asignada a la app. El kernel valida matemáticamente que[ptr, ptr+len)cae dentro de la memoria lineal del módulo, y que el tamaño es el de la región, antes de leer un byte; si no, aborta la app.sys_get_scancode()— entrega, sin bloquear, el siguiente scancode del canal de teclado propio de la app.sys_object_put/sys_object_datos/sys_object_hijo/sys_object_raiz/sys_object_fijar_raiz— el acceso al grafo de objetos persistente (veralmacen): grabar un objeto, leer su carga útil, recorrer sus aristas, y leer o fijar la raíz del DAG. Cada puntero que la app entrega se valida contra su memoria lineal, igual que ensys_render_frame.
Todo puntero inválido aborta la app —es su culpa: el Error se traduce en una
trampa de WASM, la app se desaloja y el resto del sistema sigue—. Un fallo del
almacenamiento, en cambio, no es culpa de la app: se le devuelve un código de
error que ella decide cómo afrontar.
5. Restricciones de ingeniería
- Escrituras volátiles obligatorias para framebuffer y MMIO.
unsafeconfinado en células mínimas, cada una con un contratoSEGURIDAD:y envuelta en una abstracción segura.unsafe_op_in_unsafe_fnestá endeny.- Alineación: 16 bytes para estructuras genéricas; 4096 (página) para buffers de asignador y el lienzo de respaldo.
no_stdestricto:core+alloc; nada destd.