[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Shadow: tidy the virtual-TLB translation cache.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1198059114 0
# Node ID 9d447ba0c99af9d6ad842b30079163cd05f1939a
# Parent  0335b9fe2f1003c0c10f081748cb567164ea9361
Shadow: tidy the virtual-TLB translation cache.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
 xen/arch/x86/mm/shadow/multi.c   |   19 +++++++++++--------
 xen/arch/x86/mm/shadow/private.h |   32 +++++++++++++++++---------------
 xen/arch/x86/mm/shadow/types.h   |   38 --------------------------------------
 3 files changed, 28 insertions(+), 61 deletions(-)

diff -r 0335b9fe2f10 -r 9d447ba0c99a xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Wed Dec 19 10:10:37 2007 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c    Wed Dec 19 10:11:54 2007 +0000
@@ -2829,6 +2829,12 @@ static int sh_page_fault(struct vcpu *v,
         goto not_a_shadow_fault;
     }
 
+#if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
+    /* Remember this successful VA->GFN translation for later. */
+    vtlb_insert(v, va >> PAGE_SHIFT, gfn_x(gfn), 
+                regs->error_code | PFEC_page_present);
+#endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
+
     /* Make sure there is enough free shadow memory to build a chain of
      * shadow tables. (We never allocate a top-level shadow on this path,
      * only a 32b l1, pae l1, or 64b l3+2+1. Note that while
@@ -3113,10 +3119,10 @@ sh_gva_to_gfn(struct vcpu *v, unsigned l
     gfn_t gfn;
 
 #if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
-    struct shadow_vtlb t = {0};
     /* Check the vTLB cache first */
-    if ( vtlb_lookup(v, va, pfec[0], &t) ) 
-        return t.frame_number;
+    unsigned long vtlb_gfn = vtlb_lookup(v, va, pfec[0]);
+    if ( VALID_GFN(vtlb_gfn) ) 
+        return vtlb_gfn;
 #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
 
     if ( guest_walk_tables(v, va, &gw, pfec[0], 0) != 0 )
@@ -3128,11 +3134,8 @@ sh_gva_to_gfn(struct vcpu *v, unsigned l
     gfn = guest_walk_to_gfn(&gw);
 
 #if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
-    t.page_number = va >> PAGE_SHIFT;
-    t.frame_number = gfn_x(gfn);
-    t.flags = accumulate_guest_flags(v, &gw); 
-    t.pfec = pfec[0];
-    vtlb_insert(v, t);
+    /* Remember this successful VA->GFN translation for later. */
+    vtlb_insert(v, va >> PAGE_SHIFT, gfn_x(gfn), pfec[0]);
 #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
 
     return gfn_x(gfn);
diff -r 0335b9fe2f10 -r 9d447ba0c99a xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Wed Dec 19 10:10:37 2007 +0000
+++ b/xen/arch/x86/mm/shadow/private.h  Wed Dec 19 10:11:54 2007 +0000
@@ -688,8 +688,7 @@ void shadow_continue_emulation(
  *
  * We keep a cache of virtual-to-physical translations that we have seen 
  * since the last TLB flush.  This is safe to use for frame translations, 
- * but callers that use the rights need to re-check the actual guest tables
- * before triggering a fault.
+ * but callers need to re-check the actual guest tables if the lookup fails.
  * 
  * Lookups and updates are protected by a per-vTLB (and hence per-vcpu)
  * lock.  This lock is held *only* while reading or writing the table,
@@ -702,8 +701,9 @@ struct shadow_vtlb {
 struct shadow_vtlb {
     unsigned long page_number;      /* Guest virtual address >> PAGE_SHIFT  */
     unsigned long frame_number;     /* Guest physical address >> PAGE_SHIFT */
-    uint32_t pfec;  /* Pagefault code for the lookup that filled this entry */
-    uint32_t flags; /* Accumulated guest pte flags, or 0 for an empty slot. */
+    uint32_t pfec;     /* PF error code of the lookup that filled this
+                        * entry.  A pfec of zero means the slot is empty
+                        * (since that would require us to re-try anyway) */
 };
 
 /* Call whenever the guest flushes hit actual TLB */
@@ -720,32 +720,34 @@ static inline int vtlb_hash(unsigned lon
 }
 
 /* Put a translation into the vTLB, potentially clobbering an old one */
-static inline void vtlb_insert(struct vcpu *v, struct shadow_vtlb entry)
-{
+static inline void vtlb_insert(struct vcpu *v, unsigned long page,
+                               unsigned long frame, uint32_t pfec)
+{
+    struct shadow_vtlb entry = 
+        { .page_number = page, .frame_number = frame, .pfec = pfec };
     spin_lock(&v->arch.paging.vtlb_lock);
-    v->arch.paging.vtlb[vtlb_hash(entry.page_number)] = entry;
+    v->arch.paging.vtlb[vtlb_hash(page)] = entry;
     spin_unlock(&v->arch.paging.vtlb_lock);
 }
 
-/* Look a translation up in the vTLB.  Returns 0 if not found. */
-static inline int vtlb_lookup(struct vcpu *v, unsigned long va, uint32_t pfec,
-                              struct shadow_vtlb *result) 
+/* Look a translation up in the vTLB.  Returns INVALID_GFN if not found. */
+static inline unsigned long vtlb_lookup(struct vcpu *v,
+                                        unsigned long va, uint32_t pfec)
 {
     unsigned long page_number = va >> PAGE_SHIFT;
-    int rv = 0;
+    unsigned long frame_number = INVALID_GFN;
     int i = vtlb_hash(page_number);
 
     spin_lock(&v->arch.paging.vtlb_lock);
-    if ( v->arch.paging.vtlb[i].flags != 0 
+    if ( v->arch.paging.vtlb[i].pfec != 0
          && v->arch.paging.vtlb[i].page_number == page_number 
          /* Any successful walk that had at least these pfec bits is OK */
          && (v->arch.paging.vtlb[i].pfec & pfec) == pfec )
     {
-        rv = 1; 
-        result[0] = v->arch.paging.vtlb[i];
+        frame_number = v->arch.paging.vtlb[i].frame_number;
     }
     spin_unlock(&v->arch.paging.vtlb_lock);
-    return rv;
+    return frame_number;
 }
 #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
 
diff -r 0335b9fe2f10 -r 9d447ba0c99a xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h    Wed Dec 19 10:10:37 2007 +0000
+++ b/xen/arch/x86/mm/shadow/types.h    Wed Dec 19 10:11:54 2007 +0000
@@ -527,44 +527,6 @@ struct shadow_walk_t
 #endif
 #endif /* GUEST_PAGING_LEVELS >= 3 */
 
-static inline u32
-accumulate_guest_flags(struct vcpu *v, walk_t *gw)
-{
-    u32 accumulated_flags;
-
-    if ( unlikely(!(guest_l1e_get_flags(gw->l1e) & _PAGE_PRESENT)) )
-        return 0;
-        
-    // We accumulate the permission flags with bitwise ANDing.
-    // This works for the PRESENT bit, RW bit, and USER bit.
-    // For the NX bit, however, the polarity is wrong, so we accumulate the
-    // inverse of the NX bit.
-    //
-    accumulated_flags =  guest_l1e_get_flags(gw->l1e) ^ _PAGE_NX_BIT;
-    accumulated_flags &= guest_l2e_get_flags(gw->l2e) ^ _PAGE_NX_BIT;
-
-    // Note that PAE guests do not have USER or RW or NX bits in their L3s.
-    //
-#if GUEST_PAGING_LEVELS == 3
-    accumulated_flags &=
-        ~_PAGE_PRESENT | (guest_l3e_get_flags(gw->l3e) & _PAGE_PRESENT);
-#elif GUEST_PAGING_LEVELS >= 4
-    accumulated_flags &= guest_l3e_get_flags(gw->l3e) ^ _PAGE_NX_BIT;
-    accumulated_flags &= guest_l4e_get_flags(gw->l4e) ^ _PAGE_NX_BIT;
-#endif
-
-    // Revert the NX bit back to its original polarity
-    accumulated_flags ^= _PAGE_NX_BIT;
-
-    // In 64-bit PV guests, the _PAGE_USER bit is implied in all guest
-    // entries (since even the guest kernel runs in ring 3).
-    //
-    if ( (GUEST_PAGING_LEVELS == 4) && !is_hvm_vcpu(v) )
-        accumulated_flags |= _PAGE_USER;
-
-    return accumulated_flags;
-}
-
 
 #if (SHADOW_OPTIMIZATIONS & SHOPT_FAST_FAULT_PATH) && SHADOW_PAGING_LEVELS > 2
 /******************************************************************************

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.