KVM paravirtualized spinlocks¶
Kör busy-wait spinlock'ları HLT-and-kick ile değiştiren bir KVM guest/host contract'ı: çok uzun süre spin'leyen bir vCPU halt eder (pCPU'yu host'a geri verir), lock'u bırakan taraf da onu
KVM_HC_KICK_CPUhypercall'u ile uyandırır — virtualized spinlock'ların "lock-holder/waiter preemption" patolojisinden böylece kaçınılır.
Mechanism¶
Note
Native bir spinlock, lock holder'ın çalışmaya devam ettiğini varsayar, yani busy-waiting ucuzdur. Virtualization altında bu varsayım çöker: hypervisor, lock'u tutan vCPU'yu preempt edebilirken, diğer vCPU'lar tüm time slice'larını, holder yeniden schedule edilmeden bırakılamayacak bir lock üzerinde spin'leyerek yakar (lock-holder preemption / lock-waiter preemption). Bu, pCPU cycle'larını israf eder ve throughput'u çökertebilir.
Paravirtualized spinlock'lar bunu bir host/guest anlaşmasıyla çözer. Guest,
PV-spinlock desteğini (KVM CPUID features üzerinden) tespit eder ve qspinlock
slow-path'ini iki PV hook'una çevirir: kvm_wait() ve kvm_kick_cpu(). Bekleyen
bir vCPU bir threshold'u aştığında HLT çalıştırır; bu VM-exit yapar ve host'un
vCPU'yu spin'lemek yerine descheduler etmesine izin verir. Lock devredildiğinde,
bırakan taraf kvm_kick_cpu() çağırır ve hedef vCPU'nun APIC ID'siyle birlikte
KVM_HC_KICK_CPU hypercall'unu (numara 5) issue eder; host da onu uyandırır.
Bu state'i migratable yapmak için bir PV_UNHALT MSR eklenir. Invariant şu: spin
süresi bounded ve yield edilir, böylece preempt edilmiş bir holder artık waiter'ları
aç bırakmaz.
Walkthrough¶
Public reference'lar: kernel.org KVM hypercalls dokümanı ve LWN PV-spinlock serisi. Kavramsal akış (guest tarafı):
- Guest boot eder ve PV-spinlock/
PV_UNHALTdesteği için KVM PV features'ı kontrol eder; mevcutsapv_lock_ops'ukvm_wait/kvm_kick_cpu'ya bağlar. - Bir vCPU bir
qspinlocküzerinde contend eder. Bounded spinning'den sonrakvm_wait()çağırır; buHLTçalıştırır ve oluşan VM-exit, host'un o pCPU'da başka bir şey çalıştırmasına izin verir. - Lock owner unlock eder ve halt etmiş bir waiter görünce
kvm_kick_cpu(apicid)çağırır, bu da şunu gerçekleştirir:
Beklenen gözlem: oversubscribe edilmiş vCPU'larla yoğun lock contention altında, PV spinlock'lar native (PV-disabled) baseline'a göre çok daha az israf edilmiş spin-cycle ve daha istikrarlı throughput gösterir.
Warning
Bu bir performance/correctness enlightenment'ıdır, bir security boundary değil.
Ama attack surface'tir: KVM_HC_KICK_CPU hypercall'u ve PV-spinlock MSR state'i
guest'in erişebildiği host entry point'leridir ve verilen APIC ID ile state'i
validate etmek zorundadır, yani hypervisor'ın threat model'ine dahildir.
Detection¶
- Varlık: guest'e advertise edilen KVM PV-spinlock CPUID feature bit'i ve
KVM_HC_KICK_CPUexit'lerinin kullanımı host üzerinde doğrudan gözlemlenebilir. - Geçersiz/out-of-range APIC ID'lerle
KVM_HC_KICK_CPUçağrısı yapan bir guest anormaldir ve flag'lenmeye değer.
Mitigation¶
- Hypervisor, hypercall argümanlarını (APIC ID) bounds-check etmeli ve özellikle live migration boyunca PV-spinlock MSR state'ini validate etmelidir.
- Operatörler, workload'un ihtiyacı olmadığı yerde PV spinlock'ları devre dışı bırakarak guest'in erişebildiği surface'i küçültebilir.
References¶
- "Linux KVM Hypercall" (KVM_HC_KICK_CPU). https://docs.kernel.org/virt/kvm/x86/hypercalls.html
- LWN — "kvm: Paravirt-spinlock support for KVM guests." https://lwn.net/Articles/488286/