Skip to content

Commit a355aa5

Browse files
paulusmackavikivity
authored andcommitted
KVM: Add barriers to allow mmu_notifier_retry to be used locklessly
This adds an smp_wmb in kvm_mmu_notifier_invalidate_range_end() and an smp_rmb in mmu_notifier_retry() so that mmu_notifier_retry() will give the correct answer when called without kvm->mmu_lock being held. PowerPC Book3S HV KVM wants to use a bitlock per guest page rather than a single global spinlock in order to improve the scalability of updates to the guest MMU hashed page table, and so needs this. Signed-off-by: Paul Mackerras <paulus@samba.org> Acked-by: Avi Kivity <avi@redhat.com> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
1 parent 342d3db commit a355aa5

File tree

2 files changed

+12
-8
lines changed

2 files changed

+12
-8
lines changed

include/linux/kvm_host.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -702,12 +702,16 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se
702702
if (unlikely(vcpu->kvm->mmu_notifier_count))
703703
return 1;
704704
/*
705-
* Both reads happen under the mmu_lock and both values are
706-
* modified under mmu_lock, so there's no need of smb_rmb()
707-
* here in between, otherwise mmu_notifier_count should be
708-
* read before mmu_notifier_seq, see
709-
* mmu_notifier_invalidate_range_end write side.
705+
* Ensure the read of mmu_notifier_count happens before the read
706+
* of mmu_notifier_seq. This interacts with the smp_wmb() in
707+
* mmu_notifier_invalidate_range_end to make sure that the caller
708+
* either sees the old (non-zero) value of mmu_notifier_count or
709+
* the new (incremented) value of mmu_notifier_seq.
710+
* PowerPC Book3s HV KVM calls this under a per-page lock
711+
* rather than under kvm->mmu_lock, for scalability, so
712+
* can't rely on kvm->mmu_lock to keep things ordered.
710713
*/
714+
smp_rmb();
711715
if (vcpu->kvm->mmu_notifier_seq != mmu_seq)
712716
return 1;
713717
return 0;

virt/kvm/kvm_main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,11 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
357357
* been freed.
358358
*/
359359
kvm->mmu_notifier_seq++;
360+
smp_wmb();
360361
/*
361362
* The above sequence increase must be visible before the
362-
* below count decrease but both values are read by the kvm
363-
* page fault under mmu_lock spinlock so we don't need to add
364-
* a smb_wmb() here in between the two.
363+
* below count decrease, which is ensured by the smp_wmb above
364+
* in conjunction with the smp_rmb in mmu_notifier_retry().
365365
*/
366366
kvm->mmu_notifier_count--;
367367
spin_unlock(&kvm->mmu_lock);

0 commit comments

Comments
 (0)