diff --git a/HANDOFF-nvidia-mirada.md b/HANDOFF-nvidia-mirada.md index e7b8e20f..7de41539 100644 --- a/HANDOFF-nvidia-mirada.md +++ b/HANDOFF-nvidia-mirada.md @@ -25,3 +25,37 @@ `hammer --store ./store hydrate b3:fded43c0… ` (o copialo de `store/fded43c0…-linux-generic/boot/bzImage`). Reconstruible: `hammer build recipes/linux-generic.toml` (deps flex/bison/m4/openssl/elfutils + zig-0.13, ya en el worker). Dudas del kernel (drivers a agregar, cmdline, otra config) → pedímelas y reviso `linux-generic.toml`. + +## 📥 Telemetría persistente en el propio pendrive (2026-07-14) + +**El problema:** el rootfs de esta imagen es un **initramfs = RAM pura**. Los logs iban a `/run` (tmpfs): +al apagar la máquina ajena no sobrevivía **nada**. Y la GPU a probar está lejos — un viaje sin datos es +un viaje perdido. + +**La solución:** la imagen ahora trae una **2da partición FAT32 `MIRADALOG`** (512M, `DATA_MB` en +`scripts/metal-usb-sdboot.sh`, que ganó soporte genérico de partición de datos). FAT32 a propósito: el +pendrive se lee después **desde cualquier SO** (Windows/Mac/Linux) sin herramientas. + +`/sbin/init` la monta por `findfs LABEL=MIRADALOG` con **`-o sync`** (cada escritura va al medio: un +cuelgue duro de la GPU o un corte de luz no se lleva los logs) y vuelca todo en `run-NNNN/` +(numerada: cada arranque/reintento tiene su carpeta): + +| fichero | qué trae | +|---|---| +| `00-resumen.txt` | modo (hw/sw), cmdline, GPU+driver, DRM, si la telemetría persiste | +| `01-hardware.txt` | uname, cpu, RAM, **PCI vía sysfs** (vendor/device/class/**driver**), módulos, /dev/dri, nouveau sysfs, input, firmware nvidia presente | +| `02-pantallas.txt` | por conector: `status`/`modes`/`enabled` | +| `03-dmesg-early.txt` | dmesg **antes** de mirada → si nouveau bindeó y si el firmware gp106 cargó | +| `04-seatd.log` | seatd (DRM master / sesión) | +| `05-mirada.log` | compositor + greeter, con `RUST_LOG=wgpu_core=debug,wgpu_hal=debug` + `EGL_LOG_LEVEL=debug` + `LIBGL_DEBUG=verbose` ⇒ **por qué wgpu eligió el backend y si hay float16** | +| `06-dmesg-final.txt` | dmesg **después** + exit code → cuelgues/oops/reset de nouveau | +| `07-estado-final.txt`| procesos, RAM, /dev/dri al final | + +**GOTCHA:** el busybox de Alpine **no trae el applet `lspci`** (sí `findfs`/`blkid`). El dump de PCI se +hace leyendo `/sys/bus/pci/devices/*/{vendor,device,class}` + `readlink driver` — más soberano igual. +`vendor 0x10de` = NVIDIA; `class 0x0300*` = VGA. + +**En la máquina ajena:** arranca solo. Si el compositor termina/falla, cae a un shell de rescate con la +telemetría ya sincronizada; `relanzar` reintenta y crea un `run-NNNN` nuevo. Se puede apagar sin ceremonia. + +**Al volver:** montar la partición `MIRADALOG` y leer `run-NNNN/`. diff --git a/recipes/mirada-compositor.toml b/recipes/mirada-compositor.toml index c596f69f..66dd166f 100644 --- a/recipes/mirada-compositor.toml +++ b/recipes/mirada-compositor.toml @@ -2,7 +2,7 @@ # maneja DRM/GBM/EGL/libseat/libinput directo y dentro del cual corre `mirada-greeter` como cliente. # Cierra la cadena de sesión gráfica de tawasuyu. # -# Receta Cargo (patrón arje-zero/mirada-greeter): monorepo tawasuyu al commit fijado 9967b02c (reusa +# Receta Cargo (patrón arje-zero/mirada-greeter): monorepo tawasuyu al commit fijado 9a17fefc (reusa # el árbol vendoreado). `-p mirada-compositor`, link DINÁMICO (smithay enlaza libdrm/gbm/seat/input # + dlopen de EGL/wayland/xkbcommon). # @@ -17,7 +17,7 @@ version = "0.0.1" [source] repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git" -commit = "9967b02cf597df6d065edbad8d6669b5653d4928" +commit = "9a17fefcbf63ba74f45cfabc4e608e391e397b17" [build] compiler = "zig-cc" diff --git a/recipes/mirada-ctl.toml b/recipes/mirada-ctl.toml index 313686a1..3c4d6ed1 100644 --- a/recipes/mirada-ctl.toml +++ b/recipes/mirada-ctl.toml @@ -1,7 +1,7 @@ # mirada-ctl — control del compositor mirada por línea de comandos (estilo swaymsg/hyprctl: dispara # acciones de escritorio). Del monorepo tawasuyu. Etapa G: poblar el catálogo con apps propias. # -# Receta Cargo (patrón arje-zero/dominium-cli): source = monorepo tawasuyu a commit fijado 9967b02c +# Receta Cargo (patrón arje-zero/dominium-cli): source = monorepo tawasuyu a commit fijado 9a17fefc # (Cargo.lock committeado => build --locked reproducible), `-p mirada-ctl`, estático zig-cc. bin==package. # Es el CLIENTE de control (IPC), no el compositor GPU ⇒ static-musl sano. Comparte el commit => reusa # el árbol fuente fetcheado. @@ -11,7 +11,7 @@ version = "0.0.1" [source] repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git" -commit = "9967b02cf597df6d065edbad8d6669b5653d4928" +commit = "9a17fefcbf63ba74f45cfabc4e608e391e397b17" [build] compiler = "zig-cc" diff --git a/recipes/mirada-greeter.toml b/recipes/mirada-greeter.toml index 42e46ceb..fdcfc60f 100644 --- a/recipes/mirada-greeter.toml +++ b/recipes/mirada-greeter.toml @@ -4,7 +4,7 @@ # Vulkan). Ver docs/14-mesa-stack.md §«Lado tawasuyu». # # Receta Cargo (patrón arje-zero/mirada-ctl): fuente = monorepo tawasuyu al MISMO commit fijado -# 9967b02c ⇒ reusa el árbol fetcheado y vendoreado (cargo vendor vendorea TODO el Cargo.lock del +# 9a17fefc ⇒ reusa el árbol fetcheado y vendoreado (cargo vendor vendorea TODO el Cargo.lock del # workspace, así que wgpu/winit/naga ya están). `-p mirada-greeter`, bin == package. # # link = DYNAMIC (a diferencia de arje-zero estático): wgpu/winit hacen dlopen de libEGL/libGLESv2/ @@ -16,7 +16,7 @@ version = "0.0.1" [source] repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git" -commit = "9967b02cf597df6d065edbad8d6669b5653d4928" +commit = "9a17fefcbf63ba74f45cfabc4e608e391e397b17" [build] compiler = "zig-cc" diff --git a/scripts/kde/metal-desktop-image.sh b/scripts/kde/metal-desktop-image.sh new file mode 100755 index 00000000..bd3b0836 --- /dev/null +++ b/scripts/kde/metal-desktop-image.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# metal-desktop-image.sh — arma la IMAGEN DE DISCO EFI con el escritorio KDE completo, para METAL. +# +# Funde dos rootfs y delega el particionado en scripts/install-image-efi.sh (ADR 0010 paso 5: EFI-stub +# soberano, initrd chico de pivote → switch_root a la ext4 real ⇒ el sistema NO vive en RAM, que es lo que +# hace inviable el camino de metal-usb-sdboot.sh con un escritorio de ~7 GB). +# +# work/metal-rootfs base metal: arje-zero PID1 + busybox + firmware (i915 tgl_* + iwlwifi AX201) +# work/kde-metal-rootfs KDE hidratado del store sellado (206 pkgs, cierre runtime completo) +# → work/metal-desktop-rootfs (hardlinks, NO copia: no muta ninguno de los dos) +# → work/hammer-kde-metal.img GPT: ESP(bzImage EFI-stub + initrd pivote) + ext4 / + /store + /var/lib/hammer +# +# Uso: scripts/kde/metal-desktop-image.sh +# BOOT=1 KVM=1 scripts/kde/metal-desktop-image.sh # + arranca en OVMF para validar antes de quemar +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT" + +BASE="${BASE:-work/metal-rootfs}" +KDE="${KDE:-work/kde-metal-rootfs}" +MERGED="${MERGED:-work/metal-desktop-rootfs}" +IMG="${IMG:-work/hammer-kde-metal.img}" + +[ -d "$BASE" ] || { echo "falta $BASE (scripts/metal-iso.sh lo arma)" >&2; exit 1; } +[ -d "$KDE" ] || { echo "falta $KDE (hidratá con scripts/kde/hydrate-recipes.py en el worker y bajalo)" >&2; exit 1; } + +echo "==> fundiendo rootfs por hardlinks (no muta los originales)" +# Los dos árboles son COMPLEMENTARIOS, no rivales: +# base → musl libc + loader + busybox + arje-zero + firmware (el "sustrato soberano") +# KDE → Qt/KF6/Plasma/apps (complete-closure.sh NO hidrata la libc: +# "los sonames del sustrato base los provee la base del sistema destino") +# Se pone la base primero y KDE encima; en los pocos nombres que coincidan gana KDE. +rm -rf "$MERGED" +cp -al "$BASE" "$MERGED" +cp -al --remove-destination "$KDE"/. "$MERGED"/ + +echo "==> instalando /usr/bin/plasma-start" +install -Dm755 scripts/kde/plasma-start-metal.sh "$MERGED/usr/bin/plasma-start" + +# El escritorio necesita estos dirs runtime; el rootfs es de sólo-lectura hasta que switch_root monta la ext4. +mkdir -p "$MERGED/root/.config" "$MERGED/root/.cache" "$MERGED/run/user/0" "$MERGED/tmp" +chmod 1777 "$MERGED/tmp" + +# motd: que el usuario sepa qué correr al llegar al shell. +cat > "$MERGED/etc/motd" <<'MOTD' + + #-- hammer :: escritorio KDE Plasma 6 (metal) ------------------------------ + Todo construido desde fuente con hammer (musl + zig-cc), sin binarios ajenos. + + Arrancar el escritorio: plasma-start + Logs si algo falla: /tmp/kwin.log /tmp/plasmashell.log + Diagnóstico GPU: dmesg | grep -iE 'i915|drm' + --------------------------------------------------------------------------- + +MOTD + +echo "==> rootfs fundido: $(du -sh "$MERGED" | cut -f1) ($(find "$MERGED" -name '*.so*' | wc -l) .so, $(ls "$MERGED"/usr/bin | wc -l) bins)" + +# La ext4 de / debe entrar el rootfs + holgura. Se calcula del tamaño real y se redondea hacia arriba. +need_mb=$(du -sm "$MERGED" | cut -f1) +ROOT_SIZE="${ROOT_SIZE:-$(( need_mb + 1536 ))}" +echo "==> ROOT_SIZE=${ROOT_SIZE} MiB (rootfs ${need_mb} MiB + holgura)" + +export ROOTFS="$MERGED" IMG ROOT_SIZE +export ESP_MB="${ESP_MB:-128}" STORE_SIZE="${STORE_SIZE:-512}" STATE_SIZE="${STATE_SIZE:-768}" +exec ./scripts/install-image-efi.sh diff --git a/scripts/kde/plasma-start-metal.sh b/scripts/kde/plasma-start-metal.sh new file mode 100755 index 00000000..8eea1d9c --- /dev/null +++ b/scripts/kde/plasma-start-metal.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# plasma-start — arranca la sesión Plasma en METAL (se instala como /usr/bin/plasma-start en el rootfs). +# +# Derivado de scripts/kde/run-plasma-headless.sh (la sesión VALIDADA headless en el worker), con dos +# cambios para hardware real: +# - kwin_wayland SIN `--virtual`: usa el backend DRM real (/dev/dri/card0, i915 built-in del kernel metal). +# - SIN los overrides de software (swrast/LIBGL_ALWAYS_SOFTWARE/QT_QUICK_BACKEND=software): en la +# TigerLake el driver es **iris** (mesa hidratado trae /usr/lib/dri/iris_dri.so). +# +# NO se autoarranca desde el seed card de arje-zero a propósito: en un bringup, si Plasma falla querés el +# shell de la console-getty para leer los logs, no una pantalla negra. Se lanza a mano desde ese shell. +# +# Logs: /tmp/{kwin,kamd,plasmashell}.log Salir: Ctrl-C (mata la sesión) +set -u + +export LD_LIBRARY_PATH=/usr/lib64:/usr/lib/qt6:/usr/lib:/lib +export QT_PLUGIN_PATH=/usr/lib64/qt6/plugins:/usr/lib/qt6/plugins +export QML2_IMPORT_PATH=/usr/lib64/qt6/qml:/usr/lib/qt6/qml +export QML_IMPORT_PATH=$QML2_IMPORT_PATH +export XDG_DATA_DIRS=/usr/share +export XDG_RUNTIME_DIR=/run/user/0 +export XDG_CONFIG_HOME=/root/.config +export XDG_CACHE_HOME=/root/.cache +export HOME=/root +export LIBGL_DRIVERS_PATH=/usr/lib/dri +export QT_QPA_PLATFORM=wayland + +mkdir -p "$XDG_RUNTIME_DIR" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" /root +chmod 700 "$XDG_RUNTIME_DIR" + +echo "== hammer :: sesión Plasma (metal) ==" +echo "-- GPU: $(ls /dev/dri/ 2>/dev/null | tr '\n' ' ')" +[ -e /dev/dri/card0 ] || echo " !! no hay /dev/dri/card0 — ¿i915 no cargó? (dmesg | grep i915)" +echo "-- input: $(ls /dev/input/ 2>/dev/null | tr '\n' ' ')" + +# D-Bus de sesión: kwin/plasmashell lo exigen. +if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then + DBUS_SESSION_BUS_ADDRESS=$(dbus-daemon --session --fork --print-address 2>/dev/null) + export DBUS_SESSION_BUS_ADDRESS +fi +echo "-- dbus: ${DBUS_SESSION_BUS_ADDRESS:-NO ARRANCÓ}" + +# Compositor sobre DRM real. +echo "-- lanzando kwin_wayland (DRM)…" +/usr/bin/kwin_wayland >/tmp/kwin.log 2>&1 & +KWIN=$! +i=0 +while [ $i -lt 40 ]; do + [ -S "$XDG_RUNTIME_DIR/wayland-0" ] && break + kill -0 $KWIN 2>/dev/null || { echo " !! kwin murió:"; tail -25 /tmp/kwin.log; exit 1; } + i=$((i+1)); sleep 0.5 +done +if [ -S "$XDG_RUNTIME_DIR/wayland-0" ]; then + echo " compositor OK (wayland-0)" +else + echo " !! kwin no expuso wayland-0:"; tail -25 /tmp/kwin.log; exit 1 +fi +export WAYLAND_DISPLAY=wayland-0 + +# kactivitymanagerd: plasmashell ABORTA si no corre (registra su servicio D-Bus). +KAMD=$(ls /usr/lib*/libexec/kactivitymanagerd 2>/dev/null | head -1) +if [ -n "$KAMD" ]; then "$KAMD" >/tmp/kamd.log 2>&1 & sleep 2; echo "-- kactivitymanagerd lanzado"; fi + +echo "-- lanzando plasmashell…" +/usr/bin/plasmashell >/tmp/plasmashell.log 2>&1 & +sleep 8 +echo "-- procesos: $(ps axo comm 2>/dev/null | grep -E 'kwin|plasma' | sort -u | tr '\n' ' ')" +echo +echo "Escritorio arriba. Logs en /tmp/{kwin,kamd,plasmashell}.log" +echo "Apps: konsole, dolphin, systemsettings, spectacle, okular… (lanzalas desde otra tty o krunner)" +echo "Ctrl-C para terminar la sesión." +wait $KWIN diff --git a/scripts/metal-usb-sdboot.sh b/scripts/metal-usb-sdboot.sh index 9ce82220..d04ab063 100755 --- a/scripts/metal-usb-sdboot.sh +++ b/scripts/metal-usb-sdboot.sh @@ -73,13 +73,34 @@ echo "==> ESP poblada ($(du -h "$ESP" | cut -f1)):" # 4) imagen de disco GPT: GPT primaria (1MiB) + ESP (en sector 2048) + GPT backup esp_sectors=$(( espkb * 2 )) # KiB→sectores de 512 -rm -f "$IMG"; truncate -s "$(( (2048 + esp_sectors + 2048) * 512 ))" "$IMG" -echo "label: gpt -start=2048, size=$esp_sectors, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=\"EFI System Partition\"" | sfdisk --quiet "$IMG" + +# Partición de DATOS opcional (DATA_MB>0): FAT32 con etiqueta, para que el sistema live escriba ahí lo +# que deba SOBREVIVIR al apagado (telemetría/logs). El rootfs de esta imagen es un initramfs = RAM pura: +# sin esta partición NO queda rastro de nada al cortar la luz. FAT32 (no ext4) a propósito: el pendrive +# se lee después desde CUALQUIER máquina (Windows/Mac/Linux) sin herramientas. +DATA_MB="${DATA_MB:-0}" +DATA_LABEL="${DATA_LABEL:-HAMMERLOG}" +data_sectors=0 +if [ "$DATA_MB" -gt 0 ]; then + DATA="$WORK/data.img"; rm -f "$DATA"; truncate -s "$(( DATA_MB * 1024 * 1024 ))" "$DATA" + "$MT/mformat" -F -v "$DATA_LABEL" -i "$DATA" :: + data_sectors=$(( DATA_MB * 2048 )) + echo "==> partición de datos FAT32 ${DATA_MB}M etiqueta=$DATA_LABEL (telemetría persistente)" +fi + +rm -f "$IMG"; truncate -s "$(( (2048 + esp_sectors + data_sectors + 2048) * 512 ))" "$IMG" +{ + echo "label: gpt" + echo "start=2048, size=$esp_sectors, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=\"EFI System Partition\"" + [ "$data_sectors" -gt 0 ] && \ + echo "start=$(( 2048 + esp_sectors )), size=$data_sectors, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name=\"$DATA_LABEL\"" +} | sfdisk --quiet "$IMG" dd if="$ESP" of="$IMG" bs=512 seek=2048 conv=notrunc status=none +[ "$data_sectors" -gt 0 ] && dd if="$DATA" of="$IMG" bs=512 seek=$(( 2048 + esp_sectors )) conv=notrunc status=none echo echo "✓ USB metal (systemd-boot): $IMG ($(du -h "$IMG" | cut -f1))" +[ "$data_sectors" -gt 0 ] && echo " + partición $DATA_LABEL (FAT32 ${DATA_MB}M) para telemetría — legible en cualquier SO" echo " Quemar: sudo dd if=$IMG of=/dev/sdX bs=4M oflag=sync status=progress" echo " Bootear: el menú de systemd-boot aparece; ENTER arranca. Tecla 'e' = EDITAR la cmdline en vivo." echo " Secure Boot OFF. WiFi (en consola): wifi-connect \"SSID\" \"CLAVE\"" diff --git a/scripts/mirada-usb.sh b/scripts/mirada-usb.sh index f1adbc58..b282905c 100644 --- a/scripts/mirada-usb.sh +++ b/scripts/mirada-usb.sh @@ -61,7 +61,8 @@ done # 2) busybox + applets echo "==> busybox" cp -a "$DEVFS"/bin/busybox "$RFS"/bin/busybox -for a in sh mount umount mkdir ln cp mv rm cat echo sleep ls ps kill chmod chown ip udhcpc dmesg mknod switch_root getty login setsid; do +for a in sh mount umount mkdir ln cp mv rm cat echo sleep ls ps kill chmod chown ip udhcpc dmesg mknod switch_root getty login setsid \ + findfs blkid sync tee date uname free df head tail grep sed awk cut tr wc find md5sum dd stat readlink basename; do ln -sf busybox "$RFS/bin/$a" done ln -sf /bin/busybox "$RFS/sbin/init.busybox" @@ -195,7 +196,9 @@ fi echo "==> lanzador /sbin/init" cat > "$RFS/sbin/init" <<'INIT' #!/bin/sh -# init de la imagen live de mirada (software/swrast). Arranca seatd y el compositor en modo greeter. +# init de la imagen live de mirada. Arranca seatd + el compositor en modo greeter, y — lo importante para +# probar en una GPU AJENA — vuelca TODA la telemetría a la partición FAT32 del propio pendrive, para +# traerlo de vuelta con la información. El rootfs es un initramfs (RAM): sin esto no sobrevive NADA. export PATH=/usr/bin:/bin:/usr/sbin:/sbin /bin/busybox mount -t proc proc /proc 2>/dev/null || true /bin/busybox mount -t sysfs sys /sys 2>/dev/null || true @@ -205,6 +208,77 @@ export PATH=/usr/bin:/bin:/usr/sbin:/sbin /bin/busybox mount -t devpts devpts /dev/pts 2>/dev/null || true /bin/busybox chmod 0700 /run/user/0 +# ---------------------------------------------------------------- telemetría persistente al pendrive +# La partición la crea metal-usb-sdboot.sh (DATA_MB/DATA_LABEL). Se monta con -o sync: cada escritura va +# al medio, así un cuelgue duro de la GPU o un corte de luz no se lleva los logs. +LOG=/telemetry +TELOK=0 +/bin/busybox mkdir -p $LOG +for try in 1 2 3 4 5 6 7 8 9 10; do + DEV=$(/bin/busybox findfs LABEL=MIRADALOG 2>/dev/null) + [ -n "$DEV" ] && break + /bin/busybox sleep 1 # el USB puede tardar en enumerar +done +if [ -n "$DEV" ] && /bin/busybox mount -t vfat -o rw,sync "$DEV" $LOG 2>/dev/null; then + TELOK=1 +else + echo " !! NO pude montar la partición de telemetría (LABEL=MIRADALOG) — los logs quedan sólo en RAM" + LOG=/run +fi + +# Cada arranque en su propia carpeta: run-0001, run-0002… (sin RTC confiable, se numera) +N=1 +while [ -d "$LOG/run-$(printf %04d $N)" ]; do N=$((N+1)); done +RUN="$LOG/run-$(printf %04d $N)" +/bin/busybox mkdir -p "$RUN" +echo " ## telemetría → $RUN (persistente=$TELOK)" + +snap() { # snap + local f="$RUN/$1"; shift; local t="$1"; shift + { echo "===== $t ====="; "$@" 2>&1; echo; } >> "$f" + /bin/busybox sync +} + +# PCI desde sysfs: este busybox NO trae el applet `lspci`. Con vendor/device/class/driver alcanza para +# saber QUÉ GPU hay y, sobre todo, QUÉ DRIVER la bindeó (nouveau vs nada) — que es el dato del viaje. +# vendor 0x10de = NVIDIA · class 0x0300xx = VGA · 0x0302xx = 3D controller +pci_dump() { + for d in /sys/bus/pci/devices/*/; do + [ -r "$d/class" ] || continue + drv=$(/bin/busybox readlink "$d/driver" 2>/dev/null | /bin/busybox sed 's|.*/||') + echo "$(/bin/busybox basename $d) class=$(/bin/busybox cat $d/class) vendor=$(/bin/busybox cat $d/vendor) device=$(/bin/busybox cat $d/device) driver=${drv:-NINGUNO}" + done +} +gpu_line() { + for d in /sys/bus/pci/devices/*/; do + [ -r "$d/class" ] || continue + case "$(/bin/busybox cat $d/class)" in + 0x0300*|0x0302*) + drv=$(/bin/busybox readlink "$d/driver" 2>/dev/null | /bin/busybox sed 's|.*/||') + echo "$(/bin/busybox basename $d) vendor=$(/bin/busybox cat $d/vendor) device=$(/bin/busybox cat $d/device) driver=${drv:-NINGUNO}" ;; + esac + done +} + +# --- hardware / kernel: qué GPU hay, si nouveau bindeó, si cargó el firmware +snap 01-hardware.txt "uname" /bin/busybox uname -a +snap 01-hardware.txt "cmdline" /bin/busybox cat /proc/cmdline +snap 01-hardware.txt "cpu" /bin/busybox head -20 /proc/cpuinfo +snap 01-hardware.txt "memoria" /bin/busybox free -m +snap 01-hardware.txt "PCI (sysfs; vendor 0x10de=NVIDIA)" pci_dump +snap 01-hardware.txt "modulos" /bin/busybox cat /proc/modules +snap 01-hardware.txt "DRM /dev/dri" /bin/busybox ls -la /dev/dri +snap 01-hardware.txt "DRM /sys" /bin/busybox find /sys/class/drm -maxdepth 1 +snap 01-hardware.txt "nouveau sysfs" /bin/busybox find /sys/module/nouveau -maxdepth 2 +snap 01-hardware.txt "input" /bin/busybox cat /proc/bus/input/devices +snap 01-hardware.txt "firmware nvidia" /bin/busybox find /lib/firmware/nvidia -type f +for c in /sys/class/drm/card*/status /sys/class/drm/card*/modes /sys/class/drm/card*/enabled; do + [ -r "$c" ] && snap 02-pantallas.txt "$c" /bin/busybox cat "$c" +done + +# dmesg TEMPRANO: acá se ve si nouveau bindeó y si el firmware gp106 cargó (o falló). +snap 03-dmesg-early.txt "dmesg (antes de mirada)" /bin/busybox dmesg + export XDG_RUNTIME_DIR=/run/user/0 export LIBGL_DRIVERS_PATH=/usr/lib/dri export LIBSEAT_BACKEND=seatd @@ -214,14 +288,21 @@ export MIRADA_GREETER_BIN=/usr/bin/mirada-greeter export XKB_DEFAULT_LAYOUT=us export XKB_CONFIG_ROOT=/usr/share/X11/xkb -# GPU: por defecto se INTENTA hardware (nouveau, si el firmware GSP lo deja hacer modeset) y, si no, -# mesa cae a swrast/llvmpipe sobre simpledrm solo. Con `mirada.sw` en la cmdline se FUERZA software -# (necesario en la VM virtio-sin-virgl de validación, donde mesa intentaría el driver virtio-3D y -# fallaría). El compositor (smithay/GlesRenderer) corre en ambos; el greeter (wgpu/Vello) NECESITA la -# capacidad de shaders float16 (SHADER_FLOAT16_IN_FLOAT32) que los rasterizadores software -# (llvmpipe/lavapipe) NO dan ⇒ su login sólo pinta con GPU real (nouveau). Ver HANDOFF/README. +# Telemetría MÁXIMA del stack gráfico: por qué wgpu eligió (o no) el backend, y si hay float16. +export RUST_LOG="${RUST_LOG:-info,wgpu_core=debug,wgpu_hal=debug,mirada=debug,smithay=info}" +export RUST_BACKTRACE=full +export EGL_LOG_LEVEL=debug +export MESA_DEBUG=1 +export LIBGL_DEBUG=verbose + +# GPU: por defecto se INTENTA hardware (nouveau, si el firmware deja hacer modeset) y, si no, mesa cae a +# swrast/llvmpipe sobre simpledrm. Con `mirada.sw` en la cmdline se FUERZA software (necesario en la VM +# virtio-sin-virgl de validación). El compositor (smithay/GlesRenderer) corre en ambos; el greeter +# (wgpu/Vello) NECESITA shaders float16 (SHADER_FLOAT16_IN_FLOAT32) que llvmpipe/lavapipe NO dan ⇒ su +# login sólo pinta con GPU real (nouveau). Ver HANDOFF/README. if grep -qw 'mirada.sw' /proc/cmdline 2>/dev/null; then echo " ## modo SOFTWARE forzado (mirada.sw): compositor sí; greeter no (sin float16)" + MODO="software (mirada.sw)" export LIBGL_ALWAYS_SOFTWARE=1 export GALLIUM_DRIVER=llvmpipe export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json @@ -231,24 +312,59 @@ else # por el backend GL de wgpu sobre gallium-nouveau (que sí da unpackHalf2x16 = float16). Forzamos GL y # tapamos lavapipe: si dejáramos Vulkan, wgpu caería a lavapipe (software, sin float16) y fallaría. echo " ## modo HARDWARE (nouveau GL): greeter por gallium-nouveau" + MODO="hardware (nouveau GL)" export WGPU_BACKEND=gl export VK_ICD_FILENAMES=/dev/null fi +{ echo "modo : $MODO"; echo "cmdline : $(/bin/busybox cat /proc/cmdline)"; echo "DRM : $(/bin/busybox ls /dev/dri 2>/dev/null | tr '\n' ' ')"; + echo "GPU (PCI) : $(gpu_line)"; + echo "persistente: $TELOK"; echo "RUST_LOG : $RUST_LOG"; } > "$RUN/00-resumen.txt" +/bin/busybox sync + echo "" echo " ## hammer · mirada live" echo " ## DRM: $(ls /dev/dri 2>/dev/null | tr '\n' ' ')" +echo " ## telemetría: $RUN (persistente=$TELOK)" echo "" # seatd en background (gestiona el DRM master y la sesión sobre la VT). -/usr/bin/seatd -g video >/run/seatd.log 2>&1 & -sleep 1 +/usr/bin/seatd -g video > "$RUN/04-seatd.log" 2>&1 & +/bin/busybox sleep 1 +# El compositor: su salida va A LA VEZ a la pantalla y al pendrive (tee), para verlo y llevárselo. echo "== lanzando mirada-compositor --drm --greeter ==" -/usr/bin/mirada-compositor --drm --greeter 2>&1 | /bin/busybox tee /run/mirada.log +/usr/bin/mirada-compositor --drm --greeter 2>&1 | /bin/busybox tee "$RUN/05-mirada.log" +RC=$? + +# --- post-mortem: lo que pasó DESPUÉS de correr mirada (cuelgues de GPU, oops, reset de nouveau) +snap 06-dmesg-final.txt "dmesg (después de mirada)" /bin/busybox dmesg +snap 06-dmesg-final.txt "rc del compositor" echo "exit=$RC" +snap 07-estado-final.txt "procesos" /bin/busybox ps +snap 07-estado-final.txt "memoria" /bin/busybox free -m +snap 07-estado-final.txt "DRM final" /bin/busybox ls -la /dev/dri +/bin/busybox sync echo "" -echo "== mirada terminó — shell de rescate (logs en /run/mirada.log, /run/seatd.log) ==" +echo "== mirada terminó (exit=$RC) — telemetría VOLCADA en $RUN ==" +[ "$TELOK" = "1" ] && { + echo " Ficheros en el pendrive (partición MIRADALOG):" + /bin/busybox ls -la "$RUN" + echo "" + echo " >> Podés apagar y traer el pendrive: los logs ya están sincronizados al medio." + echo " >> Si querés reintentar antes de apagar, corré: relanzar" +} || echo " !! sin partición de telemetría: los logs están en RAM y se pierden al apagar" +echo "" + +# `relanzar`: reintentar el compositor sin reiniciar; cada intento crea su propio run-NNNN. +cat > /usr/bin/relanzar <<'RL' +#!/bin/sh +echo "relanzando init (nuevo run-NNNN en el pendrive)…" +exec /sbin/init +RL +chmod +x /usr/bin/relanzar + +echo "== shell de rescate (telemetría en $RUN; 'relanzar' para reintentar) ==" exec /bin/sh INIT chmod +x "$RFS/sbin/init" @@ -269,9 +385,15 @@ if [ "$PACKAGE" = "1" ]; then # Default = HARDWARE nouveau (ya horneamos el firmware gp106): nouveau maneja la GTX 1060 y el greeter # pinta por gallium-nouveau GL. Si nouveau diera problemas, en el menú (tecla 'e') agregá # `mirada.sw nouveau.modeset=0` para caer a software (compositor sí, greeter no). + # DATA_MB: partición FAT32 de TELEMETRÍA. El rootfs de esta imagen es un initramfs = RAM pura, así que + # sin esta partición no sobrevive ni un log al apagado — y la GPU a probar está en otra máquina, lejos. + # El init la monta por LABEL=MIRADALOG con -o sync y vuelca ahí todo (ver /sbin/init). + # FAT32 ⇒ el pendrive se lee después desde cualquier SO, sin herramientas. ROOTFS="$RFS" KERNEL="$KGEN" IMG="work/hammer-mirada-usb.img" \ + DATA_MB="${DATA_MB:-512}" DATA_LABEL="MIRADALOG" \ OPTIONS="${CMDLINE:-console=tty0 loglevel=4}" \ scripts/metal-usb-sdboot.sh echo "" echo "✓ imagen: work/hammer-mirada-usb.img" + echo " Al volver, leé la telemetría montando la partición MIRADALOG (FAT32) — carpetas run-NNNN/." fi