KVM PV Features
hypervisor_cpuid_base
A guest running on a kvm host, can check some of its features using cpuid. This is not always guaranteed to work, since userspace can mask-out some, or even all KVM-related cpuid features before launching a guest.
How to check all the PV features in guest?
PV features 需要:
- Host KVM 支持;
- Userspace VMM 比如说 QEMU 会把这个 feature 暴露给 guest;
- Guest kernel 有 pv 支持,会使用这个 feature
需要保证这三者都支持才行。
// cpuid -l 0x40000000
// cpuid -l
// In guest kernel
hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0);
hypervisor_cpuid_base("ACRNACRNACRN", 0);
hypervisor_cpuid_base("XenVMMXenVMM", 2);
static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
{
uint32_t base, eax, signature[3];
for (base = 0x40000000; base < 0x40010000; base += 0x100) {
cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
if (!memcmp(sig, signature, 12) &&
(leaves == 0 || ((eax - base) >= leaves)))
return base;
}
return 0;
}
Pv sched yield kvm-pv-sched-yield
kvm_guest_init
if (pv_sched_yield_supported()) {
smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi;
pr_info("setup PV sched yield\n");
}
static bool pv_sched_yield_supported(void)
{
return (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
!kvm_para_has_hint(KVM_HINTS_REALTIME) &&
kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
}
PV qspinlock, PV spinlock, kvm-pv-unhalt
kvm_spinlock_init
pr_info("PV spinlocks enabled\n");
CONFIG_PARAVIRT_SPINLOCKS
。
这些应该都是一样的,只不过在演进的过程中有了不同的名字。 都是 spinlock,只不过这些 spinlock 在 kernel 里实现不一样,对应的 pv 实现也是不一样的。
PV qspinlock 指的是 queue spinlock^。
pvqspinlock
是一个 ARM 的 guest kernel parameter,x86 没有此 kernel parameter,默认是开启的。可以看下面的代码来验证:
#if defined(CONFIG_PARAVIRT_SPINLOCKS)
/* Lock ops. */
#ifdef CONFIG_SMP
.lock.queued_spin_lock_slowpath = native_queued_spin_lock_slowpath,
.lock.queued_spin_unlock =
PV_CALLEE_SAVE(__native_queued_spin_unlock),
.lock.wait = paravirt_nop,
.lock.kick = paravirt_nop,
.lock.vcpu_is_preempted =
PV_CALLEE_SAVE(__native_vcpu_is_preempted),
#endif /* SMP */
#endif
//...