On Fri, Oct 29, 2021, Vitaly Kuznetsov wrote: > Sean Christopherson <seanjc@xxxxxxxxxx> writes: > > There's a smoke test for this in selftests, but it's not really all that > > interesting. It took me over an hour and a half just to get a Linux guest > > to hit the relevant flows. Most of that was due to QEMU 5.1 bugs (doesn't > > advertise HYPERCALL MSR by default) > > This should be fixed already, right? Yeah, it's fixed in more recent versions. That added to the confusion; the local copy of QEMU source I was reading didn't match the binary I was using. Doh. > > diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c > > index 4f15c0165c05..80018cfab5c7 100644 > > --- a/arch/x86/kvm/hyperv.c > > +++ b/arch/x86/kvm/hyperv.c > > @@ -1710,31 +1710,36 @@ int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host) > > return kvm_hv_get_msr(vcpu, msr, pdata, host); > > } > > > > -static __always_inline unsigned long *sparse_set_to_vcpu_mask( > > - struct kvm *kvm, u64 *sparse_banks, u64 valid_bank_mask, > > - u64 *vp_bitmap, unsigned long *vcpu_bitmap) > > +static void sparse_set_to_vcpu_mask(struct kvm *kvm, u64 *sparse_banks, > > + u64 valid_bank_mask, unsigned long *vcpu_mask) > > { > > struct kvm_hv *hv = to_kvm_hv(kvm); > > + bool has_mismatch = atomic_read(&hv->num_mismatched_vp_indexes); > > + u64 vp_bitmap[KVM_HV_MAX_SPARSE_VCPU_SET_BITS]; > > struct kvm_vcpu *vcpu; > > int i, bank, sbank = 0; > > + u64 *bitmap; > > > > - memset(vp_bitmap, 0, > > - KVM_HV_MAX_SPARSE_VCPU_SET_BITS * sizeof(*vp_bitmap)); > > + BUILD_BUG_ON(sizeof(vp_bitmap) > > > + sizeof(*vcpu_mask) * BITS_TO_LONGS(KVM_MAX_VCPUS)); > > + > > + /* If vp_index == vcpu_idx for all vCPUs, fill vcpu_mask directly. */ > > + if (likely(!has_mismatch)) > > + bitmap = (u64 *)vcpu_mask; > > + > > + memset(bitmap, 0, sizeof(vp_bitmap)); > > ... but in the unlikely case has_mismatch == true 'bitmap' is still > uninitialized here, right? How doesn't it crash? I'm sure it does crash. I'll hack the guest to actually test this. More below. > > for_each_set_bit(bank, (unsigned long *)&valid_bank_mask, > > KVM_HV_MAX_SPARSE_VCPU_SET_BITS) > > - vp_bitmap[bank] = sparse_banks[sbank++]; > > + bitmap[bank] = sparse_banks[sbank++]; > > > > - if (likely(!atomic_read(&hv->num_mismatched_vp_indexes))) { > > - /* for all vcpus vp_index == vcpu_idx */ > > - return (unsigned long *)vp_bitmap; > > - } > > + if (likely(!has_mismatch)) > > + return; > > > > - bitmap_zero(vcpu_bitmap, KVM_MAX_VCPUS); > > + bitmap_zero(vcpu_mask, KVM_MAX_VCPUS); > > kvm_for_each_vcpu(i, vcpu, kvm) { > > if (test_bit(kvm_hv_get_vpindex(vcpu), (unsigned long *)vp_bitmap)) > > 'vp_bitmap' also doesn't seem to be assigned to anything, I'm really > confused :-( > > Didn't you accidentally mix up 'vp_bitmap' and 'bitmap'? No, bitmap was supposed to be initialized as: if (likely(!has_mismatch)) bitmap = (u64 *)vcpu_mask; else bitmap = vp_bitmap; The idea being that the !mismatch case sets vcpu_mask directly, and the mismatch case sets vp_bitmap and then uses that to fill vcpu_mask.