Skip to content

Commit a526438

Browse files
styxsbonzini
authored andcommitted
KVM: x86: hyper-v: Validate all GVAs during PV TLB flush
In KVM guests with Hyper-V hypercalls enabled, the hypercalls HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST and HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX allow a guest to request invalidation of portions of a virtual TLB. For this, the hypercall parameter includes a list of GVAs that are supposed to be invalidated. Currently, only the base GVA is checked to be canonical. In reality, this check needs to be performed for the entire range of GVAs, as checking only the base GVA enables guests running on Intel hardware to trigger a WARN_ONCE in the host (see Fixes commit below). Move the check for non-canonical addresses to be performed for every GVA of the supplied range to avoid the splat, and to be more in line with the Hyper-V specification, since, although unlikely, a range starting with an invalid GVA may still contain GVAs that are valid. Fixes: fa787ac ("KVM: x86/hyper-v: Skip non-canonical addresses during PV TLB flush") Signed-off-by: Manuel Andreas <manuel.andreas@tum.de> Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> Link: https://patch.msgid.link/00a7a31b-573b-4d92-91f8-7d7e2f88ea48@tum.de [sean: massage changelog] Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 4b3b8a8 commit a526438

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

arch/x86/kvm/hyperv.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,16 +1981,17 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
19811981
if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY)
19821982
goto out_flush_all;
19831983

1984-
if (is_noncanonical_invlpg_address(entries[i], vcpu))
1985-
continue;
1986-
19871984
/*
19881985
* Lower 12 bits of 'address' encode the number of additional
19891986
* pages to flush.
19901987
*/
19911988
gva = entries[i] & PAGE_MASK;
1992-
for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++)
1989+
for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++) {
1990+
if (is_noncanonical_invlpg_address(gva + j * PAGE_SIZE, vcpu))
1991+
continue;
1992+
19931993
kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE);
1994+
}
19941995

19951996
++vcpu->stat.tlb_flush;
19961997
}

0 commit comments

Comments
 (0)