debuggers.hg
changeset 16673:9d447ba0c99a
Shadow: tidy the virtual-TLB translation cache.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
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 /******************************************************************************