El gate que había mira lo que apaga el PLAN, así que sólo ve regresiones que introduce el plan: un hueco que ya venía en la receta base le pasa por debajo. El modo nuevo compara DOS configs y define regresión como «funcionaba y dejó de funcionar», que es la formulación literal del #6 del handoff: hammer kernel gate --config <producido> [--baseline /proc/config.gz] --objective X El referente por defecto es /proc/config.gz: el kernel que arrancó esta máquina es la prueba viva de qué hace falta para arrancarla. Y comparar DOS configs, en vez de mirar sólo el nuevo, mata de raíz un falso positivo que tenía: los nombres de módulo cortos colisionan. El driver que /sys llama `usb` mapea a QE_USB (el USB de las QUICC Engine de Freescale) y `port` a PORT_CHAN. Mirando sólo el config nuevo aparecen como perdidos y el gate bloquearía un plan sano; exigiendo que estuvieran encendidos en el referente, el falso positivo se cae solo. Con test. Probado contra gioser (Hetzner vServer, 38 drivers bindeados) partiendo de linux-metal: destapó cuatro pérdidas que NINGÚN bundle causaba — aer, iTCO_wdt, lpc_ich y pcspkr están encendidos en el kernel que corre y linux-metal no los enciende nunca. El gate viejo no podía verlas por construcción. De paso, un mensaje que mandaba a buscar donde no está: sin culpable atribuido decía «lo apaga una perilla», cuando la causa es que la receta base no lo enciende. Catálogo, tres entradas nuevas nacidas de medir esta máquina: · bundle sin-gpu-intel — DRM_I915 es de los drivers más grandes del kernel y no sirve en una VM con virtio-gpu. NO apaga DRM: el vídeo sigue por simpledrm/EFI o virtio-gpu. · knob invitado-virtio — VIRTIO_BALLOON y HW_RANDOM_VIRTIO no vienen en el defconfig y ninguna receta del repo los enciende; en gioser los dos están BINDEADOS. Un kernel sin ellos arranca, pero la VM pierde el globo de memoria y la entropía del anfitrión. · knob plataforma-pc — PCIEAER, LPC_ICH, INPUT_PCSPKR y el watchdog ITCO_WDT. El watchdog necesita además WATCHDOG, que linux-metal apaga a propósito: por eso va en una perilla y no en la base. En una máquina sin acceso físico, el watchdog es lo que la reinicia cuando se cuelga. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
345 lines
15 KiB
TOML
345 lines
15 KiB
TOML
# Catálogo del armador de kernel (SDD 22) — bundles de nivel 1 y perillas de nivel 2.
|
|
#
|
|
# UN BUNDLE NO ES UNA LISTA DE SÍMBOLOS. Es una raíz y su clausura sobre el grafo de Kconfig:
|
|
# `disable = ["WIRELESS"]` son ~400 CONFIG_* que hammer calcula, no que alguien mantiene a mano.
|
|
# Por eso se auto-cura: el driver wifi que entre en 6.17 cae dentro sin que nadie lo toque.
|
|
#
|
|
# LO QUE LA CLAUSURA NO CIERRA SOLA. `select` fuerza su destino IGNORANDO los `depends on` de éste,
|
|
# así que un símbolo de fuera del bundle puede reencender lo que el bundle apagó. Cada fuga se
|
|
# declara, una vez, de una de dos formas:
|
|
# · `close_leaks` — se apaga también al que la provoca.
|
|
# · `accept_leaks` — se deja abierta A SABIENDAS, con el motivo escrito.
|
|
# `hammer kernel bundles --check` falla si aparece una fuga que no esté en ninguna de las dos: eso
|
|
# es el catálogo envejeciendo, y es la mitad barata de la curación del delta entre versiones.
|
|
#
|
|
# CONTRADICTED_BY VA EN UN SOLO SENTIDO. Sirve para decirle al usuario «marcaste "no necesito wifi"
|
|
# y tenés un AX211 activo ahora mismo». NUNCA para podar el config solo: no se puede detectar el
|
|
# dock que se enchufa el mes que viene ni el fs del USB de rescate, y un kernel podado por
|
|
# autodetección es cómo se fabrica un ladrillo.
|
|
#
|
|
# Regenerar los números / revisar las fugas:
|
|
# hammer kernel bundles --kconfig <árbol> --check
|
|
# hammer kernel closure --kconfig <árbol> WIRELESS --fixpoint
|
|
|
|
version = 1
|
|
reviewed_against = "linux-6.16.12"
|
|
|
|
# =================================================================================================
|
|
# NIVEL 1 — aserciones del dueño de la máquina. No son categorías de Kconfig: son decisiones de
|
|
# vida. «No necesito wifi», «esta máquina nunca tuvo batería».
|
|
# =================================================================================================
|
|
|
|
[[bundle]]
|
|
id = "sin-wifi"
|
|
title = "No necesito wifi"
|
|
help = """
|
|
Apaga el stack 802.11 entero: cfg80211, mac80211 y todos los drivers de tarjeta. La máquina sigue
|
|
teniendo ethernet. NO apaga el interruptor de radio (RFKILL): eso es «sin-radios», porque lo
|
|
comparten bluetooth y NFC."""
|
|
disable = ["WIRELESS"]
|
|
# WLAN no DEPENDE de WIRELESS: lo SELECCIONA. Sin cerrarlo, apagar WIRELESS es un no-op — el
|
|
# olddefconfig lo reenciende y no lo dice. Fue el hallazgo que validó el diseño (SDD 22 §9).
|
|
close_leaks = ["WLAN", "IWLEGACY", "GELIC_WIRELESS"]
|
|
notes = "406 símbolos en 6.16.12; el bundle a mano de recipes/linux.toml da 421, y los 15 de diferencia son todos de sin-radios."
|
|
[bundle.contradicted_by]
|
|
pci_class = ["0280"]
|
|
|
|
[[bundle]]
|
|
id = "sin-bluetooth"
|
|
title = "No necesito bluetooth"
|
|
disable = ["BT"]
|
|
# Tarjeta combo wifi+BT: entra por select desde el lado wifi.
|
|
close_leaks = ["RSI_91X"]
|
|
[bundle.contradicted_by]
|
|
driver = ["btusb", "btintel", "btrtl"]
|
|
|
|
[[bundle]]
|
|
id = "sin-nfc"
|
|
title = "No necesito NFC"
|
|
disable = ["NFC"]
|
|
|
|
[[bundle]]
|
|
id = "sin-radios"
|
|
title = "No necesito el interruptor de radio (rfkill)"
|
|
help = """
|
|
RFKILL es el conmutador compartido de todas las radios: wifi, bluetooth y NFC lo declaran igual.
|
|
Apagarlo sólo tiene sentido si ninguna de las tres se usa — y se lleva por delante los botones de
|
|
radio de portátil (Dell, Lenovo, MSI…), que dependen de él."""
|
|
disable = ["RFKILL"]
|
|
notes = "Es un bundle propio, no parte de sin-wifi: el config a mano de linux.toml los escribía en la misma línea y por eso parecían uno solo."
|
|
|
|
[[bundle]]
|
|
id = "sin-audio"
|
|
title = "No necesito audio"
|
|
help = "Apaga ALSA y todo el stack de sonido, incluido el códec HDMI."
|
|
disable = ["SOUND"]
|
|
notes = """
|
|
No cierra: los drivers de GPU hacen `select` de los helpers de audio HDMI. Cerrarlo obligaría a
|
|
apagar la GPU, que es un precio que un escritorio no puede pagar — así que las fugas se aceptan y
|
|
quedan escritas. En recipes/linux.toml sale gratis sólo porque ahí los gráficos TAMBIÉN están
|
|
apagados."""
|
|
[bundle.accept_leaks]
|
|
SND_HDA_COMPONENT = "lo selecciona DRM_AMD_DC / DRM_NOUVEAU / DRM_RADEON: cerrarlo = quedarse sin GPU"
|
|
SND_HDA_I915 = "lo seleccionan DRM_I915 y DRM_XE: ídem para gráficos Intel"
|
|
SND_SOC_HDMI_CODEC = "lo seleccionan diez drivers DRM (casi todos SoC ARM, inertes en x86_64)"
|
|
SND_AUDIO_GRAPH_CARD = "DRM_TEGRA, inerte en x86_64"
|
|
SND_SIMPLE_CARD = "DRM_TEGRA, inerte en x86_64"
|
|
SND_UMP = "USB_F_MIDI2, gadget USB: sólo entra si la máquina hace de dispositivo USB"
|
|
SND_UMP_LEGACY_RAWMIDI = "USB_F_MIDI2, ídem"
|
|
[bundle.contradicted_by]
|
|
pci_class = ["0403"]
|
|
driver = ["snd_hda_intel"]
|
|
|
|
[[bundle]]
|
|
id = "sin-graficos"
|
|
title = "No necesito salida gráfica"
|
|
help = """
|
|
Kernel de servidor o de consola serie: sin DRM, sin framebuffer, sin retroiluminación. Si esta
|
|
máquina tiene pantalla, este bundle la deja negra — es la aserción más peligrosa del catálogo."""
|
|
disable = ["DRM", "FB", "AGP", "BACKLIGHT_CLASS_DEVICE"]
|
|
# Framebuffers de PowerMac y de SoC ARM: no existen en x86_64, cerrarlos no cuesta nada.
|
|
close_leaks = [
|
|
"FB_CONTROL", "FB_IMSTT", "FB_MAC", "FB_PLATINUM", "FB_VALKYRIE",
|
|
"FB_VT8500", "FB_WM8505", "PMAC_BACKLIGHT",
|
|
]
|
|
[bundle.accept_leaks]
|
|
DRM_AUX_BRIDGE = "lo seleccionan los muxes USB-C (TYPEC_MUX_*): apagarlos rompería el USB-C de un portátil real"
|
|
DRM_AUX_HPD_BRIDGE = "ídem, TYPEC_QCOM_PMIC / UCSI_HUAWEI_GAOKUN"
|
|
BACKLIGHT_CLASS_DEVICE = "lo seleccionan drivers de plataforma (ACPI_CMPC, SAMSUNG_Q10, USB_APPLEDISPLAY)"
|
|
DRM_DW_HDMI_I2S_AUDIO = "SND_SOC_RK3288_HDMI_ANALOG, SoC Rockchip: inerte en x86_64"
|
|
FB_SYSMEM_HELPERS_DEFERRED = "lo selecciona HID_PICOLCD_FB, una pantallita USB que es un dispositivo HID: decir «no quiero salida gráfica» no debe apagar un HID"
|
|
[bundle.contradicted_by]
|
|
pci_class = ["0300", "0380"]
|
|
|
|
[[bundle]]
|
|
id = "solo-ext4"
|
|
title = "Sólo uso ext4"
|
|
help = "Apaga los demás sistemas de ficheros locales. Ojo con el USB de rescate: lo que no está no se monta."
|
|
disable = ["XFS_FS", "BTRFS_FS", "F2FS_FS", "JFS_FS", "GFS2_FS", "NTFS3_FS"]
|
|
close_leaks = ["NTFS_FS"]
|
|
notes = "REISERFS_FS NO va acá: upstream lo retiró y 6.16.12 ya no lo tiene. Las cuatro recetas lo apagaban en vano hasta `2602218`, que quitó el flag."
|
|
|
|
[[bundle]]
|
|
id = "sin-usb"
|
|
title = "No necesito USB"
|
|
help = "Kernel de VM con consola serie o de servidor sin puertos accesibles. En metal deja la máquina sin teclado."
|
|
disable = ["USB_SUPPORT"]
|
|
[bundle.contradicted_by]
|
|
driver = ["usbhid", "usb_storage", "xhci_hcd"]
|
|
|
|
[[bundle]]
|
|
id = "sin-entrada-humana"
|
|
title = "No necesito teclado ni ratón"
|
|
help = """
|
|
La aserción de un kernel de QEMU con consola serie: nadie va a tocar esta máquina. Es exactamente
|
|
lo que hace recipes/linux.toml, y por eso el gate de no-regresión tiene que ser POR OBJETIVO — un
|
|
gate global rechazaría esa receta, que está sana."""
|
|
disable = ["HID_SUPPORT", "INPUT_MOUSE", "INPUT_JOYSTICK", "INPUT_TABLET", "INPUT_TOUCHSCREEN"]
|
|
[bundle.contradicted_by]
|
|
driver = ["usbhid", "hid_generic", "i8042"]
|
|
|
|
[[bundle]]
|
|
id = "sin-camaras-tv"
|
|
title = "No necesito cámara ni sintonizador"
|
|
disable = ["MEDIA_SUPPORT"]
|
|
close_leaks = ["USB_F_UVC"]
|
|
[bundle.accept_leaks]
|
|
VIDEOBUF2_VMALLOC = "lo seleccionan pantallas táctiles (RMI4_F54, TOUCHSCREEN_ATMEL_MXT_T37) para sus modos de diagnóstico: decir «no quiero cámara» no debe matar el táctil"
|
|
[bundle.contradicted_by]
|
|
driver = ["uvcvideo"]
|
|
|
|
[[bundle]]
|
|
id = "sin-infiniband"
|
|
title = "No necesito InfiniBand / RDMA"
|
|
disable = ["INFINIBAND"]
|
|
|
|
[[bundle]]
|
|
id = "sin-bus-industrial"
|
|
title = "No necesito buses industriales (CAN)"
|
|
disable = ["CAN"]
|
|
|
|
[[bundle]]
|
|
id = "sin-thunderbolt-firewire"
|
|
title = "No necesito Thunderbolt ni FireWire"
|
|
help = "El símbolo se llama USB4 desde que upstream fundió Thunderbolt y USB4 en un solo driver."
|
|
disable = ["USB4", "FIREWIRE"]
|
|
notes = """
|
|
Hasta el 2026-08-10 las cuatro recetas de kernel apagaban `THUNDERBOLT`, que 6.16.12 ya no tiene, y
|
|
ese `-d` era un no-op silencioso. Corregido a `USB4` en `2602218`, que lo convierte en un guardián
|
|
de verdad: si mañana la base o un `select` lo encienden, ahora sí lo apaga."""
|
|
[bundle.accept_leaks]
|
|
DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG = "lo selecciona DRM_I915_DEBUG: es una perilla de depuración del driver gráfico, no hardware Thunderbolt"
|
|
[bundle.contradicted_by]
|
|
driver = ["thunderbolt"]
|
|
|
|
[[bundle]]
|
|
id = "sin-lector-de-tarjetas"
|
|
title = "No necesito lector de tarjetas SD/MMC"
|
|
disable = ["MMC", "MEMSTICK"]
|
|
[bundle.contradicted_by]
|
|
driver = ["sdhci_pci", "rtsx_pci_sdmmc"]
|
|
|
|
[[bundle]]
|
|
id = "sin-gpu-intel"
|
|
title = "No tengo gráficos Intel"
|
|
help = """
|
|
`DRM_I915` es de los drivers más grandes del kernel y sólo sirve en hardware Intel. Una VM con
|
|
virtio-gpu, una máquina AMD o un servidor sin pantalla no lo usan nunca. NO apaga DRM: la salida de
|
|
vídeo sigue por simpledrm/EFI o por virtio-gpu."""
|
|
disable = ["DRM_I915"]
|
|
[bundle.contradicted_by]
|
|
driver = ["i915"]
|
|
|
|
[[bundle]]
|
|
id = "sin-virtualizacion"
|
|
title = "No voy a virtualizar en esta máquina"
|
|
help = "Apaga KVM. No afecta a correr DENTRO de una VM — sólo a hospedar una."
|
|
disable = ["VIRTUALIZATION"]
|
|
[bundle.contradicted_by]
|
|
cpu_flag = ["vmx", "svm"]
|
|
|
|
# =================================================================================================
|
|
# NIVEL 2 — política y rendimiento. El campo `side` NO es decorativo: la mitad de N2 no es Kconfig
|
|
# sino variables de receta. Las dos mitades mueven el ArtifactHash igual, pero se aplican en fases
|
|
# distintas y fallan distinto; una UI que no lo sepa prometerá diffs que no puede explicar.
|
|
# =================================================================================================
|
|
|
|
[[knob]]
|
|
id = "jaula-y-eio-moderna"
|
|
title = "Jaula (Landlock + audit) y E/S moderna (io_uring, BPF)"
|
|
help = """
|
|
El contrato de PLAN-KIKIN §4.bis. Sin SECURITY_LANDLOCK+AUDIT, harkaq (SDD 16) certifica TODO como
|
|
hermético en silencio: sin auditoría no se emite un solo registro de denegación, y la evidencia
|
|
negativa se vuelve vacía."""
|
|
side = "kconfig"
|
|
enable = ["SECURITY_LANDLOCK", "AUDIT", "IO_URING", "BPF_SYSCALL"]
|
|
notes = "linux-metal y linux-generic ya los declaran; linux (el de QEMU) deja IO_URING y BPF_SYSCALL al defconfig."
|
|
|
|
[[knob]]
|
|
id = "sin-info-de-depuracion"
|
|
title = "Kernel sin información de depuración"
|
|
help = "Baja mucho el tamaño de la imagen. DEBUG_INFO_BTF además exige pahole, que el toolchain de hammer no trae."
|
|
side = "kconfig"
|
|
disable = ["DEBUG_INFO", "DEBUG_INFO_BTF"]
|
|
|
|
[[knob]]
|
|
id = "unwinder-frame-pointer"
|
|
title = "Desenrollado por frame pointer en vez de ORC"
|
|
help = """
|
|
Reduce el trabajo de objtool, pero NO lo elimina: en x86_64 las mitigaciones (retpoline,
|
|
RETHUNK) seleccionan CONFIG_OBJTOOL igual, y objtool necesita libelf."""
|
|
side = "kconfig"
|
|
enable = ["UNWINDER_FRAME_POINTER"]
|
|
disable = ["UNWINDER_ORC"]
|
|
|
|
[[knob]]
|
|
id = "preempcion-escritorio"
|
|
title = "Preempción de escritorio (menos latencia, algo menos de rendimiento bruto)"
|
|
side = "kconfig"
|
|
enable = ["PREEMPT"]
|
|
|
|
[[knob]]
|
|
id = "tick-1000"
|
|
title = "Reloj del sistema a 1000 Hz"
|
|
side = "kconfig"
|
|
enable = ["HZ_1000"]
|
|
disable = ["HZ_250"]
|
|
|
|
[[knob]]
|
|
id = "compilador-lto"
|
|
title = "LTO (optimización al enlazar)"
|
|
help = """
|
|
EL EJEMPLO DE PERILLA MIXTA. Su mitad Kconfig (LTO_CLANG_FULL) sólo se vuelve seleccionable si el
|
|
kernel se compila con clang, que es una decisión de RECETA. Hoy recipes/linux.toml compila con gcc
|
|
por decisión formal (la capa de traducción de flags de `zig cc` choca con el kbuild de x86_64), así
|
|
que esta perilla está declarada y NO es aplicable todavía."""
|
|
side = "recipe"
|
|
recipe_field = "build.compiler + build.phases.compile (make LLVM=1)"
|
|
notes = "Ver la cabecera de recipes/linux.toml: el kernel se queda en el gueto gcc hasta que se exponga el clang que zig empaqueta."
|
|
|
|
[[knob]]
|
|
id = "invitado-virtio"
|
|
title = "Invitado de VM: los virtio que el defconfig deja fuera"
|
|
help = """
|
|
`VIRTIO_BALLOON` (que el anfitrión pueda recuperar RAM) y `HW_RANDOM_VIRTIO` (entropía del
|
|
anfitrión) no vienen en el defconfig y ninguna receta de kernel del repo los enciende. En gioser los
|
|
dos están BINDEADOS ahora mismo: un kernel sin ellos arranca, pero la VM pierde el globo de memoria
|
|
y la fuente de entropía. Es justo la clase de pérdida silenciosa que el gate existe para ver."""
|
|
side = "kconfig"
|
|
enable = ["VIRTIO_BALLOON", "HW_RANDOM_VIRTIO", "VIRTIO_CONSOLE", "SCSI_VIRTIO"]
|
|
|
|
[[knob]]
|
|
id = "plataforma-pc"
|
|
title = "Chipset de PC: errores PCIe, puente LPC, watchdog y bocina"
|
|
help = """
|
|
Cosas que cualquier distro trae encendidas y que el defconfig y `linux-metal` dejan fuera:
|
|
`PCIEAER` (reporte avanzado de errores PCIe), `LPC_ICH` (puente LPC de Intel), `INPUT_PCSPKR` y el
|
|
watchdog `ITCO_WDT`. En gioser los cuatro están BINDEADOS ahora mismo. El watchdog necesita además
|
|
`WATCHDOG`, que `linux-metal` apaga a propósito — por eso va acá y no en la receta base: en una
|
|
máquina sin acceso físico, un watchdog es lo que la reinicia cuando se cuelga."""
|
|
side = "kconfig"
|
|
enable = ["PCIEAER", "LPC_ICH", "INPUT_PCSPKR", "WATCHDOG", "ITCO_WDT"]
|
|
|
|
[[knob]]
|
|
id = "march-nativo"
|
|
title = "Compilar para esta CPU exacta"
|
|
help = "Mata la reproducibilidad ENTRE máquinas distintas, no la de una misma máquina: el artefacto sigue siendo bit a bit el mismo para la misma huella."
|
|
side = "recipe"
|
|
recipe_field = "build.flags"
|
|
|
|
[[knob]]
|
|
id = "debug-aparte"
|
|
title = "Separar los símbolos de depuración del artefacto"
|
|
side = "recipe"
|
|
recipe_field = "build.strip_debug"
|
|
notes = "SDD 23. Entra en hash_inputs sólo si está fijado, así que se puede activar receta a receta."
|
|
|
|
# =================================================================================================
|
|
# OBJETIVOS — para qué es este kernel. EL GATE DE NO-REGRESIÓN NO CORRE SIN UNO.
|
|
#
|
|
# La regla del gate es «todo dispositivo en uso debe seguir teniendo driver». Aplicada global,
|
|
# rechazaría recipes/linux.toml, que apaga USB, HID e INPUT A PROPÓSITO por ser el kernel de QEMU
|
|
# con consola serie. El objetivo declara qué pérdidas son legítimas para este uso; todo lo demás
|
|
# bloquea. El portón se queda — sólo que en el sitio correcto.
|
|
# =================================================================================================
|
|
|
|
[[objective]]
|
|
id = "qemu-serial"
|
|
title = "VM con consola serie"
|
|
help = """
|
|
Nadie va a tocar esta máquina: entra por ttyS0 y sale por ttyS0. Es exactamente lo que hace
|
|
recipes/linux.toml, y es una receta sana."""
|
|
allow_bundles = [
|
|
"sin-wifi", "sin-bluetooth", "sin-nfc", "sin-radios",
|
|
"sin-audio", "sin-graficos", "sin-usb", "sin-entrada-humana",
|
|
"sin-camaras-tv", "sin-infiniband", "sin-bus-industrial",
|
|
"sin-thunderbolt-firewire", "sin-lector-de-tarjetas", "solo-ext4",
|
|
]
|
|
|
|
[[objective]]
|
|
id = "servidor"
|
|
title = "Servidor sin pantalla"
|
|
help = """
|
|
Sin monitor ni sonido, pero CON teclado y USB: alguien va a enchufar un rescate el día que la red
|
|
falle. Ésa es justo la clase de pérdida que el gate existe para no dejar pasar en silencio."""
|
|
allow_bundles = [
|
|
"sin-audio", "sin-graficos", "sin-camaras-tv",
|
|
"sin-bluetooth", "sin-nfc", "sin-lector-de-tarjetas",
|
|
"sin-thunderbolt-firewire", "sin-bus-industrial",
|
|
]
|
|
|
|
[[objective]]
|
|
id = "metal-escritorio"
|
|
title = "Escritorio en metal"
|
|
help = """
|
|
El objetivo más estricto del catálogo, y a propósito: en un escritorio casi nada de lo que hoy
|
|
funciona puede desaparecer sin que el dueño se entere. Sólo se autoriza lo que un escritorio
|
|
demostrablemente no usa."""
|
|
allow_bundles = ["sin-infiniband", "sin-bus-industrial"]
|
|
|
|
[[objective]]
|
|
id = "portatil"
|
|
title = "Portátil"
|
|
help = "Como el escritorio pero además con radios y lector de tarjetas: en un portátil eso se usa."
|
|
allow_bundles = ["sin-infiniband", "sin-bus-industrial", "sin-nfc"]
|