ia64/xen-unstable

changeset 13915:a00b8d3800a8

[XEN] Snapshot PAE l3es when they are shadowed.
We don't update the shadows so we mustn't look at the guest l3es
or we'll be confused by them if they change.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Wed Feb 14 14:46:18 2007 +0000 (2007-02-14)
parents cbbd748c4b58
children 6fd71faaaa3b
files xen/arch/x86/hvm/svm/svm.c xen/arch/x86/mm.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/mm/shadow/page-guest32.h xen/arch/x86/mm/shadow/types.h xen/include/asm-x86/domain.h xen/include/asm-x86/page.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Feb 14 14:44:07 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Feb 14 14:46:18 2007 +0000
     1.3 @@ -2679,7 +2679,7 @@ void walk_shadow_and_guest_pt(unsigned l
     1.4      shadow_sync_va(v, gva);
     1.5  
     1.6      gpte.l1 = 0;
     1.7 -    __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ],
     1.8 +    __copy_from_user(&gpte, &__linear_l1_table[ l1_linear_offset(gva) ],
     1.9                       sizeof(gpte) );
    1.10      printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
    1.11  
     2.1 --- a/xen/arch/x86/mm.c	Wed Feb 14 14:44:07 2007 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Wed Feb 14 14:46:18 2007 +0000
     2.3 @@ -374,9 +374,6 @@ void write_ptbase(struct vcpu *v)
     2.4  /* Should be called after CR3 is updated.
     2.5   * Updates vcpu->arch.cr3 and, for HVM guests, vcpu->arch.hvm_vcpu.cpu_cr3.
     2.6   * 
     2.7 - * Also updates other state derived from CR3 (vcpu->arch.guest_vtable,
     2.8 - * shadow_vtable, etc).
     2.9 - *
    2.10   * Uses values found in vcpu->arch.(guest_table and guest_table_user), and
    2.11   * for HVM guests, arch.monitor_table and hvm's guest CR3.
    2.12   *
     3.1 --- a/xen/arch/x86/mm/shadow/multi.c	Wed Feb 14 14:44:07 2007 +0000
     3.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Wed Feb 14 14:46:18 2007 +0000
     3.3 @@ -237,7 +237,8 @@ guest_walk_tables(struct vcpu *v, unsign
     3.4  #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */
     3.5      /* Get l4e from the top level table */
     3.6      gw->l4mfn = pagetable_get_mfn(v->arch.guest_table);
     3.7 -    gw->l4e = (guest_l4e_t *)v->arch.guest_vtable + guest_l4_table_offset(va);
     3.8 +    gw->l4e = (guest_l4e_t *)v->arch.paging.shadow.guest_vtable 
     3.9 +        + guest_l4_table_offset(va);
    3.10      /* Walk down to the l3e */
    3.11      if ( !(guest_l4e_get_flags(*gw->l4e) & _PAGE_PRESENT) ) return 0;
    3.12      gw->l3mfn = vcpu_gfn_to_mfn(v, guest_l4e_get_gfn(*gw->l4e));
    3.13 @@ -248,9 +249,8 @@ guest_walk_tables(struct vcpu *v, unsign
    3.14      gw->l3e = ((guest_l3e_t *)sh_map_domain_page(gw->l3mfn))
    3.15          + guest_l3_table_offset(va);
    3.16  #else /* PAE only... */
    3.17 -    /* Get l3e from the top level table */
    3.18 -    gw->l3mfn = pagetable_get_mfn(v->arch.guest_table);
    3.19 -    gw->l3e = (guest_l3e_t *)v->arch.guest_vtable + guest_l3_table_offset(va);
    3.20 +    /* Get l3e from the cache of the guest's top level table */
    3.21 +    gw->l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e[guest_l3_table_offset(va)];
    3.22  #endif /* PAE or 64... */
    3.23      /* Walk down to the l2e */
    3.24      if ( !(guest_l3e_get_flags(*gw->l3e) & _PAGE_PRESENT) ) return 0;
    3.25 @@ -264,7 +264,8 @@ guest_walk_tables(struct vcpu *v, unsign
    3.26  #else /* 32-bit only... */
    3.27      /* Get l2e from the top level table */
    3.28      gw->l2mfn = pagetable_get_mfn(v->arch.guest_table);
    3.29 -    gw->l2e = (guest_l2e_t *)v->arch.guest_vtable + guest_l2_table_offset(va);
    3.30 +    gw->l2e = (guest_l2e_t *)v->arch.paging.shadow.guest_vtable 
    3.31 +        + guest_l2_table_offset(va);
    3.32  #endif /* All levels... */
    3.33      
    3.34      if ( !(guest_l2e_get_flags(*gw->l2e) & _PAGE_PRESENT) ) return 0;
    3.35 @@ -357,8 +358,8 @@ static inline void print_gw(walk_t *gw)
    3.36      SHADOW_PRINTK("   l4e=%p\n", gw->l4e);
    3.37      if ( gw->l4e )
    3.38          SHADOW_PRINTK("   *l4e=%" SH_PRI_gpte "\n", gw->l4e->l4);
    3.39 +    SHADOW_PRINTK("   l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn));
    3.40  #endif /* PAE or 64... */
    3.41 -    SHADOW_PRINTK("   l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn));
    3.42      SHADOW_PRINTK("   l3e=%p\n", gw->l3e);
    3.43      if ( gw->l3e )
    3.44          SHADOW_PRINTK("   *l3e=%" SH_PRI_gpte "\n", gw->l3e->l3);
    3.45 @@ -3169,8 +3170,7 @@ sh_update_linear_entries(struct vcpu *v)
    3.46  #else /* GUEST_PAGING_LEVELS == 3 */
    3.47          
    3.48          shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table;
    3.49 -        /* Always safe to use guest_vtable, because it's globally mapped */
    3.50 -        guest_l3e = v->arch.guest_vtable;
    3.51 +        guest_l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e;
    3.52  
    3.53  #endif /* GUEST_PAGING_LEVELS */
    3.54          
    3.55 @@ -3268,39 +3268,37 @@ sh_update_linear_entries(struct vcpu *v)
    3.56  }
    3.57  
    3.58  
    3.59 -/* Removes vcpu->arch.guest_vtable and vcpu->arch.shadow_table[].
    3.60 +/* Removes vcpu->arch.paging.shadow.guest_vtable and vcpu->arch.shadow_table[].
    3.61   * Does all appropriate management/bookkeeping/refcounting/etc...
    3.62   */
    3.63  static void
    3.64  sh_detach_old_tables(struct vcpu *v)
    3.65  {
    3.66 -    struct domain *d = v->domain;
    3.67      mfn_t smfn;
    3.68      int i = 0;
    3.69  
    3.70      ////
    3.71 -    //// vcpu->arch.guest_vtable
    3.72 +    //// vcpu->arch.paging.shadow.guest_vtable
    3.73      ////
    3.74 -    if ( v->arch.guest_vtable )
    3.75 +
    3.76 +#if GUEST_PAGING_LEVELS == 3
    3.77 +    /* PAE guests don't have a mapping of the guest top-level table */
    3.78 +    ASSERT(v->arch.paging.shadow.guest_vtable == NULL);
    3.79 +#else
    3.80 +    if ( v->arch.paging.shadow.guest_vtable )
    3.81      {
    3.82 -#if GUEST_PAGING_LEVELS == 4
    3.83 +        struct domain *d = v->domain;
    3.84          if ( shadow_mode_external(d) || shadow_mode_translate(d) )
    3.85 -            sh_unmap_domain_page_global(v->arch.guest_vtable);
    3.86 -#elif GUEST_PAGING_LEVELS == 3
    3.87 -        if ( 1 || shadow_mode_external(d) || shadow_mode_translate(d) )
    3.88 -            sh_unmap_domain_page_global(v->arch.guest_vtable);
    3.89 -#elif GUEST_PAGING_LEVELS == 2
    3.90 -        if ( shadow_mode_external(d) || shadow_mode_translate(d) )
    3.91 -            sh_unmap_domain_page_global(v->arch.guest_vtable);
    3.92 +            sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable);
    3.93 +        v->arch.paging.shadow.guest_vtable = NULL;
    3.94 +    }
    3.95  #endif
    3.96 -        v->arch.guest_vtable = NULL;
    3.97 -    }
    3.98 +
    3.99  
   3.100      ////
   3.101      //// vcpu->arch.shadow_table[]
   3.102      ////
   3.103  
   3.104 -
   3.105  #if GUEST_PAGING_LEVELS == 3
   3.106      /* PAE guests have four shadow_table entries */
   3.107      for ( i = 0 ; i < 4 ; i++ )
   3.108 @@ -3398,7 +3396,9 @@ sh_update_cr3(struct vcpu *v, int do_loc
   3.109      struct domain *d = v->domain;
   3.110      mfn_t gmfn;
   3.111  #if GUEST_PAGING_LEVELS == 3
   3.112 +    guest_l3e_t *gl3e;
   3.113      u32 guest_idx=0;
   3.114 +    int i;
   3.115  #endif
   3.116  
   3.117      /* Don't do anything on an uninitialised vcpu */
   3.118 @@ -3457,55 +3457,54 @@ sh_update_cr3(struct vcpu *v, int do_loc
   3.119  
   3.120  
   3.121      ////
   3.122 -    //// vcpu->arch.guest_vtable
   3.123 +    //// vcpu->arch.paging.shadow.guest_vtable
   3.124      ////
   3.125  #if GUEST_PAGING_LEVELS == 4
   3.126      if ( shadow_mode_external(d) || shadow_mode_translate(d) )
   3.127      {
   3.128 -        if ( v->arch.guest_vtable )
   3.129 -            sh_unmap_domain_page_global(v->arch.guest_vtable);
   3.130 -        v->arch.guest_vtable = sh_map_domain_page_global(gmfn);
   3.131 +        if ( v->arch.paging.shadow.guest_vtable )
   3.132 +            sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable);
   3.133 +        v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn);
   3.134      }
   3.135      else
   3.136 -        v->arch.guest_vtable = __linear_l4_table;
   3.137 +        v->arch.paging.shadow.guest_vtable = __linear_l4_table;
   3.138  #elif GUEST_PAGING_LEVELS == 3
   3.139 -    if ( v->arch.guest_vtable )
   3.140 -        sh_unmap_domain_page_global(v->arch.guest_vtable);
   3.141 -    if ( shadow_mode_external(d) )
   3.142 -    {
   3.143 -        if ( paging_vcpu_mode_translate(v) ) 
   3.144 -            /* Paging enabled: find where in the page the l3 table is */
   3.145 -            guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3));
   3.146 -        else
   3.147 -            /* Paging disabled: l3 is at the start of a page (in the p2m) */ 
   3.148 -            guest_idx = 0; 
   3.149 -
   3.150 -        // Ignore the low 2 bits of guest_idx -- they are really just
   3.151 -        // cache control.
   3.152 -        guest_idx &= ~3;
   3.153 -
   3.154 -        // XXX - why does this need a global map?
   3.155 -        v->arch.guest_vtable =
   3.156 -            (guest_l3e_t *)sh_map_domain_page_global(gmfn) + guest_idx;
   3.157 -    }
   3.158 +     /* On PAE guests we don't use a mapping of the guest's own top-level
   3.159 +      * table.  We cache the current state of that table and shadow that,
   3.160 +      * until the next CR3 write makes us refresh our cache. */
   3.161 +     ASSERT(v->arch.paging.shadow.guest_vtable == NULL);
   3.162 + 
   3.163 +     if ( shadow_mode_external(d) && paging_vcpu_mode_translate(v) ) 
   3.164 +         /* Paging enabled: find where in the page the l3 table is */
   3.165 +         guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3));
   3.166      else
   3.167 -        v->arch.guest_vtable = sh_map_domain_page_global(gmfn);
   3.168 +        /* Paging disabled or PV: l3 is at the start of a page */ 
   3.169 +        guest_idx = 0; 
   3.170 +     
   3.171 +     // Ignore the low 2 bits of guest_idx -- they are really just
   3.172 +     // cache control.
   3.173 +     guest_idx &= ~3;
   3.174 +     
   3.175 +     gl3e = ((guest_l3e_t *)sh_map_domain_page(gmfn)) + guest_idx;
   3.176 +     for ( i = 0; i < 4 ; i++ )
   3.177 +         v->arch.paging.shadow.gl3e[i] = gl3e[i];
   3.178 +     sh_unmap_domain_page(gl3e);
   3.179  #elif GUEST_PAGING_LEVELS == 2
   3.180      if ( shadow_mode_external(d) || shadow_mode_translate(d) )
   3.181      {
   3.182 -        if ( v->arch.guest_vtable )
   3.183 -            sh_unmap_domain_page_global(v->arch.guest_vtable);
   3.184 -        v->arch.guest_vtable = sh_map_domain_page_global(gmfn);
   3.185 +        if ( v->arch.paging.shadow.guest_vtable )
   3.186 +            sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable);
   3.187 +        v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn);
   3.188      }
   3.189      else
   3.190 -        v->arch.guest_vtable = __linear_l2_table;
   3.191 +        v->arch.paging.shadow.guest_vtable = __linear_l2_table;
   3.192  #else
   3.193  #error this should never happen
   3.194  #endif
   3.195  
   3.196  #if 0
   3.197 -    printk("%s %s %d gmfn=%05lx guest_vtable=%p\n",
   3.198 -           __func__, __FILE__, __LINE__, gmfn, v->arch.guest_vtable);
   3.199 +    printk("%s %s %d gmfn=%05lx shadow.guest_vtable=%p\n",
   3.200 +           __func__, __FILE__, __LINE__, gmfn, v->arch.paging.shadow.guest_vtable);
   3.201  #endif
   3.202  
   3.203      ////
   3.204 @@ -3523,10 +3522,10 @@ sh_update_cr3(struct vcpu *v, int do_loc
   3.205      /* PAE guests have four shadow_table entries, based on the 
   3.206       * current values of the guest's four l3es. */
   3.207      {
   3.208 -        int i, flush = 0;
   3.209 +        int flush = 0;
   3.210          gfn_t gl2gfn;
   3.211          mfn_t gl2mfn;
   3.212 -        guest_l3e_t *gl3e = (guest_l3e_t*)v->arch.guest_vtable;
   3.213 +        guest_l3e_t *gl3e = (guest_l3e_t*)&v->arch.paging.shadow.gl3e;
   3.214          /* First, make all four entries read-only. */
   3.215          for ( i = 0; i < 4; i++ )
   3.216          {
     4.1 --- a/xen/arch/x86/mm/shadow/page-guest32.h	Wed Feb 14 14:44:07 2007 +0000
     4.2 +++ b/xen/arch/x86/mm/shadow/page-guest32.h	Wed Feb 14 14:46:18 2007 +0000
     4.3 @@ -87,11 +87,6 @@ static inline l2_pgentry_32_t l2e_from_p
     4.4  #define l2_table_offset_32(a)         \
     4.5      (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
     4.6  
     4.7 -#define linear_l1_table_32                                                 \
     4.8 -    ((l1_pgentry_32_t *)(LINEAR_PT_VIRT_START))
     4.9 -
    4.10 -#define linear_pg_table_32 linear_l1_table_32
    4.11 -
    4.12  #endif /* __X86_PAGE_GUEST_H__ */
    4.13  
    4.14  /*
     5.1 --- a/xen/arch/x86/mm/shadow/types.h	Wed Feb 14 14:44:07 2007 +0000
     5.2 +++ b/xen/arch/x86/mm/shadow/types.h	Wed Feb 14 14:46:18 2007 +0000
     5.3 @@ -447,10 +447,8 @@ struct shadow_walk_t
     5.4      guest_l2e_t *l2e;           /* Pointer to guest's level 2 entry */
     5.5      guest_l1e_t *l1e;           /* Pointer to guest's level 1 entry */
     5.6      guest_l1e_t eff_l1e;        /* Effective level 1 entry */
     5.7 -#if GUEST_PAGING_LEVELS >= 3
     5.8  #if GUEST_PAGING_LEVELS >= 4
     5.9      mfn_t l4mfn;                /* MFN that the level 4 entry is in */
    5.10 -#endif
    5.11      mfn_t l3mfn;                /* MFN that the level 3 entry is in */
    5.12  #endif
    5.13      mfn_t l2mfn;                /* MFN that the level 2 entry is in */
     6.1 --- a/xen/include/asm-x86/domain.h	Wed Feb 14 14:44:07 2007 +0000
     6.2 +++ b/xen/include/asm-x86/domain.h	Wed Feb 14 14:46:18 2007 +0000
     6.3 @@ -92,7 +92,11 @@ struct shadow_vcpu {
     6.4  #if CONFIG_PAGING_LEVELS >= 3
     6.5      /* PAE guests: per-vcpu shadow top-level table */
     6.6      l3_pgentry_t l3table[4] __attribute__((__aligned__(32)));
     6.7 +    /* PAE guests: per-vcpu cache of the top-level *guest* entries */
     6.8 +    l3_pgentry_t gl3e[4] __attribute__((__aligned__(32)));
     6.9  #endif
    6.10 +    /* Non-PAE guests: pointer to guest top-level pagetable */
    6.11 +    void *guest_vtable;
    6.12      /* Last MFN that we emulated a write to. */
    6.13      unsigned long last_emulated_mfn;
    6.14      /* MFN of the last shadow that we shot a writeable mapping in */
    6.15 @@ -242,8 +246,6 @@ struct arch_vcpu
    6.16      pagetable_t monitor_table;          /* (MFN) hypervisor PT (for HVM) */
    6.17      unsigned long cr3;           	    /* (MA) value to install in HW CR3 */
    6.18  
    6.19 -    void *guest_vtable;                 /* virtual addr of pagetable */
    6.20 -
    6.21      /* Current LDT details. */
    6.22      unsigned long shadow_ldt_mapcnt;
    6.23  
     7.1 --- a/xen/include/asm-x86/page.h	Wed Feb 14 14:44:07 2007 +0000
     7.2 +++ b/xen/include/asm-x86/page.h	Wed Feb 14 14:46:18 2007 +0000
     7.3 @@ -278,9 +278,6 @@ typedef struct { u64 pfn; } pagetable_t;
     7.4  #define __linear_l4_table \
     7.5   ((l4_pgentry_t *)(__linear_l3_table + l3_linear_offset(LINEAR_PT_VIRT_START)))
     7.6  
     7.7 -#define linear_l1_table __linear_l1_table
     7.8 -#define linear_pg_table linear_l1_table
     7.9 -#define linear_l2_table(v) ((l2_pgentry_t *)(v)->arch.guest_vtable)
    7.10  
    7.11  #ifndef __ASSEMBLY__
    7.12  #if CONFIG_PAGING_LEVELS == 3