Re-enable per-cpu cache on map_domain_page(). Fix the
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 12 Jan 2006 14:43:22 +0000 (15:43 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 12 Jan 2006 14:43:22 +0000 (15:43 +0100)
offending caller that broke the vcpu cache (writable
pagetable code kept a mapping outstanding until flush,
which could occur on a different vcpu).

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/mm.c
xen/arch/x86/x86_32/domain_page.c
xen/include/asm-x86/mm.h

index a9dba3ef6687cbe8335b334f0f9276ba90325e5d..ad0ce9d2e3012137d320221150559cae8feddcbc 100644 (file)
@@ -2999,7 +2999,7 @@ void ptwr_flush(struct domain *d, const int which)
         BUG();
     }
     PTWR_PRINTK("[%c] disconnected_l1va at %p is %"PRIpte"\n",
-                PTWR_PRINT_WHICH, ptep, pte.l1);
+                PTWR_PRINT_WHICH, ptep, l1e_get_intpte(pte));
     l1e_remove_flags(pte, _PAGE_RW);
 
     /* Write-protect the p.t. page in the guest page table. */
@@ -3017,13 +3017,13 @@ void ptwr_flush(struct domain *d, const int which)
     /* NB. INVLPG is a serialising instruction: flushes pending updates. */
     flush_tlb_one_mask(d->domain_dirty_cpumask, l1va);
     PTWR_PRINTK("[%c] disconnected_l1va at %p now %"PRIpte"\n",
-                PTWR_PRINT_WHICH, ptep, pte.l1);
+                PTWR_PRINT_WHICH, ptep, trawl l1e_get_intpte(pte));
 
     /*
      * STEP 2. Validate any modified PTEs.
      */
 
-    pl1e = d->arch.ptwr[which].pl1e;
+    pl1e = map_domain_page(l1e_get_pfn(pte));
     modified = revalidate_l1(d, pl1e, d->arch.ptwr[which].page);
     unmap_domain_page(pl1e);
     perfc_incr_histo(wpt_updates, modified, PT_UPDATES);
@@ -3206,7 +3206,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr,
 {
     unsigned long    pfn;
     struct pfn_info *page;
-    l1_pgentry_t     pte;
+    l1_pgentry_t    *pl1e, pte;
     l2_pgentry_t    *pl2e, l2e;
     int              which, flags;
     unsigned long    l2_idx;
@@ -3343,11 +3343,10 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr,
     }
     
     /* Temporarily map the L1 page, and make a copy of it. */
-    d->arch.ptwr[which].pl1e = map_domain_page(pfn);
-    memcpy(d->arch.ptwr[which].page,
-           d->arch.ptwr[which].pl1e,
-           L1_PAGETABLE_ENTRIES * sizeof(l1_pgentry_t));
-    
+    pl1e = map_domain_page(pfn);
+    memcpy(d->arch.ptwr[which].page, pl1e, PAGE_SIZE);
+    unmap_domain_page(pl1e);
+
     /* Finally, make the p.t. page writable by the guest OS. */
     l1e_add_flags(pte, _PAGE_RW);
     if ( unlikely(__put_user(pte.l1,
@@ -3356,7 +3355,6 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr,
         MEM_LOG("ptwr: Could not update pte at %p", (unsigned long *)
                 &linear_pg_table[l1_linear_offset(addr)]);
         /* Toss the writable pagetable state and crash. */
-        unmap_domain_page(d->arch.ptwr[which].pl1e);
         d->arch.ptwr[which].l1va = 0;
         domain_crash(d);
         return 0;
index 0189c737f33090f9ae3b1a077d39336bf480b755..f835beee52f4ad5bcc6b31a5f30408dd6cea1183 100644 (file)
@@ -40,7 +40,6 @@ void *map_domain_page(unsigned long pfn)
     cache = &d->arch.mapcache;
 
     hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)];
-#if 0
     if ( hashent->pfn == pfn )
     {
         idx = hashent->idx;
@@ -49,7 +48,6 @@ void *map_domain_page(unsigned long pfn)
         ASSERT(l1e_get_pfn(cache->l1tab[idx]) == pfn);
         goto out;
     }
-#endif
 
     spin_lock(&cache->lock);
 
@@ -92,7 +90,7 @@ void *map_domain_page(unsigned long pfn)
 
     cache->l1tab[idx] = l1e_from_pfn(pfn, __PAGE_HYPERVISOR);
 
-/*out:*/
+ out:
     va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT);
     return (void *)va;
 }
index 9ec0e16e738fb888599930501dc2bf580a20b4cb..2e0937ea2dfdc5d9e4a30eed6cfbd1a46ee3f33f 100644 (file)
@@ -309,16 +309,13 @@ struct ptwr_info {
     unsigned long l1va;
     /* Copy of the p.t. page, taken before guest is given write access. */
     l1_pgentry_t *page;
-    /* A temporary Xen mapping of the actual p.t. page. */
-    l1_pgentry_t *pl1e;
     /* Index in L2 page table where this L1 p.t. is always hooked. */
     unsigned int l2_idx; /* NB. Only used for PTWR_PT_ACTIVE. */
     /* Info about last ptwr update batch. */
     unsigned int prev_nr_updates;
-    /* Exec domain which created writable mapping. */
+    /* VCPU which created writable mapping. */
     struct vcpu *vcpu;
-    /* EIP of the address which took the original write fault
-       used for stats collection only */
+    /* EIP of the original write fault (stats collection only). */
     unsigned long eip;
 };