sergio/takana
> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
kde/qemu: un solo output virtio (KWIN_DRM_DEVICES) — mata el negro-tras-pintar
1#!/bin/sh
2# plasma-start-qemu.sh — arranca Plasma en una VM QEMU con render por SOFTWARE (kms_swrast/llvmpipe)
3# sobre el DRM de virtio-gpu (/dev/dri/card0). Derivado de plasma-start-metal.sh pero SIN hardware iris:
4# en QEMU no hay GPU real, así que kwin presenta por el DRM de virtio con EGL/GBM de software.
5#
6# Se instala como /usr/bin/plasma-start en la imagen QEMU y lo AUTO-LANZA /etc/profile (console-getty
7# autologin). Trae los arreglos de la campaña KDE 2026-07: QT_QUICK_BACKEND=software (plasmashell no crea
8# contexto GL sin él), QT_QPA_FONTDIR (mata los tofu; qtbase se construyó sin fontconfig), kdeglobals +
9# QT_QPA_PLATFORMTHEME=kde (iconos + estilo Breeze), kactivitymanagerd (plasmashell aborta sin él).
10#
11# Logs: /tmp/{kwin,kamd,plasmashell}.log + tee a /dev/console. Salir: matar kwin.
12set -u
13# getty ejecuta este script DIRECTO (no vía login shell) ⇒ PATH viene vacío: mkdir/tr/cat/dbus-daemon
14# no se hallan y kwin nunca levanta. Seteamos PATH explícito (busybox + userland KDE) ANTES de todo.
15export PATH=/usr/bin:/bin:/usr/sbin:/sbin
16# tee a la consola gráfica (tty0) Y al serial (ttyS0) — el host captura ttyS0 con -serial file:
17say() { echo "== plasma-qemu :: $*" | tee -a /dev/console /dev/ttyS0 2>/dev/null; }
18dump() { echo "---- $1 ----" > /dev/ttyS0 2>/dev/null; cat "$1" > /dev/ttyS0 2>/dev/null; }
19
20export LD_LIBRARY_PATH=/usr/lib64:/usr/lib/qt6:/usr/lib:/lib
21export QT_PLUGIN_PATH=/usr/lib64/qt6/plugins:/usr/lib/qt6/plugins
22export QML2_IMPORT_PATH=/usr/lib64/qt6/qml:/usr/lib/qt6/qml
23export QML_IMPORT_PATH=$QML2_IMPORT_PATH
24export XDG_DATA_DIRS=/usr/share
25export XDG_RUNTIME_DIR=/run/user/0
26export XDG_CONFIG_HOME=/root/.config
27export XDG_CACHE_HOME=/root/.cache
28export HOME=/root
29
30# --- render por software sobre virtio-gpu ---
31export LIBGL_ALWAYS_SOFTWARE=1
32export GALLIUM_DRIVER=llvmpipe
33# GBM_ALWAYS_SOFTWARE=1 — EL FIX del segfault (MURO 2, verificado en fuente mesa 24.0.9). virtio-gpu-pci
34# SIN 3D expone un nodo KMS-only (no render-capable). Con MESA_LOADER_DRIVER_OVERRIDE solo, gbm carga
35# kms_swrast pero deja gbm_dri->software=FALSE (dri_screen_create tiene éxito ⇒ nunca cae al fallback
36# dri_screen_create_sw, el único que setea software=true). Entonces dri2_initialize_drm entra al bloque
37# `if(!software)` y llama gbm_dri->mesa->queryCompatibleRenderOnlyDeviceFd() — NULL en el driver software
38# ⇒ SIGSEGV. GBM_ALWAYS_SOFTWARE=1 fuerza dri_screen_create_sw ⇒ software=true ⇒ se salta ese bloque.
39export GBM_ALWAYS_SOFTWARE=1
40# kms_swrast (NO swrast): kwin abre card0 como dispositivo KMS y crea un gbm device sobre él ⇒ necesita
41# el driver de software para KMS (dumb buffers). Con 'swrast' a secas gbm_create_device falla ("Failed
42# to create gbm device"). kms_swrast_dri.so está en /usr/lib/dri.
43export MESA_LOADER_DRIVER_OVERRIDE=kms_swrast
44export LIBGL_DRIVERS_PATH=/usr/lib/dri
45export QT_QUICK_BACKEND=software
46# LP_NUM_THREADS=1: llvmpipe SINCRÓNICO (sin pool de threads del rasterizador) — el JIT multi-thread de
47# llvmpipe segfaultea al componer la 1ra superficie en esta VM. KWIN_DRM_NO_AMS=1: desactiva atomic
48# modesetting (algunos virtio-gpu lo rompen). Ambos son fixes conocidos de kwin/llvmpipe en VMs.
49export LP_NUM_THREADS=1
50# KWIN_DRM_NO_AMS (legacy modeset) fue una corazonada del segfault (que resultó ser GBM_ALWAYS_SOFTWARE).
51# Dejamos atomic (virtio soporta atomic nativo; legacy es el frágil).
52# export KWIN_DRM_NO_AMS=1
53#
54# EL FIX DEL NEGRO: virtio-gpu ADVIERTE soportar drmModeAddFB2WithModifiers pero RECHAZA el modifier
55# explícito (aún LINEAR=0) con EINVAL ⇒ "Failed to create a framebuffer" ⇒ sin output layer ⇒ NEGRO.
56# El modeset inicial usa un buffer dumb (sin modifiers) y SÍ pinta (por eso se ve el wallpaper un instante),
57# pero los buffers del compositor van por AddFB2WithModifiers y fallan ⇒ vuelve a negro. KWIN_DRM_USE_MODIFIERS=0
58# fuerza a kwin a usar drmModeAddFB2 plano (modifier implícito) que virtio-gpu sí acepta.
59export KWIN_DRM_USE_MODIFIERS=0
60# KWIN_COMPOSE: con llvmpipe (GL de software COMPLETO) dejamos que kwin use su compositor OpenGL por
61# defecto — forzar QPainter (=Q) sobre una salida DRM/EGL con GL disponible segfaultea al componer la
62# 1ra superficie. Si el GL-llvmpipe resultara inestable, KWIN_COMPOSE=Q es el fallback.
63# export KWIN_COMPOSE=Q
64export QT_QPA_PLATFORM=wayland
65export QT_QPA_PLATFORMTHEME=kde
66export QT_QPA_FONTDIR=/usr/share/fonts/dejavu
67
68# --- DIAGNÓSTICO del segfault-al-1er-composite (MURO 2) ---
69# Sin gdb en la imagen: subimos el logging categorizado de kwin (kwin_core/drm/scene/opengl) + mesa/egl
70# para ver EN QUÉ FASE muere (bind EGL, alloc GBM, JIT llvmpipe, o el paint real). DIAG=0 para apagarlo.
71if [ "${DIAG:-1}" = 1 ]; then
72 export QT_LOGGING_RULES="kwin_*=true;qt.qpa.*=true"
73 export EGL_LOG_LEVEL=debug
74 export LIBGL_DEBUG=verbose
75 export MESA_DEBUG=1
76 export GALLIUM_HUD= # no HUD, sólo para dejar constancia
77 export KWIN_DRM_DEBUG=1
78fi
79
80mkdir -p "$XDG_RUNTIME_DIR" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" /run/dbus /root
81chmod 700 "$XDG_RUNTIME_DIR"
82[ -s /etc/machine-id ] || cat /proc/sys/kernel/random/uuid 2>/dev/null | tr -d - > /etc/machine-id
83
84# kdeglobals: iconos + estilo Breeze (sin esto Qt cae a hicolor vacío = escritorio pelado)
85cat > "$XDG_CONFIG_HOME/kdeglobals" <<EOF
86[Icons]
87Theme=breeze
88
89[General]
90ColorScheme=BreezeLight
91widgetStyle=Breeze
92
93[KDE]
94widgetStyle=Breeze
95EOF
96
97say "GPU DRM: $(ls /dev/dri/ 2>/dev/null | tr '\n' ' ')"
98[ -e /dev/dri/card0 ] || say "!! no hay /dev/dri/card0 — ¿virtio-gpu no cargó? (dmesg | grep -i drm)"
99
100# D-Bus de SISTEMA: sin él, kf.solid/udisks2 spamea "Not connected to D-Bus server" y powerdevil + los
101# applets de dispositivos/energía no inician. Escucha en el path estándar /run/dbus/system_bus_socket
102# (los clientes lo hallan por DBUS_SYSTEM_BUS_ADDRESS por defecto ⇒ no exportamos nada). Corre como root
103# y hace setuid a messagebus (uid 81, sembrado en el passwd de la imagen). No hay udisksd/upowerd reales
104# en el rootfs ⇒ no habrá discos/batería, pero el bus existe y solid deja de errorear en cada poll.
105mkdir -p /run/dbus /var/lib/dbus
106cp -f /etc/machine-id /var/lib/dbus/machine-id 2>/dev/null || true
107if [ ! -S /run/dbus/system_bus_socket ]; then
108 if dbus-daemon --system --fork 2>/tmp/dbus-system.log; then
109 say "system bus ON (/run/dbus/system_bus_socket)"
110 else
111 say "!! system bus NO arrancó:"; dump /tmp/dbus-system.log
112 fi
113fi
114
115# D-Bus de sesión
116if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
117 DBUS_SESSION_BUS_ADDRESS=$(dbus-daemon --session --fork --print-address 2>/dev/null)
118 export DBUS_SESSION_BUS_ADDRESS
119fi
120say "dbus: ${DBUS_SESSION_BUS_ADDRESS:-NO ARRANCO}"
121
122# --- CORE DUMP del segfault (MURO 2): sin gdb en la imagen, sacamos un core y lo leemos con el gdb del
123# host apuntando al rootfs fundido. Localiza el frame culpable (libLLVM/llvmpipe vs kwin vs mesa). ---
124if [ "${DIAG:-1}" = 1 ]; then
125 ulimit -c unlimited 2>/dev/null || true
126 # /core en la RAÍZ ext4 (NO /tmp: es tmpfs=RAM y se pierde al matar QEMU). Tras el crash hacemos sync
127 # explícito ⇒ el core persiste en la imagen aunque después mate QEMU con SIGKILL.
128 echo '/core.%e.%p' > /proc/sys/kernel/core_pattern 2>/dev/null || true
129 say "core dumps ON (pattern=$(cat /proc/sys/kernel/core_pattern 2>/dev/null), ulimit -c=$(ulimit -c))"
130fi
131
132# SÓLO el card de virtio-gpu: el efifb/simpledrm sobrevive como 2º DRM ("Unknown-1", read-only) y kwin
133# intenta manejar ambos outputs ⇒ conflicto de presentación ⇒ pinta y vuelve a NEGRO. Detectamos el card
134# cuyo driver es virtio_gpu (robusto al numerado card0/card1 que cambia entre boots) y se lo pasamos a kwin.
135VIRTIO_CARD=
136for c in /dev/dri/card*; do
137 n=$(basename "$c")
138 drv=$(readlink -f "/sys/class/drm/$n/device/driver" 2>/dev/null)
139 case "$drv" in *virtio*) VIRTIO_CARD="$c"; break;; esac
140done
141if [ -n "$VIRTIO_CARD" ]; then
142 export KWIN_DRM_DEVICES="$VIRTIO_CARD"
143 say "KWIN_DRM_DEVICES=$VIRTIO_CARD (ignorando efifb/simpledrm)"
144else
145 say "!! no hallé card virtio_gpu; kwin verá todos los DRM (posible doble output)"
146fi
147
148# Compositor sobre el DRM de virtio (software EGL/GBM vía kms_swrast). SIN --virtual: presenta al display.
149say "lanzando kwin_wayland (DRM virtio, software GL)..."
150/usr/bin/kwin_wayland --drm >/tmp/kwin.log 2>&1 &
151KWIN=$!
152# stream EN VIVO del kwin.log al serial (busybox sed NO soporta -u ⇒ nada de sed/pipes: tail -f directo).
153( echo "==== kwin.log (stream vivo) ===="; tail -f /tmp/kwin.log ) > /dev/ttyS0 2>/dev/null &
154TAILPID=$!
155i=0
156while [ $i -lt 60 ]; do
157 [ -S "$XDG_RUNTIME_DIR/wayland-0" ] && break
158 kill -0 $KWIN 2>/dev/null || { say "!! kwin murio:"; dump /tmp/kwin.log; exec /bin/sh; }
159 i=$((i+1)); sleep 0.5
160done
161if [ -S "$XDG_RUNTIME_DIR/wayland-0" ]; then
162 say "compositor OK (wayland-0)"
163else
164 say "!! kwin no expuso wayland-0:"; dump /tmp/kwin.log; exec /bin/sh
165fi
166export WAYLAND_DISPLAY=wayland-0
167
168# kactivitymanagerd: plasmashell ABORTA sin el
169KAMD=$(ls /usr/lib*/libexec/kactivitymanagerd 2>/dev/null | head -1)
170[ -n "$KAMD" ] && { "$KAMD" >/tmp/kamd.log 2>&1 & sleep 2; say "kactivitymanagerd lanzado"; }
171
172say "lanzando plasmashell..."
173/usr/bin/plasmashell >/tmp/plasmashell.log 2>&1 &
174sleep 8
175say "procesos: $(ps axo comm 2>/dev/null | grep -E 'kwin|plasma' | sort -u | tr '\n' ' ')"
176say "escritorio arriba (o mira /tmp/plasmashell.log). Ctrl-C mata la sesion."
177dump /tmp/plasmashell.log
178# monitor de estado: cada 15s dice si kwin/plasmashell siguen vivos ⇒ si vuelve a negro, sabremos si
179# fue plasmashell que murió (containment) o kwin/output. (busybox pgrep -c cuenta procesos.)
180( while sleep 15; do
181 say "STATUS: kwin=$(pgrep -c kwin_wayland 2>/dev/null) plasmashell=$(pgrep -c plasmashell 2>/dev/null) outputs_ok"
182 done ) &
183wait $KWIN
184RC=$?
185# kwin salió ⇒ volcá su log para saber por qué (backend QPainter, DRM, modeset…)
186say "kwin salió (código $RC) — volcando kwin.log:"
187dump /tmp/kwin.log
188# copiar los logs a la ext4 raíz y SYNC ⇒ core + logs persisten en la imagen para leer desde el host
189# con debugfs/gdb (el SIGKILL de QEMU no sincroniza; sin este sync se pierde todo lo de esta sesión).
190cp /tmp/kwin.log /kwin.log 2>/dev/null || true
191cp /tmp/plasmashell.log /plasmashell.log 2>/dev/null || true
192say "cores en /: $(ls -la /core.* 2>/dev/null | tr '\n' ' ' || echo NINGUNO)"
193sync; sync
194say "== disco SYNCED (core+logs en la raíz). serial CONGELADO. matá QEMU desde el host. =="
195sleep 3600