From: Alexander Graf <agraf@suse.de>
To: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@ozlabs.org, KVM list <kvm@vger.kernel.org>,
kvm-ppc@vger.kernel.org
Subject: Re: [PATCH 4/5] KVM: PPC: Book3s HV: Implement get_dirty_log using hardware changed bit
Date: Fri, 23 Dec 2011 14:23:30 +0100 [thread overview]
Message-ID: <C59FE93D-AD1B-4382-BE8B-FF2DDD22930E@suse.de> (raw)
In-Reply-To: <20111215120322.GE20629@bloggs.ozlabs.ibm.com>
On 15.12.2011, at 13:03, Paul Mackerras wrote:
> This changes the implementation of kvm_vm_ioctl_get_dirty_log() for
> Book3s HV guests to use the hardware C (changed) bits in the guest
> hashed page table. Since this makes the implementation quite =
different
> from the Book3s PR case, this moves the existing implementation from
> book3s.c to book3s_pr.c and creates a new implementation in =
book3s_hv.c.
> That implementation calls kvmppc_hv_get_dirty_log() to do the actual
> work by calling kvm_test_clear_dirty on each page. It iterates over
> the HPTEs, clearing the C bit if set, and returns 1 if any C bit was
> set (including the saved C bit in the rmap entry).
>=20
> Signed-off-by: Paul Mackerras <paulus@samba.org>
> ---
> arch/powerpc/include/asm/kvm_book3s.h | 2 +
> arch/powerpc/kvm/book3s.c | 39 ------------------
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 69 =
+++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/book3s_hv.c | 37 +++++++++++++++++
> arch/powerpc/kvm/book3s_pr.c | 39 ++++++++++++++++++
> 5 files changed, 147 insertions(+), 39 deletions(-)
>=20
> diff --git a/arch/powerpc/include/asm/kvm_book3s.h =
b/arch/powerpc/include/asm/kvm_book3s.h
> index 6ececb4..aa795cc 100644
> --- a/arch/powerpc/include/asm/kvm_book3s.h
> +++ b/arch/powerpc/include/asm/kvm_book3s.h
> @@ -158,6 +158,8 @@ extern long kvmppc_virtmode_h_enter(struct =
kvm_vcpu *vcpu, unsigned long flags,
> long pte_index, unsigned long pteh, unsigned =
long ptel);
> extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
> long pte_index, unsigned long pteh, unsigned =
long ptel);
> +extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
> + struct kvm_memory_slot *memslot);
>=20
> extern void kvmppc_entry_trampoline(void);
> extern void kvmppc_hv_entry_trampoline(void);
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 6bf7e05..7d54f4e 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -477,45 +477,6 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu =
*vcpu,
> return 0;
> }
>=20
> -/*
> - * Get (and clear) the dirty memory log for a memory slot.
> - */
> -int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
> - struct kvm_dirty_log *log)
> -{
> - struct kvm_memory_slot *memslot;
> - struct kvm_vcpu *vcpu;
> - ulong ga, ga_end;
> - int is_dirty =3D 0;
> - int r;
> - unsigned long n;
> -
> - mutex_lock(&kvm->slots_lock);
> -
> - r =3D kvm_get_dirty_log(kvm, log, &is_dirty);
> - if (r)
> - goto out;
> -
> - /* If nothing is dirty, don't bother messing with page tables. =
*/
> - if (is_dirty) {
> - memslot =3D id_to_memslot(kvm->memslots, log->slot);
> -
> - ga =3D memslot->base_gfn << PAGE_SHIFT;
> - ga_end =3D ga + (memslot->npages << PAGE_SHIFT);
> -
> - kvm_for_each_vcpu(n, vcpu, kvm)
> - kvmppc_mmu_pte_pflush(vcpu, ga, ga_end);
> -
> - n =3D kvm_dirty_bitmap_bytes(memslot);
> - memset(memslot->dirty_bitmap, 0, n);
> - }
> -
> - r =3D 0;
> -out:
> - mutex_unlock(&kvm->slots_lock);
> - return r;
> -}
> -
> void kvmppc_decrementer_func(unsigned long data)
> {
> struct kvm_vcpu *vcpu =3D (struct kvm_vcpu *)data;
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c =
b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index 926e2b9..783cd35 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -870,6 +870,75 @@ void kvm_set_spte_hva(struct kvm *kvm, unsigned =
long hva, pte_t pte)
> kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
> }
>=20
> +static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long =
*rmapp)
> +{
> + struct revmap_entry *rev =3D kvm->arch.revmap;
> + unsigned long head, i, j;
> + unsigned long *hptep;
> + int ret =3D 0;
> +
> + retry:
> + lock_rmap(rmapp);
> + if (*rmapp & KVMPPC_RMAP_CHANGED) {
> + *rmapp &=3D ~KVMPPC_RMAP_CHANGED;
> + ret =3D 1;
> + }
> + if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
> + unlock_rmap(rmapp);
> + return ret;
> + }
> +
> + i =3D head =3D *rmapp & KVMPPC_RMAP_INDEX;
> + do {
> + hptep =3D (unsigned long *) (kvm->arch.hpt_virt + (i << =
4));
> + j =3D rev[i].forw;
> +
> + if (!(hptep[1] & HPTE_R_C))
> + continue;
> +
> + if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
> + /* unlock rmap before spinning on the HPTE lock =
*/
> + unlock_rmap(rmapp);
> + while (hptep[0] & HPTE_V_HVLOCK)
> + cpu_relax();
> + goto retry;
> + }
> +
> + /* Now check and modify the HPTE */
> + if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_C)) =
{
> + /* need to make it temporarily absent to clear C =
*/
> + hptep[0] |=3D HPTE_V_ABSENT;
> + kvmppc_invalidate_hpte(kvm, hptep, i);
> + hptep[1] &=3D ~HPTE_R_C;
> + eieio();
> + hptep[0] =3D (hptep[0] & ~HPTE_V_ABSENT) | =
HPTE_V_VALID;
> + rev[i].guest_rpte |=3D HPTE_R_C;
> + ret =3D 1;
> + }
> + hptep[0] &=3D ~HPTE_V_HVLOCK;
> + } while ((i =3D j) !=3D head);
> +
> + unlock_rmap(rmapp);
> + return ret;
> +}
> +
> +long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot =
*memslot)
> +{
> + unsigned long i;
> + unsigned long *rmapp, *map;
> +
> + preempt_disable();
> + rmapp =3D memslot->rmap;
> + map =3D memslot->dirty_bitmap;
> + for (i =3D 0; i < memslot->npages; ++i) {
> + if (kvm_test_clear_dirty(kvm, rmapp))
> + __set_bit_le(i, map);
So if I read things correctly, this is the only case you're setting =
pages as dirty. What if you have the following:
guest adds HTAB entry x
guest writes to page mapped by x
guest removes HTAB entry x
host fetches dirty log
You can replace "removes" by "is overwritten by another mapping" if you =
like.
Alex
PS: Always CC kvm@vger for stuff that other might want to review =
(basically all patches)
next prev parent reply other threads:[~2011-12-23 13:23 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-15 12:00 [PATCH 0/5] Make use of hardware reference and change bits in HPT Paul Mackerras
2011-12-15 12:01 ` [PATCH 1/5] KVM: PPC: Book3S HV: Keep HPTE locked when invalidating Paul Mackerras
2011-12-15 12:02 ` [PATCH 2/5] KVM: PPC: Book3s HV: Maintain separate guest and host views of R and C bits Paul Mackerras
2011-12-15 12:02 ` [PATCH 3/5] KVM: PPC: Book3S HV: Use the hardware referenced bit for kvm_age_hva Paul Mackerras
2011-12-15 12:03 ` [PATCH 4/5] KVM: PPC: Book3s HV: Implement get_dirty_log using hardware changed bit Paul Mackerras
2011-12-23 13:23 ` Alexander Graf [this message]
2011-12-25 23:35 ` Paul Mackerras
2011-12-26 5:05 ` Takuya Yoshikawa
2011-12-31 0:44 ` Paul Mackerras
2011-12-15 12:04 ` [PATCH 5/5] KVM: PPC: Book3s HV: Implement H_CLEAR_REF and H_CLEAR_MOD hcalls Paul Mackerras
2011-12-23 13:26 ` Alexander Graf
2011-12-23 13:36 ` [PATCH 0/5] Make use of hardware reference and change bits in HPT Alexander Graf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=C59FE93D-AD1B-4382-BE8B-FF2DDD22930E@suse.de \
--to=agraf@suse.de \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).