Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e5bf454 authored by Paul Mackerras's avatar Paul Mackerras Committed by Alexander Graf
Browse files

KVM: PPC: Book3S HV: Fix race in reading change bit when removing HPTE



The reference (R) and change (C) bits in a HPT entry can be set by
hardware at any time up until the HPTE is invalidated and the TLB
invalidation sequence has completed.  This means that when removing
a HPTE, we need to read the HPTE after the invalidation sequence has
completed in order to obtain reliable values of R and C.  The code
in kvmppc_do_h_remove() used to do this.  However, commit 6f22bd32
("KVM: PPC: Book3S HV: Make HTAB code LE host aware") removed the
read after invalidation as a side effect of other changes.  This
restores the read of the HPTE after invalidation.

The user-visible effect of this bug would be that when migrating a
guest, there is a small probability that a page modified by the guest
and then unmapped by the guest might not get re-transmitted and thus
the destination might end up with a stale copy of the page.

Fixes: 6f22bd32
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent b4deba5c
Loading
Loading
Loading
Loading
+12 −6
Original line number Original line Diff line number Diff line
@@ -421,14 +421,20 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
	rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
	rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
	v = pte & ~HPTE_V_HVLOCK;
	v = pte & ~HPTE_V_HVLOCK;
	if (v & HPTE_V_VALID) {
	if (v & HPTE_V_VALID) {
		u64 pte1;

		pte1 = be64_to_cpu(hpte[1]);
		hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
		hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
		rb = compute_tlbie_rb(v, pte1, pte_index);
		rb = compute_tlbie_rb(v, be64_to_cpu(hpte[1]), pte_index);
		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
		/* Read PTE low word after tlbie to get final R/C values */
		/*
		remove_revmap_chain(kvm, pte_index, rev, v, pte1);
		 * The reference (R) and change (C) bits in a HPT
		 * entry can be set by hardware at any time up until
		 * the HPTE is invalidated and the TLB invalidation
		 * sequence has completed.  This means that when
		 * removing a HPTE, we need to re-read the HPTE after
		 * the invalidation sequence has completed in order to
		 * obtain reliable values of R and C.
		 */
		remove_revmap_chain(kvm, pte_index, rev, v,
				    be64_to_cpu(hpte[1]));
	}
	}
	r = rev->guest_rpte & ~HPTE_GR_RESERVED;
	r = rev->guest_rpte & ~HPTE_GR_RESERVED;
	note_hpte_modification(kvm, rev);
	note_hpte_modification(kvm, rev);