tawasuyu

tawasuyu/brahman

Rust 582TOML 222Markdown 83JSON 198635 Definiciones

diag(renaser): trazado por serie del arranque + DMA salta la página 0

Para localizar dónde colapsa el kernel en máquinas que no son la del
autor, cada hito de `kernel_main` deja una traza por COM1 (con el
panic-handler-a-serie de antes, ya tenemos boot trace + autopsia).

- `baliza::Serie` se hace `pub(crate)` para que cualquier módulo deje
  trazas con `writeln!(baliza::Serie, ...)`.
- `kernel_main`: traza tras adoptar el framebuffer, encender la baliza,
  fundar GDT/IDT/PIC, fundar el heap, fundar teclado/reloj/texto,
  publicar la consola, iniciar disco y almacén, arrancar el ratón,
  crear el ejecutor, cargar el userspace y arrancar el reactor. Y un
  volcado de `physical_memory_offset` + `region_dma` al inicio.
- `drivers::disco::init`: registra offset, región, base de la arena y
  número de marcos disponibles.
- Endurecimiento: `disco::init` ahora salta SIEMPRE la primera página
  física al elegir la base de la arena DMA. Algunos cargadores la dejan
  sin mapear como protección NULL; un marco DMA ahí se traduce a una
  dirección que peta al desreferenciar.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

89117f47cc75246d5e14152b97974366c85c19e9 · por sergio · (hace 5 meses) · padre d85bb3819 · ver el árbol en este commit

Delta semántico · 4

renaser/kernel/src/baliza.rs

  • cambió de firma def Serie

renaser/kernel/src/drivers/disco.rs

  • cambió por dentro fn init pub

renaser/kernel/src/main.rs

3 archivos · +47 −3

diff --git a/renaser/kernel/src/baliza.rs b/renaser/kernel/src/baliza.rs
index 5063eb4..036930c 100644
--- a/renaser/kernel/src/baliza.rs
+++ b/renaser/kernel/src/baliza.rs
@@ -43,8 +43,10 @@ fn serie_escribir(byte: u8) {
     }
 }
 
-/// Sumidero de impresion al puerto serie — formatea sin tocar el heap.
-struct Serie;
+/// Sumidero de impresion al puerto serie — formatea sin tocar el heap. Publico
+/// para que cualquier modulo del kernel pueda dejar trazas en COM1 con un
+/// simple `writeln!(crate::baliza::Serie, "...", ...)`.
+pub(crate) struct Serie;
 
 impl Write for Serie {
     fn write_str(&mut self, s: &str) -> core::fmt::Result {
diff --git a/renaser/kernel/src/drivers/disco.rs b/renaser/kernel/src/drivers/disco.rs
index e18f07a..112f0f3 100644
--- a/renaser/kernel/src/drivers/disco.rs
+++ b/renaser/kernel/src/drivers/disco.rs
@@ -131,10 +131,23 @@ static ASIGNADOR: Once<Mutex<AsignadorMarcos>> = Once::new();
 /// el asignador de marcos sobre la region de RAM libre que el cargador reporto.
 /// Una sola vez, antes de montar el disco.
 pub fn init(offset_fisico: u64, region_inicio: u64, region_fin: u64) {
+    use core::fmt::Write;
     OFFSET_FISICO.store(offset_fisico, Ordering::Relaxed);
-    let base = alinear_arriba(region_inicio, PAGINA);
+    // Saltar SIEMPRE la primera pagina fisica: algunos cargadores la dejan sin
+    // mapear como proteccion contra punteros NULL — un marco DMA ahi seria una
+    // bomba en cuanto el driver lo desreferenciase via el mapeo alto.
+    let base = alinear_arriba(region_inicio.max(PAGINA), PAGINA);
     let disponibles = region_fin.saturating_sub(base) / PAGINA;
     let total = (disponibles as usize).min(MAX_MARCOS);
+    let _ = writeln!(
+        crate::baliza::Serie,
+        "disco :: init offset={:#x} region=[{:#x}, {:#x}) base={:#x} marcos={}",
+        offset_fisico,
+        region_inicio,
+        region_fin,
+        base,
+        total,
+    );
     ASIGNADOR.call_once(|| {
         Mutex::new(AsignadorMarcos {
             base,
diff --git a/renaser/kernel/src/main.rs b/renaser/kernel/src/main.rs
index eb85942..bda07c4 100644
--- a/renaser/kernel/src/main.rs
+++ b/renaser/kernel/src/main.rs
@@ -65,6 +65,7 @@ mod wasm;
 pub(crate) use sync::CeldaSync;
 
 use alloc::vec::Vec;
+use core::fmt::Write;
 use core::sync::atomic::{AtomicUsize, Ordering};
 
 use async_system::executor::Executor;
@@ -93,6 +94,13 @@ pub(crate) fn detener() -> ! {
     }
 }
 
+/// Deja una traza por el puerto serie (COM1) — la enruta QEMU a la terminal
+/// donde se ejecuto `cargo run`. Diagnostico barato del arranque: cada hito del
+/// `kernel_main` deja una linea, asi una caida muestra HASTA DONDE llego.
+fn traza(rotulo: &str) {
+    let _ = writeln!(baliza::Serie, "boot :: {rotulo}");
+}
+
 /// FASE 10 :: el molde de una aplicacion para los lanzamientos EN VIVO. Guarda
 /// su bytecode —cacheado en RAM al arrancar, para no volver al disco despues—
 /// y la geometria y la cuota de memoria con que instanciarla.
@@ -391,6 +399,7 @@ fn informar_almacen() {
 // =============================================================================
 
 fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
+    traza("kernel_main entrado");
     // --- 1. Recuperar el framebuffer GOP que el firmware nos confio. ---
     let framebuffer = match boot_info.framebuffer.as_mut() {
         Some(fb) => fb,
@@ -399,11 +408,18 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
     let info: FrameBufferInfo = framebuffer.info();
     let formato: PixelFormat = info.pixel_format;
     let pantalla = Pantalla::adoptar(framebuffer, info);
+    traza("framebuffer adoptado");
 
     // Datos para la sonda de disco (Fase 6.1b): el offset al que el cargador
     // mapeo la memoria fisica y la mayor region de RAM libre para el DMA.
     let offset_fisico = boot_info.physical_memory_offset.into_option();
     let region_dma = mayor_region_usable(&boot_info.memory_regions);
+    let _ = writeln!(
+        baliza::Serie,
+        "boot :: physical_memory_offset={:#x?} region_dma={:#x?}",
+        offset_fisico,
+        region_dma,
+    );
 
     // --- 2. Encender la baliza: la red de seguridad visual va primero. ---
     BALIZA_PANICO.encender(
@@ -411,20 +427,24 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
         codificar(formato, Color::ALERTA),
         codificar(formato, Color::OOM),
     );
+    traza("baliza encendida");
 
     // --- 3. Cimientos de fallos e interrupciones (Fases 2.0 y 2.1). ---
     gdt::init();
     interrupts::init();
     pic::init();
+    traza("gdt + idt + pic");
 
     // --- 4. FASE 3 :: fundar el heap. A partir de aqui, `alloc` esta vivo. ---
     memory::init();
+    traza("heap fundado");
 
     // --- 5. Con el heap activo, fundar lo que depende de el: el canal de
     //        scancodes, el reloj de fotogramas y la tipografia vectorial. ---
     async_system::teclado::init();
     async_system::reloj::init();
     texto::init();
+    traza("teclado + reloj + texto");
 
     // --- 6. Construir el lienzo y la consola; pintar el rotulo inicial,
     //        ya rasterizado por fontdue, y publicar la consola globalmente. ---
@@ -441,6 +461,7 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
     consola.escribir("renaser :: fase 6.2 -- E/S de disco asincrona por interrupcion\n");
     consola.presentar();
     CONSOLA.call_once(|| Mutex::new(consola));
+    traza("consola publicada");
 
     // --- 6.5. FASE 6.1c :: fundar el subsistema de disco y, sobre el, el grafo
     //          de objetos: enumerar el bus PCI, montar el transporte virtio-blk,
@@ -448,8 +469,11 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
     //          contenido. El kernel adquiere, por fin, una memoria que perdura. ---
     match (offset_fisico, region_dma) {
         (Some(offset), Some((inicio, fin))) => {
+            traza("disco :: init");
             drivers::disco::init(offset, inicio, fin);
+            traza("almacen :: init");
             informar_almacen();
+            traza("almacen :: listo");
         }
         _ => {
             if let Some(consola) = CONSOLA.get() {
@@ -457,6 +481,7 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
                 consola.escribir("virtio-blk :: omitido -- memoria fisica sin mapear\n");
                 consola.presentar();
             }
+            traza("disco :: OMITIDO (sin offset/region)");
         }
     }
 
@@ -465,6 +490,7 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
     //          desenmascara su IRQ12. Desde aqui hay un puntero en pantalla,
     //          y los clics pueden alcanzar al compositor.
     drivers::raton::init(ancho_lienzo, alto_lienzo);
+    traza("raton :: listo");
 
     // --- 7. FASE 7 :: levantar el reactor y poblar el userspace DESDE EL
     //        GRAFO. El kernel ya no empotra los modulos WASM: lee el
@@ -478,11 +504,14 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
     //        compas de los fotogramas y la IRQ del teclado difundira cada
     //        scancode a los canales que las apps consultan. ---
     let mut ejecutor = Executor::nuevo();
+    traza("ejecutor :: creado");
     cargar_userspace(&mut ejecutor, ancho_lienzo, alto_lienzo);
+    traza("userspace :: cargado");
     // FASE 6.2 :: una tarea mas del reactor — no una app WASM— que sondea el
     // disco de forma ASINCRONA: la demostracion de que la IRQ del disco
     // conduce la E/S sin detener a las aplicaciones visuales.
     ejecutor.spawn(tarea_sonda_disco());
+    traza("ejecutor :: arrancando reactor");
     x86_64::instructions::interrupts::enable();
     ejecutor.run();
 }