diff --git a/scripts/kde/plasma-start-qemu.sh b/scripts/kde/plasma-start-qemu.sh index 6bc9c3e1..f1567a9f 100644 --- a/scripts/kde/plasma-start-qemu.sh +++ b/scripts/kde/plasma-start-qemu.sh @@ -30,6 +30,13 @@ export HOME=/root # --- render por software sobre virtio-gpu --- export LIBGL_ALWAYS_SOFTWARE=1 export GALLIUM_DRIVER=llvmpipe +# GBM_ALWAYS_SOFTWARE=1 — EL FIX del segfault (MURO 2, verificado en fuente mesa 24.0.9). virtio-gpu-pci +# SIN 3D expone un nodo KMS-only (no render-capable). Con MESA_LOADER_DRIVER_OVERRIDE solo, gbm carga +# kms_swrast pero deja gbm_dri->software=FALSE (dri_screen_create tiene éxito ⇒ nunca cae al fallback +# dri_screen_create_sw, el único que setea software=true). Entonces dri2_initialize_drm entra al bloque +# `if(!software)` y llama gbm_dri->mesa->queryCompatibleRenderOnlyDeviceFd() — NULL en el driver software +# ⇒ SIGSEGV. GBM_ALWAYS_SOFTWARE=1 fuerza dri_screen_create_sw ⇒ software=true ⇒ se salta ese bloque. +export GBM_ALWAYS_SOFTWARE=1 # kms_swrast (NO swrast): kwin abre card0 como dispositivo KMS y crea un gbm device sobre él ⇒ necesita # el driver de software para KMS (dumb buffers). Con 'swrast' a secas gbm_create_device falla ("Failed # to create gbm device"). kms_swrast_dri.so está en /usr/lib/dri. @@ -49,6 +56,18 @@ export QT_QPA_PLATFORM=wayland export QT_QPA_PLATFORMTHEME=kde export QT_QPA_FONTDIR=/usr/share/fonts/dejavu +# --- DIAGNÓSTICO del segfault-al-1er-composite (MURO 2) --- +# Sin gdb en la imagen: subimos el logging categorizado de kwin (kwin_core/drm/scene/opengl) + mesa/egl +# para ver EN QUÉ FASE muere (bind EGL, alloc GBM, JIT llvmpipe, o el paint real). DIAG=0 para apagarlo. +if [ "${DIAG:-1}" = 1 ]; then + export QT_LOGGING_RULES="kwin_*=true;qt.qpa.*=true" + export EGL_LOG_LEVEL=debug + export LIBGL_DEBUG=verbose + export MESA_DEBUG=1 + export GALLIUM_HUD= # no HUD, sólo para dejar constancia + export KWIN_DRM_DEBUG=1 +fi + mkdir -p "$XDG_RUNTIME_DIR" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" /run/dbus /root chmod 700 "$XDG_RUNTIME_DIR" [ -s /etc/machine-id ] || cat /proc/sys/kernel/random/uuid 2>/dev/null | tr -d - > /etc/machine-id @@ -76,10 +95,24 @@ if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then fi say "dbus: ${DBUS_SESSION_BUS_ADDRESS:-NO ARRANCO}" +# --- CORE DUMP del segfault (MURO 2): sin gdb en la imagen, sacamos un core y lo leemos con el gdb del +# host apuntando al rootfs fundido. Localiza el frame culpable (libLLVM/llvmpipe vs kwin vs mesa). --- +if [ "${DIAG:-1}" = 1 ]; then + ulimit -c unlimited 2>/dev/null || true + # /core en la RAÍZ ext4 (NO /tmp: es tmpfs=RAM y se pierde al matar QEMU). Tras el crash hacemos sync + # explícito ⇒ el core persiste en la imagen aunque después mate QEMU con SIGKILL. + echo '/core.%e.%p' > /proc/sys/kernel/core_pattern 2>/dev/null || true + say "core dumps ON (pattern=$(cat /proc/sys/kernel/core_pattern 2>/dev/null), ulimit -c=$(ulimit -c))" +fi + # Compositor sobre el DRM de virtio (software EGL/GBM vía kms_swrast). SIN --virtual: presenta al display. say "lanzando kwin_wayland (DRM virtio, software GL)..." /usr/bin/kwin_wayland --drm >/tmp/kwin.log 2>&1 & KWIN=$! +# stream EN VIVO del kwin.log al serial: el volcado post-mortem se trunca porque el getty respawnea y +# pisa el serial ⇒ con tail -f la última línea antes del segfault llega al host pase lo que pase. +( tail -f /tmp/kwin.log 2>/dev/null | sed -u 's/^/kwin> /' > /dev/ttyS0 2>/dev/null ) & +TAILPID=$! i=0 while [ $i -lt 60 ]; do [ -S "$XDG_RUNTIME_DIR/wayland-0" ] && break @@ -104,6 +137,15 @@ say "procesos: $(ps axo comm 2>/dev/null | grep -E 'kwin|plasma' | sort -u | tr say "escritorio arriba (o mira /tmp/plasmashell.log). Ctrl-C mata la sesion." dump /tmp/plasmashell.log wait $KWIN +RC=$? # kwin salió ⇒ volcá su log para saber por qué (backend QPainter, DRM, modeset…) -say "kwin salió (código $?) — volcando kwin.log:" +say "kwin salió (código $RC) — volcando kwin.log:" dump /tmp/kwin.log +# copiar los logs a la ext4 raíz y SYNC ⇒ core + logs persisten en la imagen para leer desde el host +# con debugfs/gdb (el SIGKILL de QEMU no sincroniza; sin este sync se pierde todo lo de esta sesión). +cp /tmp/kwin.log /kwin.log 2>/dev/null || true +cp /tmp/plasmashell.log /plasmashell.log 2>/dev/null || true +say "cores en /: $(ls -la /core.* 2>/dev/null | tr '\n' ' ' || echo NINGUNO)" +sync; sync +say "== disco SYNCED (core+logs en la raíz). serial CONGELADO. matá QEMU desde el host. ==" +sleep 3600 diff --git a/scripts/kde/qemu-desktop-image.sh b/scripts/kde/qemu-desktop-image.sh old mode 100644 new mode 100755 diff --git a/scripts/kde/run-qemu-desktop.sh b/scripts/kde/run-qemu-desktop.sh new file mode 100755 index 00000000..140e586e --- /dev/null +++ b/scripts/kde/run-qemu-desktop.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# run-qemu-desktop.sh — arranca la imagen KDE en QEMU (virtio-gpu + software GL) de forma REPRODUCIBLE. +# Antes era un comando ad-hoc. Por defecto headless (DISPLAY=none) para diagnóstico por serial sin +# interferir con la sesión mirada del laptop; DISP=gtk para ver la ventana (necesita DISPLAY=:0 Xwayland, +# y cada restart de mirada mata la ventana). +# +# scripts/kde/run-qemu-desktop.sh # headless, serial → work/qemu-desktop-serial.log +# DISP=gtk scripts/kde/run-qemu-desktop.sh # ventana gráfica (virtio-gpu por gtk) +# TIMEOUT=90 scripts/kde/run-qemu-desktop.sh # mata QEMU a los 90s (diagnóstico automático) +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT" + +IMG="${IMG:-work/hammer-kde-qemu.img}" +SERIAL="${SERIAL:-work/qemu-desktop-serial.log}" +OVMF_CODE="${OVMF_CODE:-/usr/share/edk2/x64/OVMF_CODE.4m.fd}" +OVMF_VARS_SRC="${OVMF_VARS_SRC:-/usr/share/edk2/x64/OVMF_VARS.4m.fd}" +VARS="${VARS:-work/qemu-desktop-OVMF_VARS.fd}" +DISP="${DISP:-none}" +MEM="${MEM:-4G}" +SMP="${SMP:-4}" + +[ -r "$IMG" ] || { echo "falta $IMG — corré scripts/kde/qemu-desktop-image.sh" >&2; exit 1; } +[ -r "$OVMF_CODE" ] || { echo "falta OVMF_CODE ($OVMF_CODE)" >&2; exit 1; } +# copia escribible de las VARS (pflash necesita rw; la del sistema es read-only) +[ -r "$VARS" ] || cp "$OVMF_VARS_SRC" "$VARS" + +case "$DISP" in + gtk) DISPLAY_ARGS=(-display gtk -device virtio-gpu-pci) ;; + none) DISPLAY_ARGS=(-display none -device virtio-gpu-pci) ;; + *) DISPLAY_ARGS=(-display "$DISP" -device virtio-gpu-pci) ;; +esac + +# serial nuevo cada corrida (el diagnóstico depende de que no se mezcle con boots viejos) +: > "$SERIAL" + +QEMU_ARGS=( + -machine q35 -accel kvm -cpu host + -m "$MEM" -smp "$SMP" + -drive if=pflash,format=raw,unit=0,file="$OVMF_CODE",readonly=on + -drive if=pflash,format=raw,unit=1,file="$VARS" + -drive file="$IMG",format=raw,if=virtio + "${DISPLAY_ARGS[@]}" + -serial "file:$SERIAL" + -no-reboot +) + +echo "==> QEMU (DISP=$DISP, serial=$SERIAL)" +echo " imagen: $IMG" +if [ -n "${TIMEOUT:-}" ]; then + echo " TIMEOUT=${TIMEOUT}s (auto-kill)" + exec timeout --signal=KILL "${TIMEOUT}" qemu-system-x86_64 "${QEMU_ARGS[@]}" +else + exec qemu-system-x86_64 "${QEMU_ARGS[@]}" +fi