ia64/xen-unstable

changeset 6600:8b87d43412bf

This patch is to boot 32-bit VMX guest on the 64-bit host.
Double-compile is used to make both 64-bit guest and 32-bit guest can
work, the shadow page-table uses current 64-bit shadow code's structure
to simulate 32-bit guest's 2-level page-table.

Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
Signed-off-by: Xiaohui Xin <xiaohui.xin@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Sep 02 09:43:32 2005 +0000 (2005-09-02)
parents 95cfc001ddd1
children 4544d105f194
files xen/arch/x86/Makefile xen/arch/x86/shadow.c xen/arch/x86/shadow_public.c xen/arch/x86/vmx.c xen/include/asm-x86/page-guest32.h xen/include/asm-x86/shadow.h xen/include/asm-x86/shadow_64.h xen/include/asm-x86/shadow_public.h
line diff
     1.1 --- a/xen/arch/x86/Makefile	Fri Sep 02 09:02:13 2005 +0000
     1.2 +++ b/xen/arch/x86/Makefile	Fri Sep 02 09:43:32 2005 +0000
     1.3 @@ -17,7 +17,7 @@ endif
     1.4  
     1.5  OBJS := $(patsubst shadow%.o,,$(OBJS))	# drop all
     1.6  ifeq ($(TARGET_SUBARCH),x86_64) 
     1.7 - OBJS += shadow.o shadow_public.o	# x86_64: new code
     1.8 + OBJS += shadow.o shadow_public.o shadow_guest32.o	# x86_64: new code
     1.9  endif
    1.10  ifeq ($(TARGET_SUBARCH),x86_32) 
    1.11   ifneq ($(pae),n)
     2.1 --- a/xen/arch/x86/shadow.c	Fri Sep 02 09:02:13 2005 +0000
     2.2 +++ b/xen/arch/x86/shadow.c	Fri Sep 02 09:43:32 2005 +0000
     2.3 @@ -53,6 +53,9 @@ static unsigned long shadow_l4_table(
     2.4      struct domain *d, unsigned long gpfn, unsigned long gmfn);
     2.5  static void shadow_map_into_current(struct vcpu *v,
     2.6      unsigned long va, unsigned int from, unsigned int to);
     2.7 +static inline void validate_bl2e_change( struct domain *d,
     2.8 +	guest_root_pgentry_t *new_gle_p, pgentry_64_t *shadow_l3, int index);
     2.9 +
    2.10  #endif
    2.11  
    2.12  /********
    2.13 @@ -217,10 +220,38 @@ alloc_shadow_page(struct domain *d,
    2.14          }
    2.15          else
    2.16          {
    2.17 -            page = alloc_domheap_page(NULL);
    2.18 -            void *l1 = map_domain_page(page_to_pfn(page));
    2.19 -            memset(l1, 0, PAGE_SIZE);
    2.20 -            unmap_domain_page(l1);
    2.21 +            if (d->arch.ops->guest_paging_levels == PAGING_L2)
    2.22 +            {
    2.23 +#if CONFIG_PAGING_LEVELS >= 4
    2.24 +                /* For 32-bit VMX guest, 2 shadow L1s to simulate 1 guest L1
    2.25 +                 * So need allocate 2 continues shadow L1 each time.
    2.26 +                 */
    2.27 +                page = alloc_domheap_pages(NULL, SL1_ORDER, 0);
    2.28 +                if (!page)
    2.29 +                    domain_crash_synchronous();
    2.30 +
    2.31 +                void *l1_0 = map_domain_page(page_to_pfn(page));
    2.32 +                memset(l1_0,0,PAGE_SIZE);
    2.33 +                unmap_domain_page(l1_0);
    2.34 +                void *l1_1 = map_domain_page(page_to_pfn(page+1));
    2.35 +                memset(l1_1,0,PAGE_SIZE);
    2.36 +                unmap_domain_page(l1_1);
    2.37 +#else
    2.38 +                page = alloc_domheap_page(NULL);
    2.39 +                if (!page)
    2.40 +                    domain_crash_synchronous();
    2.41 +                void *l1 = map_domain_page(page_to_pfn(page));
    2.42 +                memset(l1, 0, PAGE_SIZE);
    2.43 +                unmap_domain_page(l1);
    2.44 +#endif
    2.45 +            }
    2.46 +            else
    2.47 +            {
    2.48 +                page = alloc_domheap_page(NULL);
    2.49 +                void *l1 = map_domain_page(page_to_pfn(page));
    2.50 +                memset(l1, 0, PAGE_SIZE);
    2.51 +                unmap_domain_page(l1);
    2.52 +            }
    2.53          }
    2.54      }
    2.55      else {
    2.56 @@ -331,7 +362,21 @@ alloc_shadow_page(struct domain *d,
    2.57    fail:
    2.58      FSH_LOG("promotion of pfn=%lx mfn=%lx failed!  external gnttab refs?",
    2.59              gpfn, gmfn);
    2.60 -    free_domheap_page(page);
    2.61 +    if (psh_type == PGT_l1_shadow)
    2.62 +    {
    2.63 +        if (d->arch.ops->guest_paging_levels == PAGING_L2)
    2.64 +        {
    2.65 +#if CONFIG_PAGING_LEVELS >=4
    2.66 +            free_domheap_pages(page, SL1_ORDER);
    2.67 +#else
    2.68 +            free_domheap_page(page);
    2.69 +#endif
    2.70 +        }
    2.71 +        else
    2.72 +            free_domheap_page(page);
    2.73 +    }
    2.74 +    else
    2.75 +        free_domheap_page(page);
    2.76      return 0;
    2.77  }
    2.78  
    2.79 @@ -478,8 +523,10 @@ static void shadow_map_l1_into_current_l
    2.80  { 
    2.81      struct vcpu *v = current;
    2.82      struct domain *d = v->domain;
    2.83 -    l1_pgentry_t *gpl1e, *spl1e;
    2.84 -    l2_pgentry_t gl2e, sl2e;
    2.85 +    l1_pgentry_t *spl1e;
    2.86 +    l2_pgentry_t sl2e;
    2.87 +    guest_l1_pgentry_t *gpl1e;
    2.88 +    guest_l2_pgentry_t gl2e;
    2.89      unsigned long gl1pfn, gl1mfn, sl1mfn;
    2.90      int i, init_table = 0;
    2.91  
    2.92 @@ -523,28 +570,49 @@ static void shadow_map_l1_into_current_l
    2.93      ASSERT( !(l2e_get_flags(old_sl2e) & _PAGE_PRESENT) );
    2.94  #endif
    2.95  
    2.96 -    if ( !get_shadow_ref(sl1mfn) )
    2.97 -        BUG();
    2.98 -    l2pde_general(d, &gl2e, &sl2e, sl1mfn);
    2.99 -    __guest_set_l2e(v, va, &gl2e);
   2.100 -    __shadow_set_l2e(v, va, &sl2e);
   2.101 +#if CONFIG_PAGING_LEVELS >=4
   2.102 +    if (d->arch.ops->guest_paging_levels == PAGING_L2)
   2.103 +    {
   2.104 +        /* for 32-bit VMX guest on 64-bit host, 
   2.105 +         * need update two L2 entries each time
   2.106 +         */
   2.107 +        if ( !get_shadow_ref(sl1mfn))
   2.108 +                BUG();
   2.109 +        l2pde_general(d, &gl2e, &sl2e, sl1mfn);
   2.110 +        __guest_set_l2e(v, va, &gl2e);
   2.111 +        __shadow_set_l2e(v, va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1), &sl2e);
   2.112 +        if ( !get_shadow_ref(sl1mfn+1))
   2.113 +            BUG();
   2.114 +        sl2e = l2e_empty();
   2.115 +        l2pde_general(d, &gl2e, &sl2e, sl1mfn+1);
   2.116 +        __shadow_set_l2e(v,((va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1)) + (1 << L2_PAGETABLE_SHIFT)) , &sl2e);
   2.117 +    } else
   2.118 +#endif
   2.119 +    {
   2.120 +        if ( !get_shadow_ref(sl1mfn) )
   2.121 +            BUG();
   2.122 +        l2pde_general(d, &gl2e, &sl2e, sl1mfn);
   2.123 +        __guest_set_l2e(v, va, &gl2e);
   2.124 +        __shadow_set_l2e(v, va , &sl2e);
   2.125 +    }
   2.126  
   2.127      if ( init_table )
   2.128      {
   2.129          l1_pgentry_t sl1e;
   2.130 -        int index = l1_table_offset(va);
   2.131 +        int index = guest_l1_table_offset(va);
   2.132          int min = 1, max = 0;
   2.133          
   2.134          unsigned long entries, pt_va;
   2.135          l1_pgentry_t tmp_sl1e;
   2.136 -        l1_pgentry_t tmp_gl1e;//Prepare for double compile
   2.137 -
   2.138 -
   2.139 -        entries = PAGE_SIZE / sizeof(l1_pgentry_t);
   2.140 +        guest_l1_pgentry_t tmp_gl1e;//Prepare for double compile
   2.141 +
   2.142 +
   2.143 +        entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t);
   2.144          pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) << L1_PAGETABLE_SHIFT;
   2.145 -        gpl1e = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e);
   2.146 -
   2.147 -        entries = PAGE_SIZE / sizeof(l1_pgentry_t);
   2.148 +        gpl1e = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e);
   2.149 +
   2.150 +        /* If the PGT_l1_shadow has two continual pages */
   2.151 +        entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t); //1024 entry!!!
   2.152          pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) << L1_PAGETABLE_SHIFT;
   2.153          spl1e = (l1_pgentry_t *) __shadow_get_l1e(v, pt_va, &tmp_sl1e);
   2.154  
   2.155 @@ -555,7 +623,7 @@ static void shadow_map_l1_into_current_l
   2.156          spl1e = &(shadow_linear_pg_table[l1_linear_offset(va) &
   2.157                                       ~(L1_PAGETABLE_ENTRIES-1)]);*/
   2.158  
   2.159 -        for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
   2.160 +        for ( i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++ )
   2.161          {
   2.162              l1pte_propagate_from_guest(d, gpl1e[i], &sl1e);
   2.163              if ( (l1e_get_flags(sl1e) & _PAGE_PRESENT) &&
   2.164 @@ -584,7 +652,7 @@ static void shadow_map_l1_into_current_l
   2.165      }
   2.166  }
   2.167  
   2.168 -static void 
   2.169 +static void
   2.170  shadow_set_l1e(unsigned long va, l1_pgentry_t new_spte, int create_l1_shadow)
   2.171  {
   2.172      struct vcpu *v = current;
   2.173 @@ -616,7 +684,7 @@ shadow_set_l1e(unsigned long va, l1_pgen
   2.174                  perfc_incrc(shadow_set_l1e_unlinked);
   2.175                  if ( !get_shadow_ref(sl1mfn) )
   2.176                      BUG();
   2.177 -                l2pde_general(d, &gpde, &sl2e, sl1mfn);
   2.178 +                l2pde_general(d, (guest_l2_pgentry_t *)&gpde, &sl2e, sl1mfn);
   2.179                  __guest_set_l2e(v, va, &gpde);
   2.180                  __shadow_set_l2e(v, va, &sl2e);
   2.181              }
   2.182 @@ -651,6 +719,7 @@ shadow_set_l1e(unsigned long va, l1_pgen
   2.183      shadow_update_min_max(l2e_get_pfn(sl2e), l1_table_offset(va));
   2.184  }
   2.185  
   2.186 +#if CONFIG_PAGING_LEVELS <= 3
   2.187  static void shadow_invlpg_32(struct vcpu *v, unsigned long va)
   2.188  {
   2.189      struct domain *d = v->domain;
   2.190 @@ -679,6 +748,7 @@ static void shadow_invlpg_32(struct vcpu
   2.191  
   2.192      shadow_unlock(d);
   2.193  }
   2.194 +#endif
   2.195  
   2.196  static struct out_of_sync_entry *
   2.197  shadow_alloc_oos_entry(struct domain *d)
   2.198 @@ -759,8 +829,8 @@ shadow_make_snapshot(
   2.199      length = max - min + 1;
   2.200      perfc_incr_histo(snapshot_copies, length, PT_UPDATES);
   2.201  
   2.202 -    min *= sizeof(l1_pgentry_t);
   2.203 -    length *= sizeof(l1_pgentry_t);
   2.204 +    min *= sizeof(guest_l1_pgentry_t);
   2.205 +    length *= sizeof(guest_l1_pgentry_t);
   2.206  
   2.207      original = map_domain_page(gmfn);
   2.208      snapshot = map_domain_page(smfn);
   2.209 @@ -841,7 +911,7 @@ static void shadow_mark_va_out_of_sync(
   2.210  
   2.211          __shadow_get_l4e(v, va, &sl4e);
   2.212          if ( !(l4e_get_flags(sl4e) & _PAGE_PRESENT)) {
   2.213 -            shadow_map_into_current(v, va, L3, L4);
   2.214 +            shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
   2.215          }
   2.216  
   2.217          if (!__shadow_get_l3e(v, va, &sl3e)) {
   2.218 @@ -849,7 +919,7 @@ static void shadow_mark_va_out_of_sync(
   2.219          }
   2.220  
   2.221          if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT)) {
   2.222 -            shadow_map_into_current(v, va, L2, L3);
   2.223 +            shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
   2.224          }
   2.225      }
   2.226  #endif
   2.227 @@ -887,11 +957,11 @@ static void shadow_mark_va_out_of_sync(
   2.228   * Returns 0 otherwise.
   2.229   */
   2.230  static int snapshot_entry_matches(
   2.231 -    struct domain *d, l1_pgentry_t *guest_pt,
   2.232 +    struct domain *d, guest_l1_pgentry_t *guest_pt,
   2.233      unsigned long gpfn, unsigned index)
   2.234  {
   2.235      unsigned long smfn = __shadow_status(d, gpfn, PGT_snapshot);
   2.236 -    l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ...
   2.237 +    guest_l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ...
   2.238      int entries_match;
   2.239  
   2.240      perfc_incrc(snapshot_entry_matches_calls);
   2.241 @@ -908,7 +978,7 @@ static int snapshot_entry_matches(
   2.242      // This could probably be smarter, but this is sufficent for
   2.243      // our current needs.
   2.244      //
   2.245 -    entries_match = !l1e_has_changed(gpte, snapshot[index],
   2.246 +    entries_match = !guest_l1e_has_changed(gpte, snapshot[index],
   2.247                                       PAGE_FLAG_MASK);
   2.248  
   2.249      unmap_domain_page(snapshot);
   2.250 @@ -936,10 +1006,10 @@ static int is_out_of_sync(struct vcpu *v
   2.251      unsigned long l2mfn = pagetable_get_pfn(v->arch.guest_table);
   2.252  #endif
   2.253      unsigned long l2pfn = __mfn_to_gpfn(d, l2mfn);
   2.254 -    l2_pgentry_t l2e;
   2.255 +    guest_l2_pgentry_t l2e;
   2.256      unsigned long l1pfn, l1mfn;
   2.257 -    l1_pgentry_t *guest_pt;
   2.258 -    l1_pgentry_t tmp_gle;
   2.259 +    guest_l1_pgentry_t *guest_pt;
   2.260 +    guest_l1_pgentry_t tmp_gle;
   2.261      unsigned long pt_va;
   2.262  
   2.263      ASSERT(shadow_lock_is_acquired(d));
   2.264 @@ -948,7 +1018,7 @@ static int is_out_of_sync(struct vcpu *v
   2.265      perfc_incrc(shadow_out_of_sync_calls);
   2.266  
   2.267  #if CONFIG_PAGING_LEVELS >= 4
   2.268 -    if (d->arch.ops->guest_paging_levels == L4) { /* Mode F */
   2.269 +    if (d->arch.ops->guest_paging_levels == PAGING_L4) { /* Mode F */
   2.270          pgentry_64_t le;
   2.271          unsigned long gmfn;
   2.272          unsigned long gpfn;
   2.273 @@ -956,9 +1026,9 @@ static int is_out_of_sync(struct vcpu *v
   2.274  
   2.275          gmfn = l2mfn;
   2.276          gpfn = l2pfn;
   2.277 -        guest_pt = (l1_pgentry_t *)v->arch.guest_vtable;
   2.278 -
   2.279 -        for (i = L4; i >= L3; i--) {
   2.280 +        guest_pt = (guest_l1_pgentry_t *)v->arch.guest_vtable;
   2.281 +
   2.282 +        for (i = PAGING_L4; i >= PAGING_L3; i--) {
   2.283              if ( page_out_of_sync(&frame_table[gmfn]) &&
   2.284                !snapshot_entry_matches(
   2.285                    d, guest_pt, gpfn, table_offset_64(va, i)) )
   2.286 @@ -972,7 +1042,7 @@ static int is_out_of_sync(struct vcpu *v
   2.287              if ( !VALID_MFN(gmfn) )
   2.288                  return 0;
   2.289              /* Todo: check!*/
   2.290 -            guest_pt = (l1_pgentry_t *)map_domain_page(gmfn);
   2.291 +            guest_pt = (guest_l1_pgentry_t *)map_domain_page(gmfn);
   2.292  
   2.293          }
   2.294  
   2.295 @@ -986,13 +1056,13 @@ static int is_out_of_sync(struct vcpu *v
   2.296  #endif
   2.297  
   2.298      if ( page_out_of_sync(&frame_table[l2mfn]) &&
   2.299 -         !snapshot_entry_matches(d, (l1_pgentry_t *)v->arch.guest_vtable,
   2.300 -                                 l2pfn, l2_table_offset(va)) )
   2.301 +         !snapshot_entry_matches(d, (guest_l1_pgentry_t *)v->arch.guest_vtable,
   2.302 +                                 l2pfn, guest_l2_table_offset(va)) )
   2.303          return 1;
   2.304  
   2.305      __guest_get_l2e(v, va, &l2e);
   2.306 -    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || 
   2.307 -         (l2e_get_flags(l2e) & _PAGE_PSE))
   2.308 +    if ( !(guest_l2e_get_flags(l2e) & _PAGE_PRESENT) || 
   2.309 +         (guest_l2e_get_flags(l2e) & _PAGE_PSE))
   2.310          return 0;
   2.311  
   2.312      l1pfn = l2e_get_pfn(l2e);
   2.313 @@ -1001,20 +1071,20 @@ static int is_out_of_sync(struct vcpu *v
   2.314      // If the l1 pfn is invalid, it can't be out of sync...
   2.315      if ( !VALID_MFN(l1mfn) )
   2.316          return 0;
   2.317 -    
   2.318 -    pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(L1_PAGETABLE_ENTRIES - 1))
   2.319 +
   2.320 +    pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(GUEST_L1_PAGETABLE_ENTRIES - 1))
   2.321        << L1_PAGETABLE_SHIFT;
   2.322 -    guest_pt = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle);
   2.323 +    guest_pt = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle);
   2.324  
   2.325      if ( page_out_of_sync(&frame_table[l1mfn]) &&
   2.326           !snapshot_entry_matches(
   2.327 -             d, guest_pt, l1pfn, l1_table_offset(va)) )
   2.328 +             d, guest_pt, l1pfn, guest_l1_table_offset(va)) )
   2.329          return 1;
   2.330  
   2.331      return 0;
   2.332  }
   2.333  
   2.334 -#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / sizeof(l1_pgentry_t)))
   2.335 +#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / sizeof(guest_l1_pgentry_t)))
   2.336  static inline unsigned long
   2.337  predict_writable_pte_page(struct domain *d, unsigned long gpfn)
   2.338  {
   2.339 @@ -1108,7 +1178,7 @@ static u32 remove_all_write_access_in_pt
   2.340          return (found == max_refs_to_find);
   2.341      }
   2.342  
   2.343 -    i = readonly_gpfn & (L1_PAGETABLE_ENTRIES - 1);
   2.344 +    i = readonly_gpfn & (GUEST_L1_PAGETABLE_ENTRIES - 1);
   2.345      if ( !l1e_has_changed(pt[i], match, flags) && fix_entry(i) )
   2.346      {
   2.347          perfc_incrc(remove_write_fast_exit);
   2.348 @@ -1117,7 +1187,7 @@ static u32 remove_all_write_access_in_pt
   2.349          return found;
   2.350      }
   2.351   
   2.352 -    for (i = 0; i < L1_PAGETABLE_ENTRIES; i++)
   2.353 +    for (i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++)
   2.354      {
   2.355          if ( unlikely(!l1e_has_changed(pt[i], match, flags)) && fix_entry(i) )
   2.356              break;
   2.357 @@ -1282,15 +1352,15 @@ static int resync_all(struct domain *d, 
   2.358          switch ( stype ) {
   2.359          case PGT_l1_shadow:
   2.360          {
   2.361 -            l1_pgentry_t *guest1 = guest;
   2.362 +            guest_l1_pgentry_t *guest1 = guest;
   2.363              l1_pgentry_t *shadow1 = shadow;
   2.364 -            l1_pgentry_t *snapshot1 = snapshot;
   2.365 +            guest_l1_pgentry_t *snapshot1 = snapshot;
   2.366  
   2.367              ASSERT(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) ||
   2.368                     shadow_mode_write_all(d));
   2.369  
   2.370              if ( !shadow_mode_refcounts(d) )
   2.371 -                revalidate_l1(d, guest1, snapshot1);
   2.372 +                revalidate_l1(d, (l1_pgentry_t *)guest1, (l1_pgentry_t *)snapshot1);
   2.373  
   2.374              if ( !smfn )
   2.375                  break;
   2.376 @@ -1301,7 +1371,7 @@ static int resync_all(struct domain *d, 
   2.377              for ( i = min_shadow; i <= max_shadow; i++ )
   2.378              {
   2.379                  if ( (i < min_snapshot) || (i > max_snapshot) ||
   2.380 -                     l1e_has_changed(guest1[i], snapshot1[i], PAGE_FLAG_MASK) )
   2.381 +                     guest_l1e_has_changed(guest1[i], snapshot1[i], PAGE_FLAG_MASK) )
   2.382                  {
   2.383                      need_flush |= validate_pte_change(d, guest1[i], &shadow1[i]);
   2.384  
   2.385 @@ -1431,32 +1501,36 @@ static int resync_all(struct domain *d, 
   2.386          {
   2.387              int max = -1;
   2.388  
   2.389 -            l4_pgentry_t *guest4 = guest;
   2.390 +            guest_root_pgentry_t *guest_root = guest;
   2.391              l4_pgentry_t *shadow4 = shadow;
   2.392 -            l4_pgentry_t *snapshot4 = snapshot;
   2.393 +            guest_root_pgentry_t *snapshot_root = snapshot;
   2.394  
   2.395              changed = 0;
   2.396 -            for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
   2.397 +            for ( i = 0; i < GUEST_ROOT_PAGETABLE_ENTRIES; i++ )
   2.398              {
   2.399                  if ( !is_guest_l4_slot(i) && !external )
   2.400                      continue;
   2.401 -                l4_pgentry_t new_l4e = guest4[i];
   2.402 -                if ( l4e_has_changed(new_l4e, snapshot4[i], PAGE_FLAG_MASK))
   2.403 +                guest_root_pgentry_t new_root_e = guest_root[i];
   2.404 +                if ( root_entry_has_changed(
   2.405 +                        new_root_e, snapshot_root[i], PAGE_FLAG_MASK))
   2.406                  {
   2.407 -                    need_flush |= validate_entry_change(
   2.408 -                      d, (pgentry_64_t *)&new_l4e,
   2.409 -                      (pgentry_64_t *)&shadow4[i], shadow_type_to_level(stype));
   2.410 -
   2.411 +                    if (d->arch.ops->guest_paging_levels == PAGING_L4) {
   2.412 +                        need_flush |= validate_entry_change(
   2.413 +                          d, (pgentry_64_t *)&new_root_e,
   2.414 +                          (pgentry_64_t *)&shadow4[i], shadow_type_to_level(stype));
   2.415 +                    } else {
   2.416 +                        validate_bl2e_change(d, &new_root_e, shadow, i);
   2.417 +                    }
   2.418                      changed++;
   2.419                      ESH_LOG("%d: shadow4 mfn: %lx, shadow root: %lx\n", i,
   2.420                        smfn, pagetable_get_paddr(current->arch.shadow_table));
   2.421                  }
   2.422 -                if ( l4e_get_intpte(new_l4e) != 0 ) /* FIXME: check flags? */
   2.423 +                if ( guest_root_get_intpte(new_root_e) != 0 ) /* FIXME: check flags? */
   2.424                      max = i;
   2.425  
   2.426                  //  Need a better solution in the long term.
   2.427 -                if ( !(l4e_get_flags(new_l4e) & _PAGE_PRESENT) &&
   2.428 -                  unlikely(l4e_get_intpte(new_l4e) != 0) &&
   2.429 +                if ( !(guest_root_get_flags(new_root_e) & _PAGE_PRESENT) &&
   2.430 +                  unlikely(guest_root_get_intpte(new_root_e) != 0) &&
   2.431                    !unshadow &&
   2.432                    (frame_table[smfn].u.inuse.type_info & PGT_pinned) )
   2.433                      unshadow = 1;
   2.434 @@ -1555,8 +1629,14 @@ static void sync_all(struct domain *d)
   2.435      if ( shadow_mode_translate(d) )
   2.436          need_flush |= resync_all(d, PGT_hl2_shadow);
   2.437  #endif
   2.438 -    need_flush |= resync_all(d, PGT_l2_shadow);
   2.439 -    need_flush |= resync_all(d, PGT_l3_shadow);
   2.440 +
   2.441 +    /*
   2.442 +     * Fixme: for i386 host
   2.443 +     */
   2.444 +    if (d->arch.ops->guest_paging_levels == PAGING_L4) {
   2.445 +        need_flush |= resync_all(d, PGT_l2_shadow);
   2.446 +        need_flush |= resync_all(d, PGT_l3_shadow);
   2.447 +    }
   2.448      need_flush |= resync_all(d, PGT_l4_shadow);
   2.449  
   2.450      if ( need_flush && !unlikely(shadow_mode_external(d)) )
   2.451 @@ -1566,11 +1646,11 @@ static void sync_all(struct domain *d)
   2.452  }
   2.453  
   2.454  static inline int l1pte_write_fault(
   2.455 -    struct vcpu *v, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
   2.456 +    struct vcpu *v, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p,
   2.457      unsigned long va)
   2.458  {
   2.459      struct domain *d = v->domain;
   2.460 -    l1_pgentry_t gpte = *gpte_p;
   2.461 +    guest_l1_pgentry_t gpte = *gpte_p;
   2.462      l1_pgentry_t spte;
   2.463      unsigned long gpfn = l1e_get_pfn(gpte);
   2.464      unsigned long gmfn = __gpfn_to_mfn(d, gpfn);
   2.465 @@ -1585,8 +1665,8 @@ static inline int l1pte_write_fault(
   2.466      }
   2.467  
   2.468      ASSERT(l1e_get_flags(gpte) & _PAGE_RW);
   2.469 -    l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
   2.470 -    spte = l1e_from_pfn(gmfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
   2.471 +    guest_l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED);
   2.472 +    spte = l1e_from_pfn(gmfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
   2.473  
   2.474      SH_VVLOG("l1pte_write_fault: updating spte=0x%" PRIpte " gpte=0x%" PRIpte,
   2.475               l1e_get_intpte(spte), l1e_get_intpte(gpte));
   2.476 @@ -1604,9 +1684,9 @@ static inline int l1pte_write_fault(
   2.477  }
   2.478  
   2.479  static inline int l1pte_read_fault(
   2.480 -    struct domain *d, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
   2.481 +    struct domain *d, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p)
   2.482  { 
   2.483 -    l1_pgentry_t gpte = *gpte_p;
   2.484 +    guest_l1_pgentry_t gpte = *gpte_p;
   2.485      l1_pgentry_t spte = *spte_p;
   2.486      unsigned long pfn = l1e_get_pfn(gpte);
   2.487      unsigned long mfn = __gpfn_to_mfn(d, pfn);
   2.488 @@ -1618,10 +1698,10 @@ static inline int l1pte_read_fault(
   2.489          return 0;
   2.490      }
   2.491  
   2.492 -    l1e_add_flags(gpte, _PAGE_ACCESSED);
   2.493 -    spte = l1e_from_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
   2.494 -
   2.495 -    if ( shadow_mode_log_dirty(d) || !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
   2.496 +    guest_l1e_add_flags(gpte, _PAGE_ACCESSED);
   2.497 +    spte = l1e_from_pfn(mfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL);
   2.498 +
   2.499 +    if ( shadow_mode_log_dirty(d) || !(guest_l1e_get_flags(gpte) & _PAGE_DIRTY) ||
   2.500           mfn_is_page_table(mfn) )
   2.501      {
   2.502          l1e_remove_flags(spte, _PAGE_RW);
   2.503 @@ -1634,7 +1714,7 @@ static inline int l1pte_read_fault(
   2.504  
   2.505      return 1;
   2.506  }
   2.507 -
   2.508 +#if CONFIG_PAGING_LEVELS <= 3
   2.509  static int shadow_fault_32(unsigned long va, struct cpu_user_regs *regs)
   2.510  {
   2.511      l1_pgentry_t gpte, spte, orig_gpte;
   2.512 @@ -1768,6 +1848,7 @@ static int shadow_fault_32(unsigned long
   2.513      shadow_unlock(d);
   2.514      return 0;
   2.515  }
   2.516 +#endif
   2.517  
   2.518  static int do_update_va_mapping(unsigned long va,
   2.519                                  l1_pgentry_t val,
   2.520 @@ -1787,7 +1868,7 @@ static int do_update_va_mapping(unsigned
   2.521      //
   2.522      __shadow_sync_va(v, va);
   2.523  
   2.524 -    l1pte_propagate_from_guest(d, val, &spte);
   2.525 +    l1pte_propagate_from_guest(d, *(guest_l1_pgentry_t *)&val, &spte);
   2.526      shadow_set_l1e(va, spte, 0);
   2.527  
   2.528      /*
   2.529 @@ -1848,7 +1929,7 @@ static void shadow_update_pagetables(str
   2.530  #if CONFIG_PAGING_LEVELS == 2
   2.531      unsigned long hl2mfn;
   2.532  #endif
   2.533 -  
   2.534 +
   2.535      int max_mode = ( shadow_mode_external(d) ? SHM_external
   2.536                       : shadow_mode_translate(d) ? SHM_translate
   2.537                       : shadow_mode_enabled(d) ? SHM_enable
   2.538 @@ -1954,17 +2035,6 @@ static void shadow_update_pagetables(str
   2.539  #endif
   2.540  }
   2.541  
   2.542 -struct shadow_ops MODE_A_HANDLER = {
   2.543 -    .guest_paging_levels        = 2,
   2.544 -    .invlpg                     = shadow_invlpg_32,
   2.545 -    .fault                      = shadow_fault_32,
   2.546 -    .update_pagetables          = shadow_update_pagetables,
   2.547 -    .sync_all                   = sync_all,
   2.548 -    .remove_all_write_access    = remove_all_write_access,
   2.549 -    .do_update_va_mapping       = do_update_va_mapping,
   2.550 -    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
   2.551 -    .is_out_of_sync             = is_out_of_sync,
   2.552 -};
   2.553  
   2.554  /************************************************************************/
   2.555  /************************************************************************/
   2.556 @@ -2445,12 +2515,90 @@ static unsigned long shadow_l3_table(
   2.557      BUG();                      /* not implemenated yet */
   2.558      return 42;
   2.559  }
   2.560 +static unsigned long gva_to_gpa_pae(unsigned long gva)
   2.561 +{
   2.562 +    BUG();
   2.563 +    return 43;
   2.564 +}
   2.565  #endif
   2.566  
   2.567  #if CONFIG_PAGING_LEVELS >= 4
   2.568  /****************************************************************************/
   2.569  /* 64-bit shadow-mode code testing */
   2.570  /****************************************************************************/
   2.571 +/*
   2.572 + * validate_bl2e_change()
   2.573 + * The code is for 32-bit VMX gues on 64-bit host.
   2.574 + * To sync guest L2.
   2.575 + */
   2.576 +
   2.577 +static inline void
   2.578 +validate_bl2e_change(
   2.579 +  struct domain *d,
   2.580 +  guest_root_pgentry_t *new_gle_p,
   2.581 +  pgentry_64_t *shadow_l3,
   2.582 +  int index)
   2.583 +{
   2.584 +    int sl3_idx, sl2_idx;
   2.585 +    unsigned long sl2mfn, sl1mfn;
   2.586 +    pgentry_64_t *sl2_p;
   2.587 +
   2.588 +    /* Using guest l2 pte index to get shadow l3&l2 index
   2.589 +     * index: 0 ~ 1023, PAGETABLE_ENTRIES: 512
   2.590 +     */
   2.591 +    sl3_idx = index / (PAGETABLE_ENTRIES / 2);
   2.592 +    sl2_idx = (index % (PAGETABLE_ENTRIES / 2)) * 2;
   2.593 +
   2.594 +    sl2mfn = entry_get_pfn(shadow_l3[sl3_idx]);
   2.595 +    sl2_p = (pgentry_64_t *)map_domain_page(sl2mfn);
   2.596 +
   2.597 +    validate_pde_change(
   2.598 +        d, *(guest_l2_pgentry_t *)new_gle_p, (l2_pgentry_t *)&sl2_p[sl2_idx]);
   2.599 +
   2.600 +    /* Mapping the second l1 shadow page */
   2.601 +    if (entry_get_flags(sl2_p[sl2_idx]) & _PAGE_PRESENT) {
   2.602 +       sl1mfn = entry_get_pfn(sl2_p[sl2_idx]);
   2.603 +       sl2_p[sl2_idx + 1] =
   2.604 +            entry_from_pfn(sl1mfn + 1, entry_get_flags(sl2_p[sl2_idx]));
   2.605 +    }
   2.606 +    unmap_domain_page(sl2_p);
   2.607 +
   2.608 +}
   2.609 +
   2.610 +/*
   2.611 + * init_bl2() is for 32-bit VMX guest on 64-bit host
   2.612 + * Using 1 shadow L4(l3) and 4 shadow L2s to simulate guest L2
   2.613 + */
   2.614 +static inline unsigned long init_bl2(l4_pgentry_t *spl4e, unsigned long smfn)
   2.615 +{
   2.616 +    unsigned int count;
   2.617 +    unsigned long sl2mfn;
   2.618 +    struct pfn_info *page;
   2.619 +
   2.620 +    memset(spl4e, 0, PAGE_SIZE);
   2.621 +
   2.622 +    /* Map the self entry, L4&L3 share the same page */
   2.623 +    spl4e[PAE_SHADOW_SELF_ENTRY] = l4e_from_pfn(smfn, __PAGE_HYPERVISOR);
   2.624 +
   2.625 +    /* Allocate 4 shadow L2s */
   2.626 +    page = alloc_domheap_pages(NULL, SL2_ORDER, 0);
   2.627 +    if (!page)
   2.628 +        domain_crash_synchronous();
   2.629 +
   2.630 +    for (count = 0; count < PDP_ENTRIES; count++)
   2.631 +    {
   2.632 +        sl2mfn = page_to_pfn(page+count);
   2.633 +        void *l2 = map_domain_page(sl2mfn);
   2.634 +        memset(l2, 0, PAGE_SIZE);
   2.635 +        unmap_domain_page(l2);
   2.636 +        spl4e[count] = l4e_from_pfn(sl2mfn, _PAGE_PRESENT);
   2.637 +    }
   2.638 +
   2.639 +    unmap_domain_page(spl4e);
   2.640 +    return smfn;
   2.641 +
   2.642 +
   2.643 +}
   2.644  
   2.645  static unsigned long shadow_l4_table(
   2.646    struct domain *d, unsigned long gpfn, unsigned long gmfn)
   2.647 @@ -2464,11 +2612,16 @@ static unsigned long shadow_l4_table(
   2.648  
   2.649      if ( unlikely(!(smfn = alloc_shadow_page(d, gpfn, gmfn, PGT_l4_shadow))) )
   2.650      {
   2.651 -        printk("Couldn't alloc an L2 shadow for pfn=%lx mfn=%lx\n", gpfn, gmfn);
   2.652 +        printk("Couldn't alloc an L4 shadow for pfn=%lx mfn=%lx\n", gpfn, gmfn);
   2.653          BUG(); /* XXX Deal gracefully with failure. */
   2.654      }
   2.655  
   2.656      spl4e = (l4_pgentry_t *)map_domain_page(smfn);
   2.657 +
   2.658 +    if (d->arch.ops->guest_paging_levels == PAGING_L2) {
   2.659 +        return init_bl2(spl4e, smfn);
   2.660 +    }
   2.661 +
   2.662      /* Install hypervisor and 4x linear p.t. mapings. */
   2.663      if ( (PGT_base_page_table == PGT_l4_page_table) &&
   2.664        !shadow_mode_external(d) )
   2.665 @@ -2576,7 +2729,7 @@ static void shadow_map_into_current(stru
   2.666      pgentry_64_t gle, sle;
   2.667      unsigned long gpfn, smfn;
   2.668  
   2.669 -    if (from == L1 && to == L2) {
   2.670 +    if (from == PAGING_L1 && to == PAGING_L2) {
   2.671          shadow_map_l1_into_current_l2(va);
   2.672          return;
   2.673      }
   2.674 @@ -2608,7 +2761,7 @@ static void shadow_set_l2e_64(unsigned l
   2.675      if (!(l4e_get_flags(sl4e) & _PAGE_PRESENT)) {
   2.676          if (create_l2_shadow) {
   2.677              perfc_incrc(shadow_set_l3e_force_map);
   2.678 -            shadow_map_into_current(v, va, L3, L4);
   2.679 +            shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
   2.680              __shadow_get_l4e(v, va, &sl4e);
   2.681          } else {
   2.682              printk("For non VMX shadow, create_l1_shadow:%d\n", create_l2_shadow);
   2.683 @@ -2619,7 +2772,7 @@ static void shadow_set_l2e_64(unsigned l
   2.684      if (!(l3e_get_flags(sl3e) & _PAGE_PRESENT)) {
   2.685           if (create_l2_shadow) {
   2.686              perfc_incrc(shadow_set_l2e_force_map);
   2.687 -            shadow_map_into_current(v, va, L2, L3);
   2.688 +            shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
   2.689              __shadow_get_l3e(v, va, &sl3e);
   2.690          } else {
   2.691              printk("For non VMX shadow, create_l1_shadow:%d\n", create_l2_shadow);
   2.692 @@ -2655,8 +2808,15 @@ static void shadow_set_l1e_64(unsigned l
   2.693      l1_pgentry_t old_spte;
   2.694      l1_pgentry_t sl1e = *(l1_pgentry_t *)sl1e_p;
   2.695      int i;
   2.696 -
   2.697 -    for (i = L4; i >= L2; i--) {
   2.698 +    unsigned long orig_va = 0;
   2.699 +
   2.700 +    if (d->arch.ops->guest_paging_levels == PAGING_L2) {
   2.701 +        /* This is for 32-bit VMX guest on 64-bit host */
   2.702 +        orig_va = va;
   2.703 +        va = va & (~((1<<L2_PAGETABLE_SHIFT_32)-1));
   2.704 +    }
   2.705 +
   2.706 +    for (i = PAGING_L4; i >= PAGING_L2; i--) {
   2.707          if (!__rw_entry(v, va, &sle, SHADOW_ENTRY | GET_ENTRY | i)) {
   2.708              printk("<%s> i = %d\n", __func__, i);
   2.709              BUG();
   2.710 @@ -2672,11 +2832,15 @@ static void shadow_set_l1e_64(unsigned l
   2.711  #endif
   2.712              }
   2.713          }
   2.714 -        if(i < L4)
   2.715 +        if(i < PAGING_L4)
   2.716              shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, i));
   2.717          sle_up = sle;
   2.718      }
   2.719  
   2.720 +    if (d->arch.ops->guest_paging_levels == PAGING_L2) {
   2.721 +        va = orig_va;
   2.722 +    }
   2.723 +
   2.724      if ( shadow_mode_refcounts(d) )
   2.725      {
   2.726          __shadow_get_l1e(v, va, &old_spte);
   2.727 @@ -2692,9 +2856,13 @@ static void shadow_set_l1e_64(unsigned l
   2.728      }
   2.729  
   2.730      __shadow_set_l1e(v, va, &sl1e);
   2.731 -    shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, L1));
   2.732 +
   2.733 +    shadow_update_min_max(entry_get_pfn(sle_up), guest_l1_table_offset(va));
   2.734  }
   2.735  
   2.736 +/* As 32-bit guest don't support 4M page yet,
   2.737 + * we don't concern double compile for this function
   2.738 + */
   2.739  static inline int l2e_rw_fault(
   2.740      struct vcpu *v, l2_pgentry_t *gl2e_p, unsigned long va, int rw)
   2.741  {
   2.742 @@ -2825,12 +2993,120 @@ static inline int l2e_rw_fault(
   2.743  
   2.744  }
   2.745  
   2.746 +/*
   2.747 + * Check P, R/W, U/S bits in the guest page table.
   2.748 + * If the fault belongs to guest return 1,
   2.749 + * else return 0.
   2.750 + */
   2.751 +#if defined( GUEST_PGENTRY_32 )
   2.752 +static inline int guest_page_fault(struct vcpu *v,
   2.753 +  unsigned long va, unsigned int error_code, 
   2.754 +  guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e)
   2.755 +{
   2.756 +    /* The following check for 32-bit guest on 64-bit host */
   2.757 +
   2.758 +    __guest_get_l2e(v, va, gpl2e);
   2.759 +
   2.760 +    /* Check the guest L2 page-table entry first*/
   2.761 +    if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_PRESENT)))
   2.762 +        return 1;
   2.763 +
   2.764 +    if (error_code & ERROR_W) {
   2.765 +        if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_RW)))
   2.766 +            return 1;
   2.767 +    }
   2.768 +    if (error_code & ERROR_U) {
   2.769 +        if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_USER)))
   2.770 +            return 1;
   2.771 +    }
   2.772 +
   2.773 +    if (guest_l2e_get_flags(*gpl2e) & _PAGE_PSE)
   2.774 +        return 0;
   2.775 +
   2.776 +    __guest_get_l1e(v, va, gpl1e);
   2.777 +
   2.778 +    /* Then check the guest L1 page-table entry */
   2.779 +    if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_PRESENT)))
   2.780 +        return 1;
   2.781 +
   2.782 +    if (error_code & ERROR_W) {
   2.783 +        if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_RW)))
   2.784 +            return 1;
   2.785 +    }
   2.786 +    if (error_code & ERROR_U) {
   2.787 +        if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_USER)))
   2.788 +            return 1;
   2.789 +    }
   2.790 +
   2.791 +    return 0;
   2.792 +}
   2.793 +#else
   2.794 +static inline int guest_page_fault(struct vcpu *v,
   2.795 +  unsigned long va, unsigned int error_code, 
   2.796 +  guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e)
   2.797 +{
   2.798 +    struct domain *d = v->domain;
   2.799 +    pgentry_64_t gle, *lva;
   2.800 +    unsigned long mfn;
   2.801 +    int i;
   2.802 +
   2.803 +    __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | PAGING_L4);
   2.804 +    if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
   2.805 +        return 1;
   2.806 +
   2.807 +    if (error_code & ERROR_W) {
   2.808 +        if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
   2.809 +            return 1;
   2.810 +    }
   2.811 +    if (error_code & ERROR_U) {
   2.812 +        if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
   2.813 +            return 1;
   2.814 +    }
   2.815 +    for (i = PAGING_L3; i >= PAGING_L1; i--) {
   2.816 +        /*
   2.817 +         * If it's not external mode, then mfn should be machine physical.
   2.818 +         */
   2.819 +        mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT));
   2.820 +
   2.821 +        lva = (pgentry_64_t *) phys_to_virt(
   2.822 +          mfn << PAGE_SHIFT);
   2.823 +        gle = lva[table_offset_64(va, i)];
   2.824 +
   2.825 +        if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
   2.826 +            return 1;
   2.827 +
   2.828 +        if (error_code & ERROR_W) {
   2.829 +            if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
   2.830 +                return 1;
   2.831 +        }
   2.832 +        if (error_code & ERROR_U) {
   2.833 +            if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
   2.834 +                return 1;
   2.835 +        }
   2.836 +
   2.837 +        if (i == PAGING_L2) {
   2.838 +            if (gpl2e)
   2.839 +                gpl2e->l2 = gle.lo;
   2.840 +
   2.841 +            if (likely(entry_get_flags(gle) & _PAGE_PSE))
   2.842 +                return 0;
   2.843 +
   2.844 +        }
   2.845 +
   2.846 +        if (i == PAGING_L1)
   2.847 +            if (gpl1e)
   2.848 +                gpl1e->l1 = gle.lo;
   2.849 +    }
   2.850 +    return 0;
   2.851 +}
   2.852 +#endif
   2.853  static int shadow_fault_64(unsigned long va, struct cpu_user_regs *regs)
   2.854  {
   2.855      struct vcpu *v = current;
   2.856      struct domain *d = v->domain;
   2.857 -    l2_pgentry_t gl2e;
   2.858 -    l1_pgentry_t sl1e, gl1e;
   2.859 +    guest_l2_pgentry_t gl2e;
   2.860 +    guest_l1_pgentry_t gl1e;
   2.861 +    l1_pgentry_t sl1e;
   2.862  
   2.863      perfc_incrc(shadow_fault_calls);
   2.864  
   2.865 @@ -2853,12 +3129,11 @@ static int shadow_fault_64(unsigned long
   2.866       * STEP 2. Check if the fault belongs to guest
   2.867       */
   2.868      if ( guest_page_fault(
   2.869 -            v, va, regs->error_code, 
   2.870 -            (pgentry_64_t *)&gl2e, (pgentry_64_t *)&gl1e) ) {
   2.871 +            v, va, regs->error_code, &gl2e, &gl1e) ) {
   2.872          goto fail;
   2.873      }
   2.874      
   2.875 -    if ( unlikely(!(l2e_get_flags(gl2e) & _PAGE_PSE)) ) {
   2.876 +    if ( unlikely(!(guest_l2e_get_flags(gl2e) & _PAGE_PSE)) ) {
   2.877          /*
   2.878           * Handle 4K pages here
   2.879           */
   2.880 @@ -2892,11 +3167,11 @@ static int shadow_fault_64(unsigned long
   2.881           */
   2.882          /* Write fault? */
   2.883          if ( regs->error_code & 2 ) {
   2.884 -            if ( !l2e_rw_fault(v, &gl2e, va, WRITE_FAULT) ) {
   2.885 +            if ( !l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, WRITE_FAULT) ) {
   2.886                  goto fail;
   2.887              }
   2.888          } else {
   2.889 -            l2e_rw_fault(v, &gl2e, va, READ_FAULT);
   2.890 +            l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, READ_FAULT);
   2.891          }
   2.892  
   2.893          /*
   2.894 @@ -2944,7 +3219,27 @@ static void shadow_invlpg_64(struct vcpu
   2.895      shadow_unlock(d);
   2.896  }
   2.897  
   2.898 -#ifndef PGENTRY_32
   2.899 +static unsigned long gva_to_gpa_64(unsigned long gva)
   2.900 +{
   2.901 +    struct vcpu *v = current;
   2.902 +    guest_l1_pgentry_t gl1e = {0};
   2.903 +    guest_l2_pgentry_t gl2e = {0};
   2.904 +    unsigned long gpa;
   2.905 +
   2.906 +    if (guest_page_fault(v, gva, 0, &gl2e, &gl1e))
   2.907 +        return 0;
   2.908 +    
   2.909 +    if (guest_l2e_get_flags(gl2e) & _PAGE_PSE)
   2.910 +        gpa = guest_l2e_get_paddr(gl2e) + (gva & ((1 << GUEST_L2_PAGETABLE_SHIFT) - 1));
   2.911 +    else
   2.912 +        gpa = guest_l1e_get_paddr(gl1e) + (gva & ~PAGE_MASK);
   2.913 +
   2.914 +    return gpa;
   2.915 +
   2.916 +}
   2.917 +
   2.918 +#ifndef GUEST_PGENTRY_32
   2.919 +
   2.920  struct shadow_ops MODE_F_HANDLER = {
   2.921      .guest_paging_levels              = 4,
   2.922      .invlpg                     = shadow_invlpg_64,
   2.923 @@ -2955,11 +3250,43 @@ struct shadow_ops MODE_F_HANDLER = {
   2.924      .do_update_va_mapping       = do_update_va_mapping,
   2.925      .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
   2.926      .is_out_of_sync             = is_out_of_sync,
   2.927 +    .gva_to_gpa                 = gva_to_gpa_64,
   2.928  };
   2.929  #endif
   2.930  
   2.931  #endif
   2.932  
   2.933 +#if CONFIG_PAGING_LEVELS == 2
   2.934 +struct shadow_ops MODE_A_HANDLER = {
   2.935 +    .guest_paging_levels        = 2,
   2.936 +    .invlpg                     = shadow_invlpg_32,
   2.937 +    .fault                      = shadow_fault_32,
   2.938 +    .update_pagetables          = shadow_update_pagetables,
   2.939 +    .sync_all                   = sync_all,
   2.940 +    .remove_all_write_access    = remove_all_write_access,
   2.941 +    .do_update_va_mapping       = do_update_va_mapping,
   2.942 +    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
   2.943 +    .is_out_of_sync             = is_out_of_sync,
   2.944 +    .gva_to_gpa                 = gva_to_gpa_64,
   2.945 +};
   2.946 +
   2.947 +#elif CONFIG_PAGING_LEVELS == 3
   2.948 +struct shadow_ops MODE_B_HANDLER = {
   2.949 +    .guest_paging_levels              = 3,
   2.950 +    .invlpg                     = shadow_invlpg_32,
   2.951 +    .fault                      = shadow_fault_32,
   2.952 +    .update_pagetables          = shadow_update_pagetables,
   2.953 +    .sync_all                   = sync_all,
   2.954 +    .remove_all_write_access    = remove_all_write_access,
   2.955 +    .do_update_va_mapping       = do_update_va_mapping,
   2.956 +    .mark_mfn_out_of_sync       = mark_mfn_out_of_sync,
   2.957 +    .is_out_of_sync             = is_out_of_sync,
   2.958 +    .gva_to_gpa                 = gva_to_gpa_pae,
   2.959 +};
   2.960 +
   2.961 +#endif
   2.962 +
   2.963 +
   2.964  /*
   2.965   * Local variables:
   2.966   * mode: C
     3.1 --- a/xen/arch/x86/shadow_public.c	Fri Sep 02 09:02:13 2005 +0000
     3.2 +++ b/xen/arch/x86/shadow_public.c	Fri Sep 02 09:43:32 2005 +0000
     3.3 @@ -33,11 +33,15 @@
     3.4  #if CONFIG_PAGING_LEVELS >= 3
     3.5  #include <asm/shadow_64.h>
     3.6  
     3.7 +#endif
     3.8 +#if CONFIG_PAGING_LEVELS == 4
     3.9  extern struct shadow_ops MODE_F_HANDLER;
    3.10 +extern struct shadow_ops MODE_D_HANDLER;
    3.11  #endif
    3.12  
    3.13  extern struct shadow_ops MODE_A_HANDLER;
    3.14  
    3.15 +#define SHADOW_MAX_GUEST32(_encoded) ((L1_PAGETABLE_ENTRIES_32 - 1) - ((_encoded) >> 16))
    3.16  /****************************************************************************/
    3.17  /************* export interface functions ***********************************/
    3.18  /****************************************************************************/
    3.19 @@ -48,7 +52,7 @@ int shadow_set_guest_paging_levels(struc
    3.20      shadow_lock(d);
    3.21  
    3.22      switch(levels) {
    3.23 -#if CONFIG_PAGING_LEVELS >= 4 
    3.24 +#if CONFIG_PAGING_LEVELS >= 4
    3.25      case 4:
    3.26  	if ( d->arch.ops != &MODE_F_HANDLER )
    3.27  	    d->arch.ops = &MODE_F_HANDLER;
    3.28 @@ -56,9 +60,14 @@ int shadow_set_guest_paging_levels(struc
    3.29          return 1;
    3.30  #endif
    3.31      case 3:
    3.32 -    case 2:                     
    3.33 +    case 2:
    3.34 +#if CONFIG_PAGING_LEVELS == 2
    3.35  	if ( d->arch.ops != &MODE_A_HANDLER )
    3.36  	    d->arch.ops = &MODE_A_HANDLER;
    3.37 +#elif CONFIG_PAGING_LEVELS == 4
    3.38 +	if ( d->arch.ops != &MODE_D_HANDLER )
    3.39 +	    d->arch.ops = &MODE_D_HANDLER;
    3.40 +#endif
    3.41  	shadow_unlock(d);
    3.42          return 1;
    3.43     default:
    3.44 @@ -122,13 +131,17 @@ int __shadow_out_of_sync(struct vcpu *v,
    3.45      return d->arch.ops->is_out_of_sync(v, va);
    3.46  }
    3.47  
    3.48 +unsigned long gva_to_gpa(unsigned long gva)
    3.49 +{
    3.50 +    struct domain *d = current->domain;
    3.51 +    return d->arch.ops->gva_to_gpa(gva);
    3.52 +}
    3.53  /****************************************************************************/
    3.54  /****************************************************************************/
    3.55  #if CONFIG_PAGING_LEVELS >= 4
    3.56  /*
    3.57   * Convert PAE 3-level page-table to 4-level page-table
    3.58   */
    3.59 -#define PDP_ENTRIES   4
    3.60  static pagetable_t page_table_convert(struct domain *d)
    3.61  {
    3.62      struct pfn_info *l4page, *l3page;
    3.63 @@ -203,20 +216,42 @@ free_shadow_fl1_table(struct domain *d, 
    3.64  /*
    3.65   * Free l2, l3, l4 shadow tables
    3.66   */
    3.67 +
    3.68 +void free_fake_shadow_l2(struct domain *d,unsigned long smfn);
    3.69 +
    3.70  static void inline
    3.71  free_shadow_tables(struct domain *d, unsigned long smfn, u32 level)
    3.72  {
    3.73      pgentry_64_t *ple = map_domain_page(smfn);
    3.74      int i, external = shadow_mode_external(d);
    3.75 +    struct pfn_info *page = &frame_table[smfn];
    3.76  
    3.77 -    for ( i = 0; i < PAGETABLE_ENTRIES; i++ )
    3.78 -        if ( external || is_guest_l4_slot(i) )
    3.79 -            if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
    3.80 -                put_shadow_ref(entry_get_pfn(ple[i]));
    3.81 +    if (d->arch.ops->guest_paging_levels == PAGING_L2)
    3.82 +    {
    3.83 +#if CONFIG_PAGING_LEVELS >=4
    3.84 +        for ( i = 0; i < PDP_ENTRIES; i++ )
    3.85 +        {
    3.86 +            if (entry_get_flags(ple[i]) & _PAGE_PRESENT )
    3.87 +                free_fake_shadow_l2(d,entry_get_pfn(ple[i]));
    3.88 +        }
    3.89 +   
    3.90 +        page = &frame_table[entry_get_pfn(ple[0])];
    3.91 +        free_domheap_pages(page, SL2_ORDER);
    3.92 +        unmap_domain_page(ple);
    3.93 +#endif
    3.94 +    }
    3.95 +    else
    3.96 +    {
    3.97 +        for ( i = 0; i < PAGETABLE_ENTRIES; i++ )
    3.98 +            if ( external || is_guest_l4_slot(i) )
    3.99 +                if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
   3.100 +                        put_shadow_ref(entry_get_pfn(ple[i]));
   3.101  
   3.102 -    unmap_domain_page(ple);
   3.103 +        unmap_domain_page(ple);
   3.104 +    }
   3.105  }
   3.106  
   3.107 +
   3.108  void free_monitor_pagetable(struct vcpu *v)
   3.109  {
   3.110      unsigned long mfn;
   3.111 @@ -453,7 +488,12 @@ free_shadow_l1_table(struct domain *d, u
   3.112      struct pfn_info *spage = pfn_to_page(smfn);
   3.113      u32 min_max = spage->tlbflush_timestamp;
   3.114      int min = SHADOW_MIN(min_max);
   3.115 -    int max = SHADOW_MAX(min_max);
   3.116 +    int max;
   3.117 +    
   3.118 +    if (d->arch.ops->guest_paging_levels == PAGING_L2)
   3.119 +        max = SHADOW_MAX_GUEST32(min_max);
   3.120 +    else
   3.121 +        max = SHADOW_MAX(min_max);
   3.122  
   3.123      for ( i = min; i <= max; i++ )
   3.124      {
   3.125 @@ -512,9 +552,24 @@ free_shadow_l2_table(struct domain *d, u
   3.126      unmap_domain_page(pl2e);
   3.127  }
   3.128  
   3.129 +void free_fake_shadow_l2(struct domain *d, unsigned long smfn)
   3.130 +{
   3.131 +    pgentry_64_t *ple = map_domain_page(smfn);
   3.132 +    int i;
   3.133 +
   3.134 +    for ( i = 0; i < PAGETABLE_ENTRIES; i = i + 2 )
   3.135 +    {
   3.136 +        if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
   3.137 +            put_shadow_ref(entry_get_pfn(ple[i]));
   3.138 +    }
   3.139 +
   3.140 +    unmap_domain_page(ple);
   3.141 +}
   3.142 +
   3.143  void free_shadow_page(unsigned long smfn)
   3.144  {
   3.145      struct pfn_info *page = &frame_table[smfn];
   3.146 +
   3.147      unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
   3.148      struct domain *d = page_get_owner(pfn_to_page(gmfn));
   3.149      unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
   3.150 @@ -531,6 +586,7 @@ void free_shadow_page(unsigned long smfn
   3.151              gpfn |= (1UL << 63);
   3.152      }
   3.153  #endif
   3.154 +
   3.155      delete_shadow_status(d, gpfn, gmfn, type);
   3.156  
   3.157      switch ( type )
   3.158 @@ -687,7 +743,7 @@ void free_shadow_pages(struct domain *d)
   3.159      int                   i;
   3.160      struct shadow_status *x;
   3.161      struct vcpu          *v;
   3.162 - 
   3.163 +
   3.164      /*
   3.165       * WARNING! The shadow page table must not currently be in use!
   3.166       * e.g., You are expected to have paused the domain and synchronized CR3.
   3.167 @@ -794,7 +850,16 @@ void free_shadow_pages(struct domain *d)
   3.168          perfc_decr(free_l1_pages);
   3.169  
   3.170          struct pfn_info *page = list_entry(list_ent, struct pfn_info, list);
   3.171 -        free_domheap_page(page);
   3.172 +	if (d->arch.ops->guest_paging_levels == PAGING_L2)
   3.173 +	{
   3.174 +#if CONFIG_PAGING_LEVELS >=4
   3.175 +        free_domheap_pages(page, SL1_ORDER);
   3.176 +#else
   3.177 +	free_domheap_page(page);
   3.178 +#endif
   3.179 +	}
   3.180 +	else
   3.181 +	free_domheap_page(page);
   3.182      }
   3.183  
   3.184      shadow_audit(d, 0);
   3.185 @@ -1191,7 +1256,7 @@ int shadow_mode_control(struct domain *d
   3.186      {
   3.187          DPRINTK("Don't try to do a shadow op on yourself!\n");
   3.188          return -EINVAL;
   3.189 -    }   
   3.190 +    }
   3.191  
   3.192      domain_pause(d);
   3.193  
     4.1 --- a/xen/arch/x86/vmx.c	Fri Sep 02 09:02:13 2005 +0000
     4.2 +++ b/xen/arch/x86/vmx.c	Fri Sep 02 09:43:32 2005 +0000
     4.3 @@ -412,7 +412,7 @@ static int vmx_do_page_fault(unsigned lo
     4.4      if ( !result )
     4.5      {
     4.6          __vmread(GUEST_RIP, &eip);
     4.7 -        printk("vmx pgfault to guest va=%p eip=%p\n", va, eip);
     4.8 +        printk("vmx pgfault to guest va=%lx eip=%lx\n", va, eip);
     4.9      }
    4.10  #endif
    4.11  
    4.12 @@ -456,7 +456,16 @@ static void vmx_vmexit_do_cpuid(unsigned
    4.13          clear_bit(X86_FEATURE_PSE, &edx);
    4.14          clear_bit(X86_FEATURE_PAE, &edx);
    4.15          clear_bit(X86_FEATURE_PSE36, &edx);
    4.16 +#else
    4.17 +        struct vcpu *d = current;
    4.18 +        if (d->domain->arch.ops->guest_paging_levels == PAGING_L2)
    4.19 +        {
    4.20 +            clear_bit(X86_FEATURE_PSE, &edx);
    4.21 +            clear_bit(X86_FEATURE_PAE, &edx);
    4.22 +            clear_bit(X86_FEATURE_PSE36, &edx);
    4.23 +        }
    4.24  #endif
    4.25 +
    4.26      }
    4.27  
    4.28      regs->eax = (unsigned long) eax;
    4.29 @@ -650,7 +659,7 @@ static void vmx_io_instruction(struct cp
    4.30          p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0;
    4.31  
    4.32          if (test_bit(5, &exit_qualification)) /* "rep" prefix */
    4.33 -	    p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
    4.34 +            p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
    4.35  
    4.36          /*
    4.37           * Split up string I/O operations that cross page boundaries. Don't
    4.38 @@ -1011,6 +1020,15 @@ static int vmx_set_cr0(unsigned long val
    4.39              }
    4.40  #endif
    4.41          }
    4.42 +        else
    4.43 +        {
    4.44 +#if CONFIG_PAGING_LEVELS >= 4
    4.45 +            if(!shadow_set_guest_paging_levels(d->domain, 2)) {
    4.46 +                printk("Unsupported guest paging levels\n");
    4.47 +                domain_crash_synchronous(); /* need to take a clean path */
    4.48 +            }
    4.49 +#endif
    4.50 +        }
    4.51  
    4.52  	unsigned long crn;
    4.53          /* update CR4's PAE if needed */
     5.1 --- a/xen/include/asm-x86/page-guest32.h	Fri Sep 02 09:02:13 2005 +0000
     5.2 +++ b/xen/include/asm-x86/page-guest32.h	Fri Sep 02 09:43:32 2005 +0000
     5.3 @@ -33,6 +33,11 @@ typedef l2_pgentry_t root_pgentry_32_t;
     5.4  #define l1e_get_flags_32(x)           (get_pte_flags_32((x).l1))
     5.5  #define l2e_get_flags_32(x)           (get_pte_flags_32((x).l2))
     5.6  
     5.7 +#define l1e_get_paddr_32(x)           \
     5.8 +    ((physaddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
     5.9 +#define l2e_get_paddr_32(x)           \
    5.10 +    ((physaddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
    5.11 +
    5.12  /* Construct an empty pte. */
    5.13  #define l1e_empty_32()                ((l1_pgentry_32_t) { 0 })
    5.14  #define l2e_empty_32()                ((l2_pgentry_32_t) { 0 })
     6.1 --- a/xen/include/asm-x86/shadow.h	Fri Sep 02 09:02:13 2005 +0000
     6.2 +++ b/xen/include/asm-x86/shadow.h	Fri Sep 02 09:43:32 2005 +0000
     6.3 @@ -34,6 +34,8 @@
     6.4  #include <asm/vmx.h>
     6.5  #include <public/dom0_ops.h>
     6.6  #include <asm/shadow_public.h>
     6.7 +#include <asm/page-guest32.h>
     6.8 +#include <asm/shadow_ops.h>
     6.9  
    6.10  /* Shadow PT operation mode : shadow-mode variable in arch_domain. */
    6.11  
    6.12 @@ -104,9 +106,9 @@ do {                                    
    6.13  } while (0)
    6.14  #endif
    6.15  
    6.16 -#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min))
    6.17 +#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min))
    6.18  #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
    6.19 -#define SHADOW_MAX(_encoded) ((L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
    6.20 +#define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
    6.21  
    6.22  extern void shadow_mode_init(void);
    6.23  extern int shadow_mode_control(struct domain *p, dom0_shadow_control_t *sc);
    6.24 @@ -132,6 +134,7 @@ extern void shadow_l2_normal_pt_update(s
    6.25                                         struct domain_mmap_cache *cache);
    6.26  #if CONFIG_PAGING_LEVELS >= 3
    6.27  #include <asm/page-guest32.h>
    6.28 +extern unsigned long gva_to_gpa(unsigned long gva);
    6.29  extern void shadow_l3_normal_pt_update(struct domain *d,
    6.30                                         unsigned long pa, l3_pgentry_t l3e,
    6.31                                         struct domain_mmap_cache *cache);
    6.32 @@ -794,22 +797,22 @@ static inline int l1pte_read_fault(
    6.33  #endif
    6.34  
    6.35  static inline void l1pte_propagate_from_guest(
    6.36 -    struct domain *d, l1_pgentry_t gpte, l1_pgentry_t *spte_p)
    6.37 +    struct domain *d, guest_l1_pgentry_t gpte, l1_pgentry_t *spte_p)
    6.38  { 
    6.39      unsigned long mfn;
    6.40      l1_pgentry_t spte;
    6.41  
    6.42      spte = l1e_empty();
    6.43  
    6.44 -    if ( ((l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
    6.45 +    if ( ((guest_l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) ==
    6.46            (_PAGE_PRESENT|_PAGE_ACCESSED)) &&
    6.47           VALID_MFN(mfn = __gpfn_to_mfn(d, l1e_get_pfn(gpte))) )
    6.48      {
    6.49          spte = l1e_from_pfn(
    6.50 -            mfn, l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL));
    6.51 +            mfn, guest_l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL));
    6.52  
    6.53          if ( shadow_mode_log_dirty(d) ||
    6.54 -             !(l1e_get_flags(gpte) & _PAGE_DIRTY) ||
    6.55 +             !(guest_l1e_get_flags(gpte) & _PAGE_DIRTY) ||
    6.56               mfn_is_page_table(mfn) )
    6.57          {
    6.58              l1e_remove_flags(spte, _PAGE_RW);
    6.59 @@ -859,22 +862,22 @@ static inline void hl2e_propagate_from_g
    6.60  
    6.61  static inline void l2pde_general(
    6.62      struct domain *d,
    6.63 -    l2_pgentry_t *gpde_p,
    6.64 +    guest_l2_pgentry_t *gpde_p,
    6.65      l2_pgentry_t *spde_p,
    6.66      unsigned long sl1mfn)
    6.67  {
    6.68 -    l2_pgentry_t gpde = *gpde_p;
    6.69 +    guest_l2_pgentry_t gpde = *gpde_p;
    6.70      l2_pgentry_t spde;
    6.71  
    6.72      spde = l2e_empty();
    6.73 -    if ( (l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
    6.74 +    if ( (guest_l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) )
    6.75      {
    6.76          spde = l2e_from_pfn(
    6.77 -            sl1mfn, 
    6.78 -            (l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL);
    6.79 +            sl1mfn,
    6.80 +            (guest_l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL);
    6.81  
    6.82          /* N.B. PDEs do not have a dirty bit. */
    6.83 -        l2e_add_flags(gpde, _PAGE_ACCESSED);
    6.84 +        guest_l2e_add_flags(gpde, _PAGE_ACCESSED);
    6.85  
    6.86          *gpde_p = gpde;
    6.87      }
    6.88 @@ -887,12 +890,12 @@ static inline void l2pde_general(
    6.89  }
    6.90  
    6.91  static inline void l2pde_propagate_from_guest(
    6.92 -    struct domain *d, l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
    6.93 +    struct domain *d, guest_l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p)
    6.94  {
    6.95 -    l2_pgentry_t gpde = *gpde_p;
    6.96 +    guest_l2_pgentry_t gpde = *gpde_p;
    6.97      unsigned long sl1mfn = 0;
    6.98  
    6.99 -    if ( l2e_get_flags(gpde) & _PAGE_PRESENT )
   6.100 +    if ( guest_l2e_get_flags(gpde) & _PAGE_PRESENT )
   6.101          sl1mfn =  __shadow_status(d, l2e_get_pfn(gpde), PGT_l1_shadow);
   6.102      l2pde_general(d, gpde_p, spde_p, sl1mfn);
   6.103  }
   6.104 @@ -904,7 +907,7 @@ static inline void l2pde_propagate_from_
   6.105  static int inline
   6.106  validate_pte_change(
   6.107      struct domain *d,
   6.108 -    l1_pgentry_t new_pte,
   6.109 +    guest_l1_pgentry_t new_pte,
   6.110      l1_pgentry_t *shadow_pte_p)
   6.111  {
   6.112      l1_pgentry_t old_spte, new_spte;
   6.113 @@ -1004,7 +1007,7 @@ validate_hl2e_change(
   6.114  static int inline
   6.115  validate_pde_change(
   6.116      struct domain *d,
   6.117 -    l2_pgentry_t new_gpde,
   6.118 +    guest_l2_pgentry_t new_gpde,
   6.119      l2_pgentry_t *shadow_pde_p)
   6.120  {
   6.121      l2_pgentry_t old_spde, new_spde;
     7.1 --- a/xen/include/asm-x86/shadow_64.h	Fri Sep 02 09:02:13 2005 +0000
     7.2 +++ b/xen/include/asm-x86/shadow_64.h	Fri Sep 02 09:43:32 2005 +0000
     7.3 @@ -27,6 +27,7 @@
     7.4  #ifndef _XEN_SHADOW_64_H
     7.5  #define _XEN_SHADOW_64_H
     7.6  #include <asm/shadow.h>
     7.7 +#include <asm/shadow_ops.h>
     7.8  
     7.9  #define READ_FAULT  0
    7.10  #define WRITE_FAULT 1
    7.11 @@ -42,14 +43,14 @@
    7.12  #define ESH_LOG(_f, _a...) ((void)0)
    7.13  #endif
    7.14  
    7.15 -#define L4      4UL
    7.16 -#define L3      3UL
    7.17 -#define L2      2UL
    7.18 -#define L1      1UL
    7.19 +#define PAGING_L4      4UL
    7.20 +#define PAGING_L3      3UL
    7.21 +#define PAGING_L2      2UL
    7.22 +#define PAGING_L1      1UL
    7.23  #define L_MASK  0xff
    7.24  
    7.25 -#define ROOT_LEVEL_64   L4
    7.26 -#define ROOT_LEVEL_32   L2
    7.27 +#define ROOT_LEVEL_64   PAGING_L4
    7.28 +#define ROOT_LEVEL_32   PAGING_L2
    7.29  
    7.30  #define SHADOW_ENTRY    (2UL << 16)
    7.31  #define GUEST_ENTRY     (1UL << 16)
    7.32 @@ -59,6 +60,10 @@
    7.33  
    7.34  #define PAGETABLE_ENTRIES    (1<<PAGETABLE_ORDER)
    7.35  
    7.36 +/* For 32-bit VMX guest to allocate shadow L1 & L2*/
    7.37 +#define SL1_ORDER   1
    7.38 +#define SL2_ORDER   2
    7.39 +
    7.40  typedef struct { intpte_t lo; } pgentry_64_t;
    7.41  #define shadow_level_to_type(l)    (l << 29)
    7.42  #define shadow_type_to_level(t)    (t >> 29)
    7.43 @@ -76,6 +81,10 @@ typedef struct { intpte_t lo; } pgentry_
    7.44  #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags))
    7.45  #define entry_has_changed(x,y,flags) \
    7.46          ( !!(((x).lo ^ (y).lo) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )
    7.47 +
    7.48 +#define PAE_SHADOW_SELF_ENTRY   259
    7.49 +#define PDP_ENTRIES   4
    7.50 +
    7.51  static inline int  table_offset_64(unsigned long va, int level)
    7.52  {
    7.53      switch(level) {
    7.54 @@ -86,8 +95,13 @@ static inline int  table_offset_64(unsig
    7.55          case 3:
    7.56              return  (((va) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1));
    7.57  #if CONFIG_PAGING_LEVELS >= 4
    7.58 +#ifndef GUEST_PGENTRY_32
    7.59          case 4:
    7.60              return  (((va) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1));
    7.61 +#else
    7.62 +        case 4:
    7.63 +            return PAE_SHADOW_SELF_ENTRY; 
    7.64 +#endif
    7.65  #endif
    7.66          default:
    7.67              //printk("<table_offset_64> level %d is too big\n", level);
    7.68 @@ -165,30 +179,30 @@ static inline pgentry_64_t *__rw_entry(
    7.69      return le_e;
    7.70  }
    7.71  #define __shadow_set_l4e(v, va, value) \
    7.72 -  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L4)
    7.73 +  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L4)
    7.74  #define __shadow_get_l4e(v, va, sl4e) \
    7.75 -  __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | L4)
    7.76 +  __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | PAGING_L4)
    7.77  #define __shadow_set_l3e(v, va, value) \
    7.78 -  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L3)
    7.79 +  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L3)
    7.80  #define __shadow_get_l3e(v, va, sl3e) \
    7.81 -  __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | L3)
    7.82 +  __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | PAGING_L3)
    7.83  #define __shadow_set_l2e(v, va, value) \
    7.84 -  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L2)
    7.85 +  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L2)
    7.86  #define __shadow_get_l2e(v, va, sl2e) \
    7.87 -  __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | L2)
    7.88 +  __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | PAGING_L2)
    7.89  #define __shadow_set_l1e(v, va, value) \
    7.90 -  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L1)
    7.91 +  __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L1)
    7.92  #define __shadow_get_l1e(v, va, sl1e) \
    7.93 -  __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | L1)
    7.94 +  __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | PAGING_L1)
    7.95  
    7.96  #define __guest_set_l4e(v, va, value) \
    7.97 -  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L4)
    7.98 +  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L4)
    7.99  #define __guest_get_l4e(v, va, gl4e) \
   7.100 -  __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | L4)
   7.101 +  __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | PAGING_L4)
   7.102  #define __guest_set_l3e(v, va, value) \
   7.103 -  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L3)
   7.104 +  __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L3)
   7.105  #define __guest_get_l3e(v, va, sl3e) \
   7.106 -  __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | L3)
   7.107 +  __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3)
   7.108  
   7.109  static inline void *  __guest_set_l2e(
   7.110      struct vcpu *v, u64 va, void *value, int size)
   7.111 @@ -205,7 +219,7 @@ static inline void *  __guest_set_l2e(
   7.112                  return &l2va[l2_table_offset_32(va)];
   7.113              }
   7.114          case 8:
   7.115 -            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L2);
   7.116 +            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L2);
   7.117          default:
   7.118              BUG();
   7.119              return NULL;
   7.120 @@ -230,7 +244,7 @@ static inline void * __guest_get_l2e(
   7.121                  return &l2va[l2_table_offset_32(va)];
   7.122              }
   7.123          case 8:
   7.124 -            return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | L2);
   7.125 +            return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | PAGING_L2);
   7.126          default:
   7.127              BUG();
   7.128              return NULL;
   7.129 @@ -269,7 +283,7 @@ static inline void *  __guest_set_l1e(
   7.130              }
   7.131  
   7.132          case 8:
   7.133 -            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L1);
   7.134 +            return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L1);
   7.135          default:
   7.136              BUG();
   7.137              return NULL;
   7.138 @@ -310,7 +324,7 @@ static inline void *  __guest_get_l1e(
   7.139              }
   7.140          case 8:
   7.141              // 64-bit guest
   7.142 -            return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | L1);
   7.143 +            return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | PAGING_L1);
   7.144          default:
   7.145              BUG();
   7.146              return NULL;
   7.147 @@ -334,7 +348,7 @@ static inline void entry_general(
   7.148      sle = entry_empty();
   7.149      if ( (entry_get_flags(gle) & _PAGE_PRESENT) && (smfn != 0) )
   7.150      {
   7.151 -        if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) {
   7.152 +        if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) {
   7.153              sle = entry_from_pfn(smfn, entry_get_flags(gle));
   7.154              entry_remove_flags(sle, _PAGE_PSE);
   7.155  
   7.156 @@ -376,7 +390,7 @@ static inline void entry_propagate_from_
   7.157      unsigned long smfn = 0;
   7.158  
   7.159      if ( entry_get_flags(gle) & _PAGE_PRESENT ) {
   7.160 -        if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) {
   7.161 +        if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) {
   7.162              smfn =  __shadow_status(d, entry_get_value(gle) >> PAGE_SHIFT, PGT_fl1_shadow);
   7.163          } else {
   7.164              smfn =  __shadow_status(d, entry_get_pfn(gle), 
   7.165 @@ -421,88 +435,6 @@ validate_entry_change(
   7.166      return 1;
   7.167  }
   7.168  
   7.169 -/*
   7.170 - * Check P, R/W, U/S bits in the guest page table.
   7.171 - * If the fault belongs to guest return 1,
   7.172 - * else return 0.
   7.173 - */
   7.174 -static inline int guest_page_fault(struct vcpu *v,
   7.175 -  unsigned long va, unsigned int error_code, pgentry_64_t *gpl2e, pgentry_64_t *gpl1e)
   7.176 -{
   7.177 -    struct domain *d = v->domain;
   7.178 -    pgentry_64_t gle, *lva;
   7.179 -    unsigned long mfn;
   7.180 -    int i;
   7.181 -
   7.182 -    __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | L4);
   7.183 -    if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
   7.184 -        return 1;
   7.185 -
   7.186 -    if (error_code & ERROR_W) {
   7.187 -        if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
   7.188 -            return 1;
   7.189 -    }
   7.190 -    if (error_code & ERROR_U) {
   7.191 -        if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
   7.192 -            return 1;
   7.193 -    }
   7.194 -    for (i = L3; i >= L1; i--) {
   7.195 -	/*
   7.196 -	 * If it's not external mode, then mfn should be machine physical.
   7.197 -	 */
   7.198 -	mfn = __gpfn_to_mfn(d, (entry_get_paddr(gle) >> PAGE_SHIFT));
   7.199 -        if (mfn == -1)
   7.200 -            return 1;
   7.201 -
   7.202 -        lva = (pgentry_64_t *) phys_to_virt(
   7.203 -	    mfn << PAGE_SHIFT);
   7.204 -        gle = lva[table_offset_64(va, i)];
   7.205 -
   7.206 -        if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT)))
   7.207 -            return 1;
   7.208 -
   7.209 -        if (error_code & ERROR_W) {
   7.210 -            if (unlikely(!(entry_get_flags(gle) & _PAGE_RW)))
   7.211 -                return 1;
   7.212 -        }
   7.213 -        if (error_code & ERROR_U) {
   7.214 -            if (unlikely(!(entry_get_flags(gle) & _PAGE_USER)))
   7.215 -                return 1;
   7.216 -        }
   7.217 -
   7.218 -        if (i == L2) {
   7.219 -            if (gpl2e)
   7.220 -                *gpl2e = gle;
   7.221 -
   7.222 -            if (likely(entry_get_flags(gle) & _PAGE_PSE))
   7.223 -                return 0;
   7.224 -
   7.225 -        }
   7.226 -
   7.227 -        if (i == L1)
   7.228 -            if (gpl1e)
   7.229 -                *gpl1e = gle;
   7.230 -    }
   7.231 -    return 0;
   7.232 -}
   7.233 -
   7.234 -static inline unsigned long gva_to_gpa(unsigned long gva)
   7.235 -{
   7.236 -    struct vcpu *v = current;
   7.237 -    pgentry_64_t gl1e = {0};
   7.238 -    pgentry_64_t gl2e = {0};
   7.239 -    unsigned long gpa;
   7.240 -
   7.241 -    if (guest_page_fault(v, gva, 0, &gl2e, &gl1e))
   7.242 -        return 0;
   7.243 -    if (entry_get_flags(gl2e) & _PAGE_PSE)
   7.244 -        gpa = entry_get_paddr(gl2e) + (gva & ((1 << L2_PAGETABLE_SHIFT) - 1));
   7.245 -    else
   7.246 -        gpa = entry_get_paddr(gl1e) + (gva & ~PAGE_MASK);
   7.247 -
   7.248 -    return gpa;
   7.249 -
   7.250 -}
   7.251  #endif
   7.252  
   7.253  
     8.1 --- a/xen/include/asm-x86/shadow_public.h	Fri Sep 02 09:02:13 2005 +0000
     8.2 +++ b/xen/include/asm-x86/shadow_public.h	Fri Sep 02 09:43:32 2005 +0000
     8.3 @@ -49,6 +49,7 @@ struct shadow_ops {
     8.4           (*mark_mfn_out_of_sync)(struct vcpu *v, unsigned long gpfn,
     8.5                                unsigned long mfn);
     8.6      int  (*is_out_of_sync)(struct vcpu *v, unsigned long va);
     8.7 +    unsigned long (*gva_to_gpa)(unsigned long gva);
     8.8  };
     8.9  #endif
    8.10