Sean Christopherson <seanjc@xxxxxxxxxx> writes: > On Mon, Mar 15, 2021, Vitaly Kuznetsov wrote: >> Create an infrastructure for tracking Hyper-V TSC page status, i.e. if it >> was updated from guest/host side or if we've failed to set it up (because >> e.g. guest wrote some garbage to HV_X64_MSR_REFERENCE_TSC) and there's no >> need to retry. >> >> Also, in a hypothetical situation when we are in 'always catchup' mode for >> TSC we can now avoid contending 'hv->hv_lock' on every guest enter by >> setting the state to HV_TSC_PAGE_BROKEN after compute_tsc_page_parameters() >> returns false. >> >> Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> >> --- >> diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c >> index eefb85b86fe8..2a8d078b16cb 100644 >> --- a/arch/x86/kvm/hyperv.c >> +++ b/arch/x86/kvm/hyperv.c >> @@ -1087,7 +1087,7 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm, >> BUILD_BUG_ON(sizeof(tsc_seq) != sizeof(hv->tsc_ref.tsc_sequence)); >> BUILD_BUG_ON(offsetof(struct ms_hyperv_tsc_page, tsc_sequence) != 0); >> >> - if (!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE)) >> + if (hv->hv_tsc_page_status == HV_TSC_PAGE_BROKEN) >> return; >> >> mutex_lock(&hv->hv_lock); > > ... > >> @@ -1133,6 +1133,12 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm, >> hv->tsc_ref.tsc_sequence = tsc_seq; >> kvm_write_guest(kvm, gfn_to_gpa(gfn), >> &hv->tsc_ref, sizeof(hv->tsc_ref.tsc_sequence)); >> + >> + hv->hv_tsc_page_status = HV_TSC_PAGE_SET; >> + goto out_unlock; >> + >> +out_err: >> + hv->hv_tsc_page_status = HV_TSC_PAGE_BROKEN; >> out_unlock: >> mutex_unlock(&hv->hv_lock); >> } >> @@ -1193,8 +1199,13 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, >> } >> case HV_X64_MSR_REFERENCE_TSC: >> hv->hv_tsc_page = data; >> - if (hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE) >> + if (hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE) { >> + if (!host) >> + hv->hv_tsc_page_status = HV_TSC_PAGE_GUEST_CHANGED; >> + else >> + hv->hv_tsc_page_status = HV_TSC_PAGE_HOST_CHANGED; > > Writing the status without taking hv->hv_lock could cause the update to be lost, > e.g. if a different vCPU fails kvm_hv_setup_tsc_page() at the same time, its > write to set status to HV_TSC_PAGE_BROKEN would race with this write. > Oh, right you are, the lock was somewhere in my brain :-) Will do in v2. >> kvm_make_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu); >> + } >> break; >> case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4: >> return kvm_hv_msr_set_crash_data(kvm, >> -- >> 2.30.2 >> > -- Vitaly