direct-io.hg

changeset 12451:11a93cc59159

[XEN] Track high-water-mark of p2m map
and so avoid some unnecessary __copy_from_user faults.
Also tidy the p2m functions generally.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Wed Nov 15 14:36:10 2006 +0000 (2006-11-15)
parents 6e22ba721720
children 85f331c7af76
files xen/arch/x86/mm/shadow/common.c xen/arch/x86/mm/shadow/types.h xen/include/asm-x86/domain.h xen/include/asm-x86/hvm/io.h xen/include/asm-x86/mm.h xen/include/asm-x86/shadow.h
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/common.c	Wed Nov 15 09:44:12 2006 +0000
     1.2 +++ b/xen/arch/x86/mm/shadow/common.c	Wed Nov 15 14:36:10 2006 +0000
     1.3 @@ -1047,6 +1047,10 @@ shadow_set_p2m_entry(struct domain *d, u
     1.4      else
     1.5          *p2m_entry = l1e_empty();
     1.6  
     1.7 +    /* Track the highest gfn for which we have ever had a valid mapping */
     1.8 +    if ( valid_mfn(mfn) && (gfn > d->arch.max_mapped_pfn) ) 
     1.9 +        d->arch.max_mapped_pfn = gfn;
    1.10 +
    1.11      /* The P2M can be shadowed: keep the shadows synced */
    1.12      if ( d->vcpu[0] != NULL )
    1.13          (void)__shadow_validate_guest_entry(
    1.14 @@ -1142,12 +1146,9 @@ sh_gfn_to_mfn_foreign(struct domain *d, 
    1.15      mfn = pagetable_get_mfn(d->arch.phys_table);
    1.16  
    1.17  
    1.18 -#if CONFIG_PAGING_LEVELS > 2
    1.19 -    if ( gpfn >= (RO_MPT_VIRT_END-RO_MPT_VIRT_START) / sizeof(l1_pgentry_t) ) 
    1.20 -        /* This pfn is higher than the p2m map can hold */
    1.21 +    if ( gpfn > d->arch.max_mapped_pfn ) 
    1.22 +        /* This pfn is higher than the highest the p2m map currently holds */
    1.23          return _mfn(INVALID_MFN);
    1.24 -#endif
    1.25 -
    1.26  
    1.27  #if CONFIG_PAGING_LEVELS >= 4
    1.28      { 
    1.29 @@ -3333,13 +3334,14 @@ void shadow_audit_p2m(struct domain *d)
    1.30              set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
    1.31          }
    1.32  
    1.33 -        if ( test_linear )
    1.34 +        if ( test_linear && (gfn <= d->arch.max_mapped_pfn) )
    1.35          {
    1.36 -            lp2mfn = get_mfn_from_gpfn(gfn);
    1.37 -            if ( lp2mfn != mfn_x(p2mfn) )
    1.38 +            lp2mfn = gfn_to_mfn_current(gfn);
    1.39 +            if ( mfn_x(lp2mfn) != mfn_x(p2mfn) )
    1.40              {
    1.41                  SHADOW_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
    1.42 -                               "(!= mfn %#lx)\n", gfn, lp2mfn, p2mfn);
    1.43 +                              "(!= mfn %#lx)\n", gfn, 
    1.44 +                              mfn_x(lp2mfn), mfn_x(p2mfn));
    1.45              }
    1.46          }
    1.47  
     2.1 --- a/xen/arch/x86/mm/shadow/types.h	Wed Nov 15 09:44:12 2006 +0000
     2.2 +++ b/xen/arch/x86/mm/shadow/types.h	Wed Nov 15 14:36:10 2006 +0000
     2.3 @@ -416,9 +416,7 @@ vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gf
     2.4  {
     2.5      if ( !shadow_vcpu_mode_translate(v) )
     2.6          return _mfn(gfn_x(gfn));
     2.7 -    if ( likely(current->domain == v->domain) )
     2.8 -        return _mfn(get_mfn_from_gpfn(gfn_x(gfn)));
     2.9 -    return sh_gfn_to_mfn_foreign(v->domain, gfn_x(gfn));
    2.10 +    return sh_gfn_to_mfn(v->domain, gfn_x(gfn));
    2.11  }
    2.12  
    2.13  static inline gfn_t
     3.1 --- a/xen/include/asm-x86/domain.h	Wed Nov 15 09:44:12 2006 +0000
     3.2 +++ b/xen/include/asm-x86/domain.h	Wed Nov 15 14:36:10 2006 +0000
     3.3 @@ -111,6 +111,8 @@ struct arch_domain
     3.4  
     3.5      /* Shadow translated domain: P2M mapping */
     3.6      pagetable_t phys_table;
     3.7 +    /* Highest guest frame that's ever been mapped in the p2m */
     3.8 +    unsigned long max_mapped_pfn;
     3.9  
    3.10  } __cacheline_aligned;
    3.11  
     4.1 --- a/xen/include/asm-x86/hvm/io.h	Wed Nov 15 09:44:12 2006 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/io.h	Wed Nov 15 14:36:10 2006 +0000
     4.3 @@ -151,8 +151,5 @@ extern void pic_irq_request(void *data, 
     4.4  extern int cpu_get_interrupt(struct vcpu *v, int *type);
     4.5  extern int cpu_has_pending_irq(struct vcpu *v);
     4.6  
     4.7 -// XXX - think about this, maybe use bit 30 of the mfn to signify an MMIO frame.
     4.8 -#define mmio_space(gpa) (!VALID_MFN(get_mfn_from_gpfn((gpa) >> PAGE_SHIFT)))
     4.9 -
    4.10  #endif /* __ASM_X86_HVM_IO_H__ */
    4.11  
     5.1 --- a/xen/include/asm-x86/mm.h	Wed Nov 15 09:44:12 2006 +0000
     5.2 +++ b/xen/include/asm-x86/mm.h	Wed Nov 15 14:36:10 2006 +0000
     5.3 @@ -304,37 +304,9 @@ int check_descriptor(struct desc_struct 
     5.4  
     5.5  #define gmfn_to_mfn(_d, gpfn)  mfn_x(sh_gfn_to_mfn(_d, gpfn))
     5.6  
     5.7 -
     5.8 -/*
     5.9 - * The phys_to_machine_mapping is the reversed mapping of MPT for full
    5.10 - * virtualization.  It is only used by shadow_mode_translate()==true
    5.11 - * guests, so we steal the address space that would have normally
    5.12 - * been used by the read-only MPT map.
    5.13 - */
    5.14 -#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START)
    5.15  #define INVALID_MFN             (~0UL)
    5.16  #define VALID_MFN(_mfn)         (!((_mfn) & (1U<<31)))
    5.17  
    5.18 -static inline unsigned long get_mfn_from_gpfn(unsigned long pfn)
    5.19 -{
    5.20 -    l1_pgentry_t l1e = l1e_empty();
    5.21 -    int ret;
    5.22 -
    5.23 -#if CONFIG_PAGING_LEVELS > 2
    5.24 -    if ( pfn >= (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t) ) 
    5.25 -        /* This pfn is higher than the p2m map can hold */
    5.26 -        return INVALID_MFN;
    5.27 -#endif
    5.28 -
    5.29 -    ret = __copy_from_user(&l1e,
    5.30 -                               &phys_to_machine_mapping[pfn],
    5.31 -                               sizeof(l1e));
    5.32 -
    5.33 -    if ( (ret == 0) && (l1e_get_flags(l1e) & _PAGE_PRESENT) )
    5.34 -        return l1e_get_pfn(l1e);
    5.35 -
    5.36 -    return INVALID_MFN;
    5.37 -}
    5.38  
    5.39  #ifdef MEMORY_GUARD
    5.40  void memguard_init(void);
     6.1 --- a/xen/include/asm-x86/shadow.h	Wed Nov 15 09:44:12 2006 +0000
     6.2 +++ b/xen/include/asm-x86/shadow.h	Wed Nov 15 14:36:10 2006 +0000
     6.3 @@ -663,12 +663,40 @@ struct shadow_walk_cache {
     6.4  
     6.5  
     6.6  /**************************************************************************/
     6.7 -/* Guest physmap (p2m) support */
     6.8 +/* Guest physmap (p2m) support 
     6.9 + *
    6.10 + * The phys_to_machine_mapping is the reversed mapping of MPT for full
    6.11 + * virtualization.  It is only used by shadow_mode_translate()==true
    6.12 + * guests, so we steal the address space that would have normally
    6.13 + * been used by the read-only MPT map.
    6.14 + */
    6.15 +
    6.16 +#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START)
    6.17 +
    6.18 +/* Read the current domain's P2M table. */
    6.19 +static inline mfn_t sh_gfn_to_mfn_current(unsigned long gfn)
    6.20 +{
    6.21 +    l1_pgentry_t l1e = l1e_empty();
    6.22 +    int ret;
    6.23 +
    6.24 +    if ( gfn > current->domain->arch.max_mapped_pfn )
    6.25 +        return _mfn(INVALID_MFN);
    6.26 +
    6.27 +    /* Don't read off the end of the p2m table */
    6.28 +    ASSERT(gfn < (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t));
    6.29 +
    6.30 +    ret = __copy_from_user(&l1e,
    6.31 +                           &phys_to_machine_mapping[gfn],
    6.32 +                           sizeof(l1e));
    6.33 +
    6.34 +    if ( (ret == 0) && (l1e_get_flags(l1e) & _PAGE_PRESENT) )
    6.35 +        return _mfn(l1e_get_pfn(l1e));
    6.36 +
    6.37 +    return _mfn(INVALID_MFN);
    6.38 +}
    6.39  
    6.40  /* Walk another domain's P2M table, mapping pages as we go */
    6.41 -extern mfn_t
    6.42 -sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
    6.43 -
    6.44 +extern mfn_t sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
    6.45  
    6.46  /* General conversion function from gfn to mfn */
    6.47  static inline mfn_t
    6.48 @@ -676,12 +704,19 @@ sh_gfn_to_mfn(struct domain *d, unsigned
    6.49  {
    6.50      if ( !shadow_mode_translate(d) )
    6.51          return _mfn(gfn);
    6.52 -    else if ( likely(current->domain == d) )
    6.53 -        return _mfn(get_mfn_from_gpfn(gfn));
    6.54 -    else
    6.55 +    if ( likely(current->domain == d) )
    6.56 +        return sh_gfn_to_mfn_current(gfn);
    6.57 +    else 
    6.58          return sh_gfn_to_mfn_foreign(d, gfn);
    6.59  }
    6.60  
    6.61 +/* Compatibility function for HVM code */
    6.62 +static inline unsigned long get_mfn_from_gpfn(unsigned long pfn)
    6.63 +{
    6.64 +    return mfn_x(sh_gfn_to_mfn_current(pfn));
    6.65 +}
    6.66 +
    6.67 +/* General conversion function from mfn to gfn */
    6.68  static inline unsigned long
    6.69  sh_mfn_to_gfn(struct domain *d, mfn_t mfn)
    6.70  {
    6.71 @@ -691,6 +726,14 @@ sh_mfn_to_gfn(struct domain *d, mfn_t mf
    6.72          return mfn_x(mfn);
    6.73  }
    6.74  
    6.75 +/* Is this guest address an mmio one? (i.e. not defined in p2m map) */
    6.76 +static inline int
    6.77 +mmio_space(paddr_t gpa)
    6.78 +{
    6.79 +    unsigned long gfn = gpa >> PAGE_SHIFT;    
    6.80 +    return !VALID_MFN(mfn_x(sh_gfn_to_mfn_current(gfn)));
    6.81 +}
    6.82 +
    6.83  static inline l1_pgentry_t
    6.84  gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e)
    6.85  {