ia64/xen-unstable

changeset 19167:5fd1a6951801

x86: EPT cleanups.

Signed-off-by: Xin, Xiaohui <xiaohui.xin@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 05 12:12:34 2009 +0000 (2009-02-05)
parents 416197f0292b
children 4c92a04f4f5e
files xen/arch/x86/mm/hap/p2m-ept.c xen/include/asm-x86/hvm/vmx/vmx.h
line diff
     1.1 --- a/xen/arch/x86/mm/hap/p2m-ept.c	Thu Feb 05 12:09:10 2009 +0000
     1.2 +++ b/xen/arch/x86/mm/hap/p2m-ept.c	Thu Feb 05 12:12:34 2009 +0000
     1.3 @@ -116,12 +116,12 @@ static int ept_next_level(struct domain 
     1.4  }
     1.5  
     1.6  /*
     1.7 - * TODO: ept_set_entry() computes 'need_modify_vtd_table' for itself,
     1.8 + * ept_set_entry() computes 'need_modify_vtd_table' for itself,
     1.9   * by observing whether any gfn->mfn translations are modified.
    1.10   */
    1.11  static int
    1.12 -_ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, 
    1.13 -              unsigned int order, p2m_type_t p2mt, int need_modify_vtd_table)
    1.14 +ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, 
    1.15 +              unsigned int order, p2m_type_t p2mt)
    1.16  {
    1.17      ept_entry_t *table = NULL;
    1.18      unsigned long gfn_remainder = gfn, offset = 0;
    1.19 @@ -131,6 +131,7 @@ static int
    1.20      int walk_level = order / EPT_TABLE_ORDER;
    1.21      int direct_mmio = (p2mt == p2m_mmio_direct);
    1.22      uint8_t igmt = 0;
    1.23 +    int need_modify_vtd_table = 1;
    1.24  
    1.25      /* we only support 4k and 2m pages now */
    1.26  
    1.27 @@ -171,14 +172,23 @@ static int
    1.28  
    1.29              if ( ret == GUEST_TABLE_SUPER_PAGE )
    1.30              {
    1.31 -                ept_entry->mfn = mfn_x(mfn) - offset;
    1.32 +                if ( ept_entry->mfn == (mfn_x(mfn) - offset) )
    1.33 +                    need_modify_vtd_table = 0;  
    1.34 +                else                  
    1.35 +                    ept_entry->mfn = mfn_x(mfn) - offset;
    1.36 +
    1.37                  if ( ept_entry->avail1 == p2m_ram_logdirty &&
    1.38                    p2mt == p2m_ram_rw )
    1.39                      for ( i = 0; i < 512; i++ )
    1.40                          paging_mark_dirty(d, mfn_x(mfn)-offset+i);
    1.41              }
    1.42              else
    1.43 -                ept_entry->mfn = mfn_x(mfn);
    1.44 +            {
    1.45 +                if ( ept_entry->mfn == mfn_x(mfn) )
    1.46 +                    need_modify_vtd_table = 0;
    1.47 +                else
    1.48 +                    ept_entry->mfn = mfn_x(mfn);
    1.49 +            }
    1.50  
    1.51              ept_entry->avail1 = p2mt;
    1.52              ept_entry->rsvd = 0;
    1.53 @@ -239,7 +249,10 @@ static int
    1.54                                                  &igmt, direct_mmio);
    1.55          split_ept_entry->igmt = igmt;
    1.56  
    1.57 -        split_ept_entry->mfn = mfn_x(mfn);
    1.58 +        if ( split_ept_entry->mfn == mfn_x(mfn) )
    1.59 +            need_modify_vtd_table = 0;
    1.60 +        else
    1.61 +            split_ept_entry->mfn = mfn_x(mfn);
    1.62          split_ept_entry->avail1 = p2mt;
    1.63          ept_p2m_type_to_flags(split_ept_entry, p2mt);
    1.64  
    1.65 @@ -289,17 +302,6 @@ out:
    1.66      return rv;
    1.67  }
    1.68  
    1.69 -static int
    1.70 -ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
    1.71 -              unsigned int order, p2m_type_t p2mt)
    1.72 -{
    1.73 -    /* ept_set_entry() are called from set_entry(),
    1.74 -     * We should always create VT-d page table acording 
    1.75 -     * to the gfn to mfn translations changes.
    1.76 -     */
    1.77 -    return _ept_set_entry(d, gfn, mfn, order, p2mt, 1); 
    1.78 -}
    1.79 -
    1.80  /* Read ept p2m entries */
    1.81  static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
    1.82      p2m_query_t q)
    1.83 @@ -393,6 +395,21 @@ static mfn_t ept_get_entry_current(unsig
    1.84      return ept_get_entry(current->domain, gfn, t, q);
    1.85  }
    1.86  
    1.87 +/* To test if the new emt type is the same with old,
    1.88 + * return 1 to not to reset ept entry.
    1.89 + */
    1.90 +static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
    1.91 +                                    unsigned long mfn, uint8_t o_igmt,
    1.92 +                                    uint8_t o_emt, p2m_type_t p2mt)
    1.93 +{
    1.94 +    uint8_t igmt, emt;
    1.95 +    emt = epte_get_entry_emt(d, gfn, mfn, &igmt, 
    1.96 +                                (p2mt == p2m_mmio_direct));
    1.97 +    if ( (emt == o_emt) && (igmt == o_igmt) )
    1.98 +        return 0;
    1.99 +    return 1; 
   1.100 +}
   1.101 +
   1.102  void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
   1.103                   unsigned long end_gfn)
   1.104  {
   1.105 @@ -401,6 +418,7 @@ void ept_change_entry_emt_with_range(str
   1.106      uint64_t epte;
   1.107      int order = 0;
   1.108      unsigned long mfn;
   1.109 +    uint8_t o_igmt, o_emt;
   1.110  
   1.111      for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
   1.112      {
   1.113 @@ -410,7 +428,9 @@ void ept_change_entry_emt_with_range(str
   1.114          mfn = (epte & EPTE_MFN_MASK) >> PAGE_SHIFT;
   1.115          if ( !mfn_valid(mfn) )
   1.116              continue;
   1.117 -        p2mt = (epte & EPTE_AVAIL1_MASK) >> 8;
   1.118 +        p2mt = (epte & EPTE_AVAIL1_MASK) >> EPTE_AVAIL1_SHIFT;
   1.119 +        o_igmt = (epte & EPTE_IGMT_MASK) >> EPTE_IGMT_SHIFT;
   1.120 +        o_emt = (epte & EPTE_EMT_MASK) >> EPTE_EMT_SHIFT;
   1.121          order = 0;
   1.122  
   1.123          if ( epte & EPTE_SUPER_PAGE_MASK )
   1.124 @@ -422,30 +442,26 @@ void ept_change_entry_emt_with_range(str
   1.125                   * Set emt for super page.
   1.126                   */
   1.127                  order = EPT_TABLE_ORDER;
   1.128 -                /* vmx_set_uc_mode() dont' touch the gfn to mfn
   1.129 -                 * translations, only modify the emt field of the EPT entries.
   1.130 -                 * so we need not modify the current VT-d page tables.
   1.131 -                 */
   1.132 -                _ept_set_entry(d, gfn, _mfn(mfn), order, p2mt, 0);
   1.133 +                if ( need_modify_ept_entry(d, gfn, mfn, 
   1.134 +                                            o_igmt, o_emt, p2mt) )
   1.135 +                    ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
   1.136                  gfn += 0x1FF;
   1.137              }
   1.138              else
   1.139              {
   1.140 -                /* 1)change emt for partial entries of the 2m area.
   1.141 -                 * 2)vmx_set_uc_mode() dont' touch the gfn to mfn
   1.142 -                 * translations, only modify the emt field of the EPT entries.
   1.143 -                 * so we need not modify the current VT-d page tables.
   1.144 -                 */
   1.145 -                _ept_set_entry(d, gfn, _mfn(mfn), order, p2mt,0);
   1.146 +                /* change emt for partial entries of the 2m area. */
   1.147 +                if ( need_modify_ept_entry(d, gfn, mfn, 
   1.148 +                                            o_igmt, o_emt, p2mt) )
   1.149 +                    ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
   1.150                  gfn = ((gfn >> EPT_TABLE_ORDER) << EPT_TABLE_ORDER) + 0x1FF;
   1.151              }
   1.152          }
   1.153 -        else /* 1)gfn assigned with 4k
   1.154 -              * 2)vmx_set_uc_mode() dont' touch the gfn to mfn
   1.155 -              * translations, only modify the emt field of the EPT entries.
   1.156 -              * so we need not modify the current VT-d page tables.
   1.157 -             */
   1.158 -            _ept_set_entry(d, gfn, _mfn(mfn), order, p2mt, 0);
   1.159 +        else /* gfn assigned with 4k */
   1.160 +        {
   1.161 +            if ( need_modify_ept_entry(d, gfn, mfn, 
   1.162 +                                            o_igmt, o_emt, p2mt) )
   1.163 +                ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
   1.164 +        }
   1.165      }
   1.166  }
   1.167  
     2.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Thu Feb 05 12:09:10 2009 +0000
     2.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Thu Feb 05 12:12:34 2009 +0000
     2.3 @@ -48,7 +48,11 @@ typedef union {
     2.4  #define EPTE_SUPER_PAGE_MASK    0x80
     2.5  #define EPTE_MFN_MASK           0x1fffffffffff000
     2.6  #define EPTE_AVAIL1_MASK        0xF00
     2.7 -#define EPTE_EMT_MASK           0x78
     2.8 +#define EPTE_EMT_MASK           0x38
     2.9 +#define EPTE_IGMT_MASK          0x40
    2.10 +#define EPTE_AVAIL1_SHIFT       8
    2.11 +#define EPTE_EMT_SHIFT          3
    2.12 +#define EPTE_IGMT_SHIFT         6
    2.13  
    2.14  void vmx_asm_vmexit_handler(struct cpu_user_regs);
    2.15  void vmx_asm_do_vmentry(void);