ia64/xen-unstable

changeset 8868:a543a4778a7d

Fix problems with direct-mapping handling especially when
VMX assist is used for real mode and protected mode.

Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Xin B Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 16 16:46:21 2006 +0100 (2006-02-16)
parents bee659de2a36
children 18fa851b6dc6
files xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/shadow.c xen/arch/x86/shadow32.c xen/arch/x86/shadow_public.c xen/include/asm-x86/shadow.h xen/include/asm-x86/shadow_64.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/svm.c	Thu Feb 16 16:35:09 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Thu Feb 16 16:46:21 2006 +0100
     1.3 @@ -799,6 +799,7 @@ void svm_relinquish_resources(struct vcp
     1.4          struct domain *d = v->domain;
     1.5          if (d->arch.hvm_domain.shared_page_va)
     1.6              unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va);
     1.7 +        shadow_direct_map_clean(v);
     1.8      }
     1.9  
    1.10      destroy_vmcb(&v->arch.hvm_svm);
    1.11 @@ -1443,9 +1444,7 @@ static int svm_set_cr0(unsigned long val
    1.12                  put_page(mfn_to_page(old_base_mfn));
    1.13  	}
    1.14  #endif
    1.15 -#if CONFIG_PAGING_LEVELS == 2
    1.16 -        shadow_direct_map_clean(v);
    1.17 -#endif
    1.18 +
    1.19          /* Now arch.guest_table points to machine physical. */
    1.20          v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
    1.21          update_pagetables(v);
     2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Thu Feb 16 16:35:09 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Thu Feb 16 16:46:21 2006 +0100
     2.3 @@ -88,6 +88,7 @@ void vmx_relinquish_resources(struct vcp
     2.4          if ( d->arch.hvm_domain.shared_page_va )
     2.5              unmap_domain_page_global(
     2.6  	        (void *)d->arch.hvm_domain.shared_page_va);
     2.7 +        shadow_direct_map_clean(v);
     2.8      }
     2.9  
    2.10      vmx_request_clear_vmcs(v);
    2.11 @@ -1227,9 +1228,7 @@ static int vmx_set_cr0(unsigned long val
    2.12                  __vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
    2.13              }
    2.14          }
    2.15 -#if CONFIG_PAGING_LEVELS == 2
    2.16 -        shadow_direct_map_clean(v);
    2.17 -#endif
    2.18 +
    2.19          /*
    2.20           * Now arch.guest_table points to machine physical.
    2.21           */
     3.1 --- a/xen/arch/x86/shadow.c	Thu Feb 16 16:35:09 2006 +0100
     3.2 +++ b/xen/arch/x86/shadow.c	Thu Feb 16 16:46:21 2006 +0100
     3.3 @@ -3743,6 +3743,7 @@ struct shadow_ops MODE_32_2_HANDLER = {
     3.4  #if ( CONFIG_PAGING_LEVELS == 3 && !defined (GUEST_PGENTRY_32) ) ||  \
     3.5      ( CONFIG_PAGING_LEVELS == 4 && defined (GUEST_PGENTRY_32) )
     3.6  
     3.7 +
     3.8  /* 
     3.9   * Use GUEST_PGENTRY_32 to force PAE_SHADOW_SELF_ENTRY for L4.
    3.10   *
    3.11 @@ -3756,8 +3757,8 @@ int shadow_direct_map_fault(unsigned lon
    3.12  {
    3.13      struct vcpu *v = current;
    3.14      struct domain *d = v->domain;
    3.15 -    l3_pgentry_t sl3e;
    3.16 -    l2_pgentry_t sl2e;
    3.17 +    l3_pgentry_t sl3e, *sl3e_p;
    3.18 +    l2_pgentry_t sl2e, *sl2e_p;
    3.19      l1_pgentry_t sl1e;
    3.20      unsigned long mfn, smfn;
    3.21      struct page_info *page;
    3.22 @@ -3773,37 +3774,47 @@ int shadow_direct_map_fault(unsigned lon
    3.23  
    3.24      shadow_lock(d);
    3.25  
    3.26 -    __shadow_get_l3e(v, vpa, &sl3e);
    3.27 +    __direct_get_l3e(v, vpa, &sl3e);
    3.28  
    3.29      if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT) ) 
    3.30      {
    3.31          page = alloc_domheap_page(NULL);
    3.32          if ( !page )
    3.33 -            goto fail; 
    3.34 +            goto nomem; 
    3.35 +
    3.36          smfn = page_to_mfn(page);
    3.37          sl3e = l3e_from_pfn(smfn, _PAGE_PRESENT);
    3.38 -        __shadow_set_l3e(v, vpa, &sl3e);
    3.39 +
    3.40 +        sl3e_p = (l3_pgentry_t *)map_domain_page(smfn);
    3.41 +        memset(sl3e_p, 0, PAGE_SIZE);
    3.42 +        unmap_domain_page(sl3e_p);
    3.43 +
    3.44 +        __direct_set_l3e(v, vpa, &sl3e);
    3.45      }
    3.46  
    3.47 -    __shadow_get_l2e(v, vpa, &sl2e);
    3.48 +    __direct_get_l2e(v, vpa, &sl2e);
    3.49  
    3.50      if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) 
    3.51      {
    3.52          page = alloc_domheap_page(NULL);
    3.53          if ( !page )
    3.54 -            goto fail; 
    3.55 +            goto nomem; 
    3.56 +
    3.57          smfn = page_to_mfn(page);
    3.58 -
    3.59          sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER);
    3.60 -        __shadow_set_l2e(v, vpa, &sl2e);
    3.61 +        sl2e_p = (l2_pgentry_t *)map_domain_page(smfn);
    3.62 +        memset(sl2e_p, 0, PAGE_SIZE);
    3.63 +        unmap_domain_page(sl2e_p);
    3.64 +
    3.65 +        __direct_set_l2e(v, vpa, &sl2e);
    3.66      }
    3.67  
    3.68 -    __shadow_get_l1e(v, vpa, &sl1e);
    3.69 +    __direct_get_l1e(v, vpa, &sl1e);
    3.70  
    3.71      if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) ) 
    3.72      {
    3.73          sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER);
    3.74 -        __shadow_set_l1e(v, vpa, &sl1e);
    3.75 +        __direct_set_l1e(v, vpa, &sl1e);
    3.76      } 
    3.77  
    3.78      shadow_unlock(d);
    3.79 @@ -3811,6 +3822,10 @@ int shadow_direct_map_fault(unsigned lon
    3.80  
    3.81  fail:
    3.82      return 0;
    3.83 +
    3.84 +nomem:
    3.85 +    shadow_direct_map_clean(v);
    3.86 +    domain_crash_synchronous();
    3.87  }
    3.88  #endif
    3.89  
     4.1 --- a/xen/arch/x86/shadow32.c	Thu Feb 16 16:35:09 2006 +0100
     4.2 +++ b/xen/arch/x86/shadow32.c	Thu Feb 16 16:46:21 2006 +0100
     4.3 @@ -807,21 +807,99 @@ void free_monitor_pagetable(struct vcpu 
     4.4      v->arch.monitor_vtable = 0;
     4.5  }
     4.6  
     4.7 +static int
     4.8 +map_p2m_entry(
     4.9 +    l1_pgentry_t *l1tab, unsigned long va, unsigned long gpa, unsigned long mfn)
    4.10 +{
    4.11 +    unsigned long *l0tab = NULL;
    4.12 +    l1_pgentry_t l1e = { 0 };
    4.13 +    struct page_info *page;
    4.14 +
    4.15 +    l1e = l1tab[l1_table_offset(va)];
    4.16 +    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
    4.17 +    {
    4.18 +        page = alloc_domheap_page(NULL);
    4.19 +        if ( !page )
    4.20 +            goto fail;
    4.21 +
    4.22 +        if ( l0tab  )
    4.23 +            unmap_domain_page(l0tab);
    4.24 +        l0tab = map_domain_page(page_to_mfn(page));
    4.25 +        memset(l0tab, 0, PAGE_SIZE );
    4.26 +        l1e = l1tab[l1_table_offset(va)] =
    4.27 +            l1e_from_page(page, __PAGE_HYPERVISOR);
    4.28 +    }
    4.29 +    else if ( l0tab == NULL)
    4.30 +        l0tab = map_domain_page(l1e_get_pfn(l1e));
    4.31 +
    4.32 +    l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
    4.33 +
    4.34 +    if ( l0tab )
    4.35 +        unmap_domain_page(l0tab);
    4.36 +
    4.37 +    return 1;
    4.38 +
    4.39 +fail:
    4.40 +    return 0;
    4.41 +}
    4.42 +
    4.43  int
    4.44  set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
    4.45                struct domain_mmap_cache *l2cache,
    4.46                struct domain_mmap_cache *l1cache)
    4.47  {
    4.48 -    unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table);
    4.49 +    unsigned long tabpfn;
    4.50      l2_pgentry_t *l2, l2e;
    4.51      l1_pgentry_t *l1;
    4.52      struct page_info *l1page;
    4.53      unsigned long va = pfn << PAGE_SHIFT;
    4.54 +    int error;
    4.55 +
    4.56 +    if ( shadow_mode_external(d) )
    4.57 +    {
    4.58 +        tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
    4.59 +        va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
    4.60 +    }
    4.61 +    else
    4.62 +    {
    4.63 +        tabpfn = pagetable_get_pfn(d->arch.phys_table);
    4.64 +        va = pfn << PAGE_SHIFT;
    4.65 +    }
    4.66  
    4.67      ASSERT(tabpfn != 0);
    4.68      ASSERT(shadow_lock_is_acquired(d));
    4.69  
    4.70      l2 = map_domain_page_with_cache(tabpfn, l2cache);
    4.71 +
    4.72 +    /*
    4.73 +     * The following code covers (SHM_translate | SHM_external) mode.
    4.74 +     */
    4.75 +
    4.76 +    if ( shadow_mode_external(d) )
    4.77 +    {
    4.78 +        l1_pgentry_t *l1tab = NULL;
    4.79 +        l2_pgentry_t l2e;
    4.80 +
    4.81 +        l2e = l2[l2_table_offset(va)];
    4.82 +
    4.83 +        ASSERT( l2e_get_flags(l2e) & _PAGE_PRESENT );
    4.84 +
    4.85 +        l1tab = map_domain_page(l2e_get_pfn(l2e));
    4.86 +        error = map_p2m_entry(l1tab, va, pfn, mfn);
    4.87 +        if ( !error )
    4.88 +            domain_crash_synchronous(); 
    4.89 +
    4.90 +        unmap_domain_page(l1tab);
    4.91 +        unmap_domain_page_with_cache(l2, l2cache);
    4.92 +
    4.93 +        return 1;
    4.94 +    }
    4.95 +
    4.96 +    /*
    4.97 +     * The following code covers SHM_translate mode.
    4.98 +     */
    4.99 +    ASSERT(shadow_mode_translate(d));
   4.100 +
   4.101      l2e = l2[l2_table_offset(va)];
   4.102      if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
   4.103      {
   4.104 @@ -856,13 +934,10 @@ alloc_p2m_table(struct domain *d)
   4.105  
   4.106      l2_pgentry_t *l2tab = NULL;
   4.107      l1_pgentry_t *l1tab = NULL;
   4.108 -    unsigned long *l0tab = NULL;
   4.109      l2_pgentry_t l2e = { 0 };
   4.110 -    l1_pgentry_t l1e = { 0 };
   4.111 -
   4.112      struct page_info *page;
   4.113 -    unsigned long pfn;
   4.114 -    int i;
   4.115 +    unsigned long gpfn, mfn;
   4.116 +    int error;
   4.117  
   4.118      if ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) )
   4.119      {
   4.120 @@ -892,34 +967,22 @@ alloc_p2m_table(struct domain *d)
   4.121  
   4.122      list_ent = d->page_list.next;
   4.123  
   4.124 -    for ( i = 0; list_ent != &d->page_list; i++ )
   4.125 +    for ( gpfn = 0; list_ent != &d->page_list; gpfn++ )
   4.126      {
   4.127          page = list_entry(list_ent, struct page_info, list);
   4.128 -        pfn = page_to_mfn(page);
   4.129 -
   4.130 -        l1e = l1tab[l1_table_offset(va)];
   4.131 -        if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
   4.132 -        {
   4.133 -            page = alloc_domheap_page(NULL);
   4.134 -            if ( l0tab  )
   4.135 -                unmap_domain_page(l0tab);
   4.136 -            l0tab = map_domain_page(page_to_mfn(page));
   4.137 -            memset(l0tab, 0, PAGE_SIZE );
   4.138 -            l1e = l1tab[l1_table_offset(va)] =
   4.139 -                l1e_from_page(page, __PAGE_HYPERVISOR);
   4.140 -        }
   4.141 -        else if ( l0tab == NULL)
   4.142 -            l0tab = map_domain_page(l1e_get_pfn(l1e));
   4.143 -
   4.144 -        l0tab[i & ((1 << PAGETABLE_ORDER) - 1) ] = pfn;
   4.145 -        list_ent = frame_table[pfn].list.next;
   4.146 -        va += sizeof(pfn);
   4.147 +        mfn = page_to_mfn(page);
   4.148 +
   4.149 +        error = map_p2m_entry(l1tab, va, gpfn, mfn);
   4.150 +        if ( !error )
   4.151 +            domain_crash_synchronous(); 
   4.152 +
   4.153 +        list_ent = frame_table[mfn].list.next;
   4.154 +        va += sizeof(mfn);
   4.155      }
   4.156  
   4.157      if (l2tab)
   4.158          unmap_domain_page(l2tab);
   4.159      unmap_domain_page(l1tab);
   4.160 -    unmap_domain_page(l0tab);
   4.161  
   4.162      return 1;
   4.163  }
   4.164 @@ -981,21 +1044,26 @@ int shadow_direct_map_fault(unsigned lon
   4.165      }
   4.166  
   4.167      shadow_lock(d);
   4.168 -
   4.169 -    __shadow_get_l2e(v, vpa, &sl2e);
   4.170 -
   4.171 -   if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
   4.172 +  
   4.173 +   __direct_get_l2e(v, vpa, &sl2e);
   4.174 +
   4.175 +    if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
   4.176      {
   4.177          page = alloc_domheap_page(NULL);
   4.178          if ( !page )
   4.179 -            goto fail;
   4.180 +            goto nomem;
   4.181  
   4.182          smfn = page_to_mfn(page);
   4.183          sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER);
   4.184 -        __shadow_set_l2e(v, vpa, sl2e);
   4.185 -    }
   4.186 -
   4.187 -    sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e));
   4.188 +
   4.189 +        sple = (l1_pgentry_t *)map_domain_page(smfn);
   4.190 +        memset(sple, 0, PAGE_SIZE);
   4.191 +        __direct_set_l2e(v, vpa, sl2e);
   4.192 +    } 
   4.193 +
   4.194 +    if ( !sple )
   4.195 +        sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e));
   4.196 +
   4.197      sl1e = sple[l1_table_offset(vpa)];
   4.198  
   4.199      if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) )
   4.200 @@ -1003,13 +1071,19 @@ int shadow_direct_map_fault(unsigned lon
   4.201          sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER);
   4.202          sple[l1_table_offset(vpa)] = sl1e;
   4.203      }
   4.204 -    unmap_domain_page(sple);
   4.205 +
   4.206 +    if (sple)
   4.207 +        unmap_domain_page(sple);
   4.208 +
   4.209      shadow_unlock(d);
   4.210 -
   4.211      return EXCRET_fault_fixed;
   4.212  
   4.213  fail:
   4.214      return 0;
   4.215 +
   4.216 +nomem:
   4.217 +    shadow_direct_map_clean(v);
   4.218 +    domain_crash_synchronous();
   4.219  }
   4.220  
   4.221  
   4.222 @@ -1021,16 +1095,12 @@ int shadow_direct_map_init(struct vcpu *
   4.223      if ( !(page = alloc_domheap_page(NULL)) )
   4.224          goto fail;
   4.225  
   4.226 -    root = map_domain_page_global(page_to_mfn(page));
   4.227 +    root = map_domain_page(page_to_mfn(page));
   4.228      memset(root, 0, PAGE_SIZE);
   4.229 +    unmap_domain_page(root);
   4.230  
   4.231      v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page));
   4.232 -    /* 
   4.233 -     * We need to set shadow_vtable to get __shadow_set/get_xxx
   4.234 -     * working
   4.235 -     */
   4.236 -    v->arch.shadow_vtable = (l2_pgentry_t *) root;
   4.237 -    v->arch.shadow_table = mk_pagetable(0);
   4.238 +
   4.239      return 1;
   4.240  
   4.241  fail:
   4.242 @@ -1042,9 +1112,8 @@ void shadow_direct_map_clean(struct vcpu
   4.243      int i;
   4.244      l2_pgentry_t *l2e;
   4.245  
   4.246 -    ASSERT ( v->arch.shadow_vtable );
   4.247 -
   4.248 -    l2e = v->arch.shadow_vtable;
   4.249 +    l2e = map_domain_page(
   4.250 +      pagetable_get_pfn(v->domain->arch.phys_table));
   4.251  
   4.252      for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   4.253      {
   4.254 @@ -1055,8 +1124,7 @@ void shadow_direct_map_clean(struct vcpu
   4.255      free_domheap_page(
   4.256              mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table)));
   4.257  
   4.258 -    unmap_domain_page_global(v->arch.shadow_vtable);
   4.259 -    v->arch.shadow_vtable = 0;
   4.260 +    unmap_domain_page(l2e);
   4.261      v->domain->arch.phys_table = mk_pagetable(0);
   4.262  }
   4.263  
   4.264 @@ -1169,13 +1237,6 @@ int __shadow_mode_enable(struct domain *
   4.265                  goto nomem;
   4.266              }
   4.267          }
   4.268 -        else
   4.269 -        {
   4.270 -            // external guests provide their own memory for their P2M maps.
   4.271 -            //
   4.272 -            ASSERT(d == page_get_owner(mfn_to_page(pagetable_get_pfn(
   4.273 -                d->arch.phys_table))));
   4.274 -        }
   4.275      }
   4.276  
   4.277      // Get rid of any shadow pages from any previous shadow mode.
     5.1 --- a/xen/arch/x86/shadow_public.c	Thu Feb 16 16:35:09 2006 +0100
     5.2 +++ b/xen/arch/x86/shadow_public.c	Thu Feb 16 16:46:21 2006 +0100
     5.3 @@ -44,33 +44,28 @@ int shadow_direct_map_init(struct vcpu *
     5.4      if ( !(page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA)) )
     5.5          goto fail;
     5.6  
     5.7 -    root = map_domain_page_global(page_to_mfn(page));
     5.8 +    root = map_domain_page(page_to_mfn(page));
     5.9      memset(root, 0, PAGE_SIZE);
    5.10      root[PAE_SHADOW_SELF_ENTRY] = l3e_from_page(page, __PAGE_HYPERVISOR);
    5.11  
    5.12      v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page));
    5.13 -    /* 
    5.14 -     * We need to set shadow_vtable to get __shadow_set/get_xxx
    5.15 -     * working
    5.16 -     */
    5.17 -    v->arch.shadow_vtable = (l2_pgentry_t *) root;
    5.18  
    5.19 +    unmap_domain_page(root);
    5.20      return 1;
    5.21 -    
    5.22 +
    5.23  fail:
    5.24      return 0;
    5.25  }
    5.26  
    5.27 -static void shadow_direct_map_clean(struct vcpu *v)
    5.28 +void shadow_direct_map_clean(struct vcpu *v)
    5.29  {
    5.30      l2_pgentry_t *l2e;
    5.31      l3_pgentry_t *l3e;
    5.32      int i, j;
    5.33  
    5.34 -    ASSERT ( v->arch.shadow_vtable );
    5.35 +    l3e = (l3_pgentry_t *)map_domain_page(
    5.36 +        pagetable_get_pfn(v->domain->arch.phys_table));
    5.37  
    5.38 -    l3e = (l3_pgentry_t *) v->arch.shadow_vtable;
    5.39 -    
    5.40      for ( i = 0; i < PAE_L3_PAGETABLE_ENTRIES; i++ )
    5.41      {
    5.42          if ( l3e_get_flags(l3e[i]) & _PAGE_PRESENT )
    5.43 @@ -90,8 +85,7 @@ static void shadow_direct_map_clean(stru
    5.44      free_domheap_page(
    5.45          mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table)));
    5.46  
    5.47 -    unmap_domain_page_global(v->arch.shadow_vtable);
    5.48 -    v->arch.shadow_vtable = 0;
    5.49 +    unmap_domain_page(l3e);
    5.50      v->domain->arch.phys_table = mk_pagetable(0);
    5.51  }
    5.52  
    5.53 @@ -102,13 +96,8 @@ static void shadow_direct_map_clean(stru
    5.54  
    5.55  int shadow_set_guest_paging_levels(struct domain *d, int levels)
    5.56  {
    5.57 -    struct vcpu *v = current;
    5.58      shadow_lock(d);
    5.59  
    5.60 -    if ( shadow_mode_translate(d) && 
    5.61 -         !(pagetable_get_paddr(v->domain->arch.phys_table)) )
    5.62 -         shadow_direct_map_clean(v);
    5.63 -
    5.64      switch(levels) {
    5.65  #if CONFIG_PAGING_LEVELS == 4
    5.66      case 4:
    5.67 @@ -1330,43 +1319,133 @@ int _shadow_mode_refcounts(struct domain
    5.68      return shadow_mode_refcounts(d);
    5.69  }
    5.70  
    5.71 +static int
    5.72 +map_p2m_entry(
    5.73 +    pgentry_64_t *top_tab, unsigned long va, unsigned long gpa, unsigned long mfn)
    5.74 +{
    5.75 +#if CONFIG_PAGING_LEVELS >= 4
    5.76 +    pgentry_64_t l4e = { 0 };
    5.77 +#endif
    5.78 +#if CONFIG_PAGING_LEVELS >= 3
    5.79 +    pgentry_64_t *l3tab = NULL;
    5.80 +    pgentry_64_t l3e = { 0 };
    5.81 +#endif
    5.82 +    l2_pgentry_t *l2tab = NULL;
    5.83 +    l1_pgentry_t *l1tab = NULL;
    5.84 +    unsigned long *l0tab = NULL;
    5.85 +    l2_pgentry_t l2e = { 0 };
    5.86 +    l1_pgentry_t l1e = { 0 };
    5.87 +    struct page_info *page;
    5.88 +
    5.89 +#if CONFIG_PAGING_LEVELS >= 4
    5.90 +    l4e = top_tab[l4_table_offset(va)];
    5.91 +    if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) ) 
    5.92 +    {
    5.93 +        page = alloc_domheap_page(NULL);
    5.94 +        if ( !page )
    5.95 +            goto nomem;
    5.96 +
    5.97 +        l3tab = map_domain_page(page_to_mfn(page));
    5.98 +        memset(l3tab, 0, PAGE_SIZE);
    5.99 +        l4e = top_tab[l4_table_offset(va)] = 
   5.100 +            entry_from_page(page, __PAGE_HYPERVISOR);
   5.101 +    } 
   5.102 +    else if ( l3tab == NULL)
   5.103 +        l3tab = map_domain_page(entry_get_pfn(l4e));
   5.104 +
   5.105 +    l3e = l3tab[l3_table_offset(va)];
   5.106 +#else
   5.107 +    l3e = top_tab[l3_table_offset(va)];
   5.108 +#endif
   5.109 +    if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) ) 
   5.110 +    {
   5.111 +        page = alloc_domheap_page(NULL);
   5.112 +        if ( !page )
   5.113 +            goto nomem;
   5.114 +
   5.115 +        l2tab = map_domain_page(page_to_mfn(page));
   5.116 +        memset(l2tab, 0, PAGE_SIZE);
   5.117 +        l3e = l3tab[l3_table_offset(va)] = 
   5.118 +            entry_from_page(page, __PAGE_HYPERVISOR);
   5.119 +    } 
   5.120 +    else if ( l2tab == NULL) 
   5.121 +        l2tab = map_domain_page(entry_get_pfn(l3e));
   5.122 +
   5.123 +    l2e = l2tab[l2_table_offset(va)];
   5.124 +    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 
   5.125 +    {
   5.126 +        page = alloc_domheap_page(NULL);
   5.127 +        if ( !page )
   5.128 +            goto nomem;
   5.129 +
   5.130 +        l1tab = map_domain_page(page_to_mfn(page));
   5.131 +        memset(l1tab, 0, PAGE_SIZE);
   5.132 +        l2e = l2tab[l2_table_offset(va)] = 
   5.133 +            l2e_from_page(page, __PAGE_HYPERVISOR);
   5.134 +    } 
   5.135 +    else if ( l1tab == NULL) 
   5.136 +        l1tab = map_domain_page(l2e_get_pfn(l2e));
   5.137 +
   5.138 +    l1e = l1tab[l1_table_offset(va)];
   5.139 +    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 
   5.140 +    {
   5.141 +        page = alloc_domheap_page(NULL);
   5.142 +        if ( !page )
   5.143 +            goto nomem;
   5.144 +
   5.145 +        l0tab = map_domain_page(page_to_mfn(page));
   5.146 +        memset(l0tab, 0, PAGE_SIZE);
   5.147 +        l1e = l1tab[l1_table_offset(va)] = 
   5.148 +            l1e_from_page(page, __PAGE_HYPERVISOR);
   5.149 +    }
   5.150 +    else if ( l0tab == NULL) 
   5.151 +        l0tab = map_domain_page(l1e_get_pfn(l1e));
   5.152 +
   5.153 +    l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
   5.154 +
   5.155 +    if ( l2tab )
   5.156 +    {
   5.157 +        unmap_domain_page(l2tab);
   5.158 +        l2tab = NULL;
   5.159 +    }
   5.160 +    if ( l1tab )
   5.161 +    {
   5.162 +        unmap_domain_page(l1tab);
   5.163 +        l1tab = NULL;
   5.164 +    }
   5.165 +    if ( l0tab )
   5.166 +    {
   5.167 +        unmap_domain_page(l0tab);
   5.168 +        l0tab = NULL;
   5.169 +    }
   5.170 +
   5.171 +    return 1;
   5.172 +
   5.173 +nomem:
   5.174 +
   5.175 +    return 0;
   5.176 +}
   5.177 +
   5.178  int
   5.179  set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
   5.180                struct domain_mmap_cache *l2cache,
   5.181                struct domain_mmap_cache *l1cache)
   5.182  {
   5.183 -    unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table);
   5.184 -    l2_pgentry_t *l2, l2e;
   5.185 -    l1_pgentry_t *l1;
   5.186 -    struct page_info *l1page;
   5.187 -    unsigned long va = pfn << PAGE_SHIFT;
   5.188 +    unsigned long tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
   5.189 +    pgentry_64_t *top;
   5.190 +    unsigned long va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
   5.191 +    int error;
   5.192  
   5.193      ASSERT(tabpfn != 0);
   5.194 -
   5.195 -    l2 = map_domain_page_with_cache(tabpfn, l2cache);
   5.196 -    l2e = l2[l2_table_offset(va)];
   5.197 -    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
   5.198 -    {
   5.199 -        l1page = alloc_domheap_page(NULL);
   5.200 -        if ( !l1page )
   5.201 -        {
   5.202 -            unmap_domain_page_with_cache(l2, l2cache);
   5.203 -            return 0;
   5.204 -        }
   5.205 +    ASSERT(shadow_lock_is_acquired(d));
   5.206  
   5.207 -        l1 = map_domain_page_with_cache(page_to_mfn(l1page), l1cache);
   5.208 -        memset(l1, 0, PAGE_SIZE);
   5.209 -        unmap_domain_page_with_cache(l1, l1cache);
   5.210 +    top = map_domain_page_with_cache(tabpfn, l2cache);
   5.211 +    error = map_p2m_entry(top, va, pfn, mfn);
   5.212 +    unmap_domain_page_with_cache(top, l2cache);
   5.213  
   5.214 -        l2e = l2e_from_page(l1page, __PAGE_HYPERVISOR);
   5.215 -        l2[l2_table_offset(va)] = l2e;
   5.216 -    }
   5.217 -    unmap_domain_page_with_cache(l2, l2cache);
   5.218 -
   5.219 -    l1 = map_domain_page_with_cache(l2e_get_pfn(l2e), l1cache);
   5.220 -    l1[l1_table_offset(va)] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
   5.221 -    unmap_domain_page_with_cache(l1, l1cache);
   5.222 -
   5.223 +    if ( !error )
   5.224 +         domain_crash_synchronous();
   5.225 +        
   5.226      return 1;
   5.227  }
   5.228  
   5.229 @@ -1375,119 +1454,31 @@ alloc_p2m_table(struct domain *d)
   5.230  {
   5.231      struct list_head *list_ent;
   5.232      unsigned long va = RO_MPT_VIRT_START; /*  phys_to_machine_mapping */
   5.233 -
   5.234 -#if CONFIG_PAGING_LEVELS >= 4
   5.235 -    l4_pgentry_t *l4tab = NULL;
   5.236 -    l4_pgentry_t l4e = { 0 };
   5.237 -#endif
   5.238 -#if CONFIG_PAGING_LEVELS >= 3
   5.239 -    l3_pgentry_t *l3tab = NULL;
   5.240 -    l3_pgentry_t l3e = { 0 };
   5.241 -#endif
   5.242 -    l2_pgentry_t *l2tab = NULL;
   5.243 -    l1_pgentry_t *l1tab = NULL;
   5.244 -    unsigned long *l0tab = NULL;
   5.245 -    l2_pgentry_t l2e = { 0 };
   5.246 -    l1_pgentry_t l1e = { 0 };
   5.247 -
   5.248 -    unsigned long pfn;
   5.249 -    int i;
   5.250 +    pgentry_64_t *top_tab = NULL;
   5.251 +    unsigned long mfn;
   5.252 +    int gpa;
   5.253  
   5.254      ASSERT ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
   5.255  
   5.256 -#if CONFIG_PAGING_LEVELS >= 4
   5.257 -    l4tab = map_domain_page(
   5.258 +    top_tab = map_domain_page(
   5.259          pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
   5.260 -#endif
   5.261 -#if CONFIG_PAGING_LEVELS >= 3
   5.262 -    l3tab = map_domain_page(
   5.263 -        pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
   5.264 -#endif
   5.265 +
   5.266  
   5.267      list_ent = d->page_list.next;
   5.268  
   5.269 -    for ( i = 0; list_ent != &d->page_list; i++ ) 
   5.270 +    for ( gpa = 0; list_ent != &d->page_list; gpa++ ) 
   5.271      {
   5.272          struct page_info *page;
   5.273 -
   5.274          page = list_entry(list_ent, struct page_info, list);
   5.275 -        pfn = page_to_mfn(page);
   5.276 -
   5.277 -#if CONFIG_PAGING_LEVELS >= 4
   5.278 -        l4e = l4tab[l4_table_offset(va)];
   5.279 -        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) 
   5.280 -        {
   5.281 -            page = alloc_domheap_page(NULL);
   5.282 -            l3tab = map_domain_page(page_to_mfn(page));
   5.283 -            memset(l3tab, 0, PAGE_SIZE);
   5.284 -            l4e = l4tab[l4_table_offset(va)] = 
   5.285 -                l4e_from_page(page, __PAGE_HYPERVISOR);
   5.286 -        } 
   5.287 -        else if ( l3tab == NULL)
   5.288 -            l3tab = map_domain_page(l4e_get_pfn(l4e));
   5.289 -#endif
   5.290 -        l3e = l3tab[l3_table_offset(va)];
   5.291 -        if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) 
   5.292 -        {
   5.293 -            page = alloc_domheap_page(NULL);
   5.294 -            l2tab = map_domain_page(page_to_mfn(page));
   5.295 -            memset(l2tab, 0, PAGE_SIZE);
   5.296 -            l3e = l3tab[l3_table_offset(va)] = 
   5.297 -                l3e_from_page(page, __PAGE_HYPERVISOR);
   5.298 -        } 
   5.299 -        else if ( l2tab == NULL) 
   5.300 -            l2tab = map_domain_page(l3e_get_pfn(l3e));
   5.301 +        mfn = page_to_mfn(page);
   5.302  
   5.303 -        l2e = l2tab[l2_table_offset(va)];
   5.304 -        if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 
   5.305 -        {
   5.306 -            page = alloc_domheap_page(NULL);
   5.307 -            l1tab = map_domain_page(page_to_mfn(page));
   5.308 -            memset(l1tab, 0, PAGE_SIZE);
   5.309 -            l2e = l2tab[l2_table_offset(va)] = 
   5.310 -                l2e_from_page(page, __PAGE_HYPERVISOR);
   5.311 -        } 
   5.312 -        else if ( l1tab == NULL) 
   5.313 -            l1tab = map_domain_page(l2e_get_pfn(l2e));
   5.314 -
   5.315 -        l1e = l1tab[l1_table_offset(va)];
   5.316 -        if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 
   5.317 -        {
   5.318 -            page = alloc_domheap_page(NULL);
   5.319 -            l0tab = map_domain_page(page_to_mfn(page));
   5.320 -            memset(l0tab, 0, PAGE_SIZE);
   5.321 -            l1e = l1tab[l1_table_offset(va)] = 
   5.322 -                l1e_from_page(page, __PAGE_HYPERVISOR);
   5.323 -        }
   5.324 -        else if ( l0tab == NULL) 
   5.325 -            l0tab = map_domain_page(l1e_get_pfn(l1e));
   5.326 +        map_p2m_entry(top_tab, va, gpa, mfn);
   5.327 +        list_ent = frame_table[mfn].list.next;
   5.328 +        va += sizeof(mfn);
   5.329 +    }
   5.330  
   5.331 -        l0tab[i & ((PAGE_SIZE / sizeof (pfn)) - 1) ] = pfn;
   5.332 -        list_ent = frame_table[pfn].list.next;
   5.333 -        va += sizeof (pfn);
   5.334 +    unmap_domain_page(top_tab);
   5.335  
   5.336 -        if ( l2tab )
   5.337 -        {
   5.338 -            unmap_domain_page(l2tab);
   5.339 -            l2tab = NULL;
   5.340 -        }
   5.341 -        if ( l1tab )
   5.342 -        {
   5.343 -            unmap_domain_page(l1tab);
   5.344 -            l1tab = NULL;
   5.345 -        }
   5.346 -        if ( l0tab )
   5.347 -        {
   5.348 -            unmap_domain_page(l0tab);
   5.349 -            l0tab = NULL;
   5.350 -        }
   5.351 -    }
   5.352 -#if CONFIG_PAGING_LEVELS >= 4
   5.353 -    unmap_domain_page(l4tab);
   5.354 -#endif
   5.355 -#if CONFIG_PAGING_LEVELS >= 3
   5.356 -    unmap_domain_page(l3tab);
   5.357 -#endif
   5.358      return 1;
   5.359  }
   5.360  
     6.1 --- a/xen/include/asm-x86/shadow.h	Thu Feb 16 16:35:09 2006 +0100
     6.2 +++ b/xen/include/asm-x86/shadow.h	Thu Feb 16 16:46:21 2006 +0100
     6.3 @@ -115,9 +115,7 @@ do {                                    
     6.4  #define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min))
     6.5  #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
     6.6  #define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16))
     6.7 -#if CONFIG_PAGING_LEVELS == 2
     6.8  extern void shadow_direct_map_clean(struct vcpu *v);
     6.9 -#endif
    6.10  extern int shadow_direct_map_init(struct vcpu *v);
    6.11  extern int shadow_direct_map_fault(
    6.12      unsigned long vpa, struct cpu_user_regs *regs);
    6.13 @@ -559,6 +557,38 @@ static inline void
    6.14  }
    6.15  
    6.16  static inline void
    6.17 +__direct_get_l2e(
    6.18 +    struct vcpu *v, unsigned long va, l2_pgentry_t *psl2e)
    6.19 +{
    6.20 +    l2_pgentry_t *phys_vtable;
    6.21 +
    6.22 +    ASSERT(shadow_mode_enabled(v->domain));
    6.23 +
    6.24 +    phys_vtable = map_domain_page(
    6.25 +        pagetable_get_pfn(v->domain->arch.phys_table));
    6.26 +
    6.27 +    *psl2e = phys_vtable[l2_table_offset(va)];
    6.28 +
    6.29 +    unmap_domain_page(phys_vtable);
    6.30 +}
    6.31 +
    6.32 +static inline void
    6.33 +__direct_set_l2e(
    6.34 +    struct vcpu *v, unsigned long va, l2_pgentry_t value)
    6.35 +{
    6.36 +    l2_pgentry_t *phys_vtable;
    6.37 +
    6.38 +    ASSERT(shadow_mode_enabled(v->domain));
    6.39 +
    6.40 +    phys_vtable = map_domain_page(
    6.41 +        pagetable_get_pfn(v->domain->arch.phys_table));
    6.42 +
    6.43 +    phys_vtable[l2_table_offset(va)] = value;
    6.44 +
    6.45 +    unmap_domain_page(phys_vtable);
    6.46 +}
    6.47 +
    6.48 +static inline void
    6.49  update_hl2e(struct vcpu *v, unsigned long va)
    6.50  {
    6.51      int index = l2_table_offset(va);
     7.1 --- a/xen/include/asm-x86/shadow_64.h	Thu Feb 16 16:35:09 2006 +0100
     7.2 +++ b/xen/include/asm-x86/shadow_64.h	Thu Feb 16 16:46:21 2006 +0100
     7.3 @@ -66,9 +66,12 @@ typedef struct { intpte_t l4; } l4_pgent
     7.4  #define PAGING_L1      1UL
     7.5  #define L_MASK  0xff
     7.6  
     7.7 +#define PAE_PAGING_LEVELS   3
     7.8 +
     7.9  #define ROOT_LEVEL_64   PAGING_L4
    7.10  #define ROOT_LEVEL_32   PAGING_L2
    7.11  
    7.12 +#define DIRECT_ENTRY    (4UL << 16)
    7.13  #define SHADOW_ENTRY    (2UL << 16)
    7.14  #define GUEST_ENTRY     (1UL << 16)
    7.15  
    7.16 @@ -94,6 +97,7 @@ typedef struct { intpte_t lo; } pgentry_
    7.17  #define entry_empty()           ((pgentry_64_t) { 0 })
    7.18  #define entry_from_pfn(pfn, flags)  \
    7.19      ((pgentry_64_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
    7.20 +#define entry_from_page(page, flags) (entry_from_pfn(page_to_mfn(page),(flags)))
    7.21  #define entry_add_flags(x, flags)    ((x).lo |= put_pte_flags(flags))
    7.22  #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags))
    7.23  #define entry_has_changed(x,y,flags) \
    7.24 @@ -162,16 +166,24 @@ static inline int __entry(
    7.25  
    7.26      if ( flag & SHADOW_ENTRY )
    7.27      {
    7.28 -	root_level =  ROOT_LEVEL_64;
    7.29 -	index = table_offset_64(va, root_level);
    7.30 +        root_level =  ROOT_LEVEL_64;
    7.31 +        index = table_offset_64(va, root_level);
    7.32          le_e = (pgentry_64_t *)&v->arch.shadow_vtable[index];
    7.33      }
    7.34 -    else /* guest entry */  
    7.35 +    else if ( flag & GUEST_ENTRY )
    7.36      {
    7.37          root_level = v->domain->arch.ops->guest_paging_levels;
    7.38 -	index = table_offset_64(va, root_level);
    7.39 +        index = table_offset_64(va, root_level);
    7.40          le_e = (pgentry_64_t *)&v->arch.guest_vtable[index];
    7.41      }
    7.42 +    else /* direct mode */
    7.43 +    {
    7.44 +        root_level = PAE_PAGING_LEVELS;
    7.45 +        index = table_offset_64(va, root_level);
    7.46 +        le_e = (pgentry_64_t *)map_domain_page(
    7.47 +            pagetable_get_pfn(v->domain->arch.phys_table));
    7.48 +    }
    7.49 +
    7.50      /*
    7.51       * If it's not external mode, then mfn should be machine physical.
    7.52       */
    7.53 @@ -241,6 +253,20 @@ static inline int __rw_entry(
    7.54  #define __guest_get_l3e(v, va, sl3e) \
    7.55    __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3)
    7.56  
    7.57 +#define __direct_set_l3e(v, va, value) \
    7.58 +  __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L3)
    7.59 +#define __direct_get_l3e(v, va, sl3e) \
    7.60 +  __rw_entry(v, va, sl3e, DIRECT_ENTRY | GET_ENTRY | PAGING_L3)
    7.61 +#define __direct_set_l2e(v, va, value) \
    7.62 +  __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L2)
    7.63 +#define __direct_get_l2e(v, va, sl2e) \
    7.64 +  __rw_entry(v, va, sl2e, DIRECT_ENTRY | GET_ENTRY | PAGING_L2)
    7.65 +#define __direct_set_l1e(v, va, value) \
    7.66 +  __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L1)
    7.67 +#define __direct_get_l1e(v, va, sl1e) \
    7.68 +  __rw_entry(v, va, sl1e, DIRECT_ENTRY | GET_ENTRY | PAGING_L1)
    7.69 +
    7.70 +
    7.71  static inline int  __guest_set_l2e(
    7.72      struct vcpu *v, unsigned long va, void *value, int size)
    7.73  {