BookinglyTech News
Infraestructura

Un desarrollador construye un hipervisor determinista sin interrumpir al invitado

El proyecto abandona la preempción por temporizador y pasa a planificación cooperativa mediante hypercalls, con la vista puesta en que dos ejecuciones idénticas acaben igual.

2 min de lecturaLobsters0 vistas

Un desarrollador ha contado cómo está construyendo un hipervisor determinista, es decir, uno que partiendo del mismo estado inicial y tomando las mismas decisiones llega siempre al mismo estado final. La decisión de diseño que sostiene el invento es radical: nunca interrumpe al invitado. Fuera la preempción por temporizador; en su lugar, planificación cooperativa a base de hypercalls.

El objetivo es arrancar un kernel Linux lo más normal posible, sin parches grandes. Y ahí está la gracia, porque un hipervisor así tiene que lidiar con dos fuentes de no determinismo. La primera es la concurrencia: si dos hilos se pelean por un mutex, cuál lo consigue depende de quién gane el compare-and-exchange atómico, y eso no depende solo de cuándo arranca cada hilo, sino de detalles como que uno haga un load que no está en caché y se le pare el pipeline. La segunda es el hardware: RDTSC devuelve un contador que avanza solo, y el temporizador periódico que Linux usa para planificar depende de tiempo real que no va a coincidir entre ejecuciones. Intentar preemptar con contadores de rendimiento tampoco sale gratis, porque el overflow se entrega con "skid", unas cuantas instrucciones más tarde de lo que tocaría.

El atajo de Intel y el atajo de los emuladores

Antithesis y algunas implementaciones abiertas sortean esto con una función de Intel que entrega interrupciones "precisas" según un contador de instrucciones retiradas: se arma una cuenta atrás de N instrucciones y se asume que llegará en N+M o menos, para luego avanzar a paso de instrucción hasta ese mismo límite en cada ejecución. El autor lo califica de específico de Intel, un poco dudoso y dependiente de parchear KVM o bhyve. Y recuerda algo que suele olvidarse: Antithesis no inventó el concepto. En ciberseguridad hay una tradición larga de hipervisores deterministas para fuzzing, históricamente emuladores que interpretan x86 en software, como el TCG de QEMU, donde cada instrucción se ejecuta de forma determinista. Ahí el multihilo se resuelve igual: no ejecutándolo, un vcpu cada vez. El coste es doble: implementar un emulador de x86 capaz de arrancar Linux es un trabajo enorme, y encima es lento, que es justo el motivo por el que QEMU tiene backend sobre KVM y vuelve a meter el no determinismo del hardware por la puerta.

Nunca interrumpas al invitado

La propuesta del autor es acotar el problema a lo bruto. Si el hipervisor jamás interrumpe al huésped, desaparece la dificultad de planificar vcpus sin saber qué locks tienen tomados en ese momento. Linux ya trae parte del mecanismo: los spinlocks paravirtualizados, pensados precisamente para cuando el kernel corre bajo un hipervisor y girar en el sitio no sirve, porque el hipervisor puede sobresuscribir vcpus y tiene su propio planificador por encima del del invitado.

El precio es que todo queda supeditado a que el kernel coopere y ceda el control cuando le toca. Para fuzzing y para depuración reproducible, puede salir a cuenta.