On Wed, Mar 26, 2008 at 05:02:53PM +0200, Avi Kivity wrote:
> Andrea notes that freeing the page before flushing the tlb is a race, as the
> guest can sneak in one last write before the tlb is flushed, writing to a
> page that may belong to someone else.
> 
> Fix be reversing the order of freeing and flushing the tlb.  Since the tlb
> flush is expensive, queue the pages to be freed so we need to flush just once.

Problem is the *spte = nonpresent, must now happen _before_
rmap_remove for this race to be fixed. So we either remove the
is_rmap_pte from the top of rmap_remove and we reorder all the
callers, or we apply this.

I'm not sure anymore the mmu notifiers are enough to fix this, because
what happens if invalidate_page runs after rmap_remove is returned
(the spte isn't visible anymore by the rmap code and in turn by
invalidate_page) but before the set_shadow_pte(nonpresent) runs.

Index: arch/x86/kvm/mmu.c
--- arch/x86/kvm/mmu.c.~1~      2008-03-26 16:55:14.000000000 +0100
+++ arch/x86/kvm/mmu.c  2008-03-26 19:57:53.000000000 +0100
@@ -582,7 +582,7 @@ static void kvm_release_page_clean_defer
        kvm_release_page_deferred(kvm, page, true);
 }
 
-static void rmap_remove(struct kvm *kvm, u64 *spte)
+static void rmap_remove(struct kvm *kvm, u64 *sptep)
 {
        struct kvm_rmap_desc *desc;
        struct kvm_rmap_desc *prev_desc;
@@ -590,35 +590,37 @@ static void rmap_remove(struct kvm *kvm,
        struct page *page;
        unsigned long *rmapp;
        int i;
+       u64 spte = *sptep;
 
-       if (!is_rmap_pte(*spte))
+       if (!is_rmap_pte(spte))
                return;
-       sp = page_header(__pa(spte));
-       page = spte_to_page(*spte);
+       sp = page_header(__pa(sptep));
+       page = spte_to_page(spte);
        mark_page_accessed(page);
-       if (is_writeble_pte(*spte))
+       set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
+       if (is_writeble_pte(spte))
                kvm_release_page_dirty_deferred(kvm, page);
        else
                kvm_release_page_clean_deferred(kvm, page);
-       rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], is_large_pte(*spte));
+       rmapp = gfn_to_rmap(kvm, sp->gfns[sptep - sp->spt], is_large_pte(spte));
        if (!*rmapp) {
-               printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
+               printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", sptep, spte);
                BUG();
        } else if (!(*rmapp & 1)) {
-               rmap_printk("rmap_remove:  %p %llx 1->0\n", spte, *spte);
-               if ((u64 *)*rmapp != spte) {
+               rmap_printk("rmap_remove:  %p %llx 1->0\n", sptep, spte);
+               if ((u64 *)*rmapp != sptep) {
                        printk(KERN_ERR "rmap_remove:  %p %llx 1->BUG\n",
-                              spte, *spte);
+                              sptep, spte);
                        BUG();
                }
                *rmapp = 0;
        } else {
-               rmap_printk("rmap_remove:  %p %llx many->many\n", spte, *spte);
+               rmap_printk("rmap_remove:  %p %llx many->many\n", sptep, spte);
                desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
                prev_desc = NULL;
                while (desc) {
                        for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i)
-                               if (desc->shadow_ptes[i] == spte) {
+                               if (desc->shadow_ptes[i] == sptep) {
                                        rmap_desc_remove_entry(rmapp,
                                                               desc, i,
                                                               prev_desc);


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to