ia64/xen-unstable

changeset 16635:9d447ba0c99a

Shadow: tidy the virtual-TLB translation cache.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 19 10:11:54 2007 +0000 (2007-12-19)
parents 0335b9fe2f10
children 181483b8e959
files xen/arch/x86/mm/shadow/multi.c xen/arch/x86/mm/shadow/private.h xen/arch/x86/mm/shadow/types.h
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/multi.c	Wed Dec 19 10:10:37 2007 +0000
     1.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Wed Dec 19 10:11:54 2007 +0000
     1.3 @@ -2829,6 +2829,12 @@ static int sh_page_fault(struct vcpu *v,
     1.4          goto not_a_shadow_fault;
     1.5      }
     1.6  
     1.7 +#if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
     1.8 +    /* Remember this successful VA->GFN translation for later. */
     1.9 +    vtlb_insert(v, va >> PAGE_SHIFT, gfn_x(gfn), 
    1.10 +                regs->error_code | PFEC_page_present);
    1.11 +#endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
    1.12 +
    1.13      /* Make sure there is enough free shadow memory to build a chain of
    1.14       * shadow tables. (We never allocate a top-level shadow on this path,
    1.15       * only a 32b l1, pae l1, or 64b l3+2+1. Note that while
    1.16 @@ -3113,10 +3119,10 @@ sh_gva_to_gfn(struct vcpu *v, unsigned l
    1.17      gfn_t gfn;
    1.18  
    1.19  #if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
    1.20 -    struct shadow_vtlb t = {0};
    1.21      /* Check the vTLB cache first */
    1.22 -    if ( vtlb_lookup(v, va, pfec[0], &t) ) 
    1.23 -        return t.frame_number;
    1.24 +    unsigned long vtlb_gfn = vtlb_lookup(v, va, pfec[0]);
    1.25 +    if ( VALID_GFN(vtlb_gfn) ) 
    1.26 +        return vtlb_gfn;
    1.27  #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
    1.28  
    1.29      if ( guest_walk_tables(v, va, &gw, pfec[0], 0) != 0 )
    1.30 @@ -3128,11 +3134,8 @@ sh_gva_to_gfn(struct vcpu *v, unsigned l
    1.31      gfn = guest_walk_to_gfn(&gw);
    1.32  
    1.33  #if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
    1.34 -    t.page_number = va >> PAGE_SHIFT;
    1.35 -    t.frame_number = gfn_x(gfn);
    1.36 -    t.flags = accumulate_guest_flags(v, &gw); 
    1.37 -    t.pfec = pfec[0];
    1.38 -    vtlb_insert(v, t);
    1.39 +    /* Remember this successful VA->GFN translation for later. */
    1.40 +    vtlb_insert(v, va >> PAGE_SHIFT, gfn_x(gfn), pfec[0]);
    1.41  #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
    1.42  
    1.43      return gfn_x(gfn);
     2.1 --- a/xen/arch/x86/mm/shadow/private.h	Wed Dec 19 10:10:37 2007 +0000
     2.2 +++ b/xen/arch/x86/mm/shadow/private.h	Wed Dec 19 10:11:54 2007 +0000
     2.3 @@ -688,8 +688,7 @@ void shadow_continue_emulation(
     2.4   *
     2.5   * We keep a cache of virtual-to-physical translations that we have seen 
     2.6   * since the last TLB flush.  This is safe to use for frame translations, 
     2.7 - * but callers that use the rights need to re-check the actual guest tables
     2.8 - * before triggering a fault.
     2.9 + * but callers need to re-check the actual guest tables if the lookup fails.
    2.10   * 
    2.11   * Lookups and updates are protected by a per-vTLB (and hence per-vcpu)
    2.12   * lock.  This lock is held *only* while reading or writing the table,
    2.13 @@ -702,8 +701,9 @@ void shadow_continue_emulation(
    2.14  struct shadow_vtlb {
    2.15      unsigned long page_number;      /* Guest virtual address >> PAGE_SHIFT  */
    2.16      unsigned long frame_number;     /* Guest physical address >> PAGE_SHIFT */
    2.17 -    uint32_t pfec;  /* Pagefault code for the lookup that filled this entry */
    2.18 -    uint32_t flags; /* Accumulated guest pte flags, or 0 for an empty slot. */
    2.19 +    uint32_t pfec;     /* PF error code of the lookup that filled this
    2.20 +                        * entry.  A pfec of zero means the slot is empty
    2.21 +                        * (since that would require us to re-try anyway) */
    2.22  };
    2.23  
    2.24  /* Call whenever the guest flushes hit actual TLB */
    2.25 @@ -720,32 +720,34 @@ static inline int vtlb_hash(unsigned lon
    2.26  }
    2.27  
    2.28  /* Put a translation into the vTLB, potentially clobbering an old one */
    2.29 -static inline void vtlb_insert(struct vcpu *v, struct shadow_vtlb entry)
    2.30 +static inline void vtlb_insert(struct vcpu *v, unsigned long page,
    2.31 +                               unsigned long frame, uint32_t pfec)
    2.32  {
    2.33 +    struct shadow_vtlb entry = 
    2.34 +        { .page_number = page, .frame_number = frame, .pfec = pfec };
    2.35      spin_lock(&v->arch.paging.vtlb_lock);
    2.36 -    v->arch.paging.vtlb[vtlb_hash(entry.page_number)] = entry;
    2.37 +    v->arch.paging.vtlb[vtlb_hash(page)] = entry;
    2.38      spin_unlock(&v->arch.paging.vtlb_lock);
    2.39  }
    2.40  
    2.41 -/* Look a translation up in the vTLB.  Returns 0 if not found. */
    2.42 -static inline int vtlb_lookup(struct vcpu *v, unsigned long va, uint32_t pfec,
    2.43 -                              struct shadow_vtlb *result) 
    2.44 +/* Look a translation up in the vTLB.  Returns INVALID_GFN if not found. */
    2.45 +static inline unsigned long vtlb_lookup(struct vcpu *v,
    2.46 +                                        unsigned long va, uint32_t pfec)
    2.47  {
    2.48      unsigned long page_number = va >> PAGE_SHIFT;
    2.49 -    int rv = 0;
    2.50 +    unsigned long frame_number = INVALID_GFN;
    2.51      int i = vtlb_hash(page_number);
    2.52  
    2.53      spin_lock(&v->arch.paging.vtlb_lock);
    2.54 -    if ( v->arch.paging.vtlb[i].flags != 0 
    2.55 +    if ( v->arch.paging.vtlb[i].pfec != 0
    2.56           && v->arch.paging.vtlb[i].page_number == page_number 
    2.57           /* Any successful walk that had at least these pfec bits is OK */
    2.58           && (v->arch.paging.vtlb[i].pfec & pfec) == pfec )
    2.59      {
    2.60 -        rv = 1; 
    2.61 -        result[0] = v->arch.paging.vtlb[i];
    2.62 +        frame_number = v->arch.paging.vtlb[i].frame_number;
    2.63      }
    2.64      spin_unlock(&v->arch.paging.vtlb_lock);
    2.65 -    return rv;
    2.66 +    return frame_number;
    2.67  }
    2.68  #endif /* (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB) */
    2.69  
     3.1 --- a/xen/arch/x86/mm/shadow/types.h	Wed Dec 19 10:10:37 2007 +0000
     3.2 +++ b/xen/arch/x86/mm/shadow/types.h	Wed Dec 19 10:11:54 2007 +0000
     3.3 @@ -527,44 +527,6 @@ struct shadow_walk_t
     3.4  #endif
     3.5  #endif /* GUEST_PAGING_LEVELS >= 3 */
     3.6  
     3.7 -static inline u32
     3.8 -accumulate_guest_flags(struct vcpu *v, walk_t *gw)
     3.9 -{
    3.10 -    u32 accumulated_flags;
    3.11 -
    3.12 -    if ( unlikely(!(guest_l1e_get_flags(gw->l1e) & _PAGE_PRESENT)) )
    3.13 -        return 0;
    3.14 -        
    3.15 -    // We accumulate the permission flags with bitwise ANDing.
    3.16 -    // This works for the PRESENT bit, RW bit, and USER bit.
    3.17 -    // For the NX bit, however, the polarity is wrong, so we accumulate the
    3.18 -    // inverse of the NX bit.
    3.19 -    //
    3.20 -    accumulated_flags =  guest_l1e_get_flags(gw->l1e) ^ _PAGE_NX_BIT;
    3.21 -    accumulated_flags &= guest_l2e_get_flags(gw->l2e) ^ _PAGE_NX_BIT;
    3.22 -
    3.23 -    // Note that PAE guests do not have USER or RW or NX bits in their L3s.
    3.24 -    //
    3.25 -#if GUEST_PAGING_LEVELS == 3
    3.26 -    accumulated_flags &=
    3.27 -        ~_PAGE_PRESENT | (guest_l3e_get_flags(gw->l3e) & _PAGE_PRESENT);
    3.28 -#elif GUEST_PAGING_LEVELS >= 4
    3.29 -    accumulated_flags &= guest_l3e_get_flags(gw->l3e) ^ _PAGE_NX_BIT;
    3.30 -    accumulated_flags &= guest_l4e_get_flags(gw->l4e) ^ _PAGE_NX_BIT;
    3.31 -#endif
    3.32 -
    3.33 -    // Revert the NX bit back to its original polarity
    3.34 -    accumulated_flags ^= _PAGE_NX_BIT;
    3.35 -
    3.36 -    // In 64-bit PV guests, the _PAGE_USER bit is implied in all guest
    3.37 -    // entries (since even the guest kernel runs in ring 3).
    3.38 -    //
    3.39 -    if ( (GUEST_PAGING_LEVELS == 4) && !is_hvm_vcpu(v) )
    3.40 -        accumulated_flags |= _PAGE_USER;
    3.41 -
    3.42 -    return accumulated_flags;
    3.43 -}
    3.44 -
    3.45  
    3.46  #if (SHADOW_OPTIMIZATIONS & SHOPT_FAST_FAULT_PATH) && SHADOW_PAGING_LEVELS > 2
    3.47  /******************************************************************************