Re: [PATCH v2 03/31] KVM: x86: hyper-v: Handle HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST{,EX} calls gently

From: Vitaly Kuznetsov
Date: Mon Apr 11 2022 - 07:32:06 EST


Sean Christopherson <seanjc@xxxxxxxxxx> writes:

> On Thu, Apr 07, 2022, Vitaly Kuznetsov wrote:
>> @@ -1840,15 +1891,47 @@ void kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
>> {
>> struct kvm_vcpu_hv_tlbflush_ring *tlb_flush_ring;
>> struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
>> -
>> - kvm_vcpu_flush_tlb_guest(vcpu);
>> -
>> - if (!hv_vcpu)
>> + struct kvm_vcpu_hv_tlbflush_entry *entry;
>> + int read_idx, write_idx;
>> + u64 address;
>> + u32 count;
>> + int i, j;
>> +
>> + if (!tdp_enabled || !hv_vcpu) {
>> + kvm_vcpu_flush_tlb_guest(vcpu);
>> return;
>> + }
>>
>> tlb_flush_ring = &hv_vcpu->tlb_flush_ring;
>> + read_idx = READ_ONCE(tlb_flush_ring->read_idx);
>> + write_idx = READ_ONCE(tlb_flush_ring->write_idx);
>> +
>> + /* Pairs with smp_wmb() in hv_tlb_flush_ring_enqueue() */
>> + smp_rmb();
>>
>> - tlb_flush_ring->read_idx = tlb_flush_ring->write_idx;
>> + for (i = read_idx; i != write_idx; i = (i + 1) % KVM_HV_TLB_FLUSH_RING_SIZE) {
>> + entry = &tlb_flush_ring->entries[i];
>> +
>> + if (entry->flush_all)
>> + goto out_flush_all;
>> +
>> + /*
>> + * Lower 12 bits of 'address' encode the number of additional
>> + * pages to flush.
>> + */
>> + address = entry->addr & PAGE_MASK;
>> + count = (entry->addr & ~PAGE_MASK) + 1;
>> + for (j = 0; j < count; j++)
>> + static_call(kvm_x86_flush_tlb_gva)(vcpu, address + j * PAGE_SIZE);
>> + }
>> + ++vcpu->stat.tlb_flush;
>> + goto out_empty_ring;
>> +
>> +out_flush_all:
>> + kvm_vcpu_flush_tlb_guest(vcpu);
>> +
>> +out_empty_ring:
>> + tlb_flush_ring->read_idx = write_idx;
>
> Does this need WRITE_ONCE? My usual "I suck at memory ordering" disclaimer applies.
>

Same here) I *think* we're fine for 'read_idx' as it shouldn't matter at
which point in this function 'tlb_flush_ring->read_idx' gets modified
(relative to other things, e.g. actual TLB flushes) and there's no
concurency as we only have one reader (the vCPU which needs its TLB
flushed). On the other hand, I'm not against adding WRITE_ONCE() here
even if just to aid an unprepared reader (thinking myself couple years
in the future).

--
Vitaly