[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Fix problems with direct-mapping handling especially when



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID a543a4778a7d9888fad13ffafff0aa9bc5541b48
# Parent  bee659de2a369cbf1da2e7751c0eb5e2f0e11dec
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@xxxxxxxxx>
Signed-off-by: Xin B Li <xin.b.li@xxxxxxxxx>
Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>

diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Thu Feb 16 15:35:09 2006
+++ b/xen/arch/x86/hvm/svm/svm.c        Thu Feb 16 15:46:21 2006
@@ -799,6 +799,7 @@
         struct domain *d = v->domain;
         if (d->arch.hvm_domain.shared_page_va)
             unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va);
+        shadow_direct_map_clean(v);
     }
 
     destroy_vmcb(&v->arch.hvm_svm);
@@ -1443,9 +1444,7 @@
                 put_page(mfn_to_page(old_base_mfn));
        }
 #endif
-#if CONFIG_PAGING_LEVELS == 2
-        shadow_direct_map_clean(v);
-#endif
+
         /* Now arch.guest_table points to machine physical. */
         v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
         update_pagetables(v);
diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Feb 16 15:35:09 2006
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Feb 16 15:46:21 2006
@@ -88,6 +88,7 @@
         if ( d->arch.hvm_domain.shared_page_va )
             unmap_domain_page_global(
                (void *)d->arch.hvm_domain.shared_page_va);
+        shadow_direct_map_clean(v);
     }
 
     vmx_request_clear_vmcs(v);
@@ -1227,9 +1228,7 @@
                 __vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
             }
         }
-#if CONFIG_PAGING_LEVELS == 2
-        shadow_direct_map_clean(v);
-#endif
+
         /*
          * Now arch.guest_table points to machine physical.
          */
diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     Thu Feb 16 15:35:09 2006
+++ b/xen/arch/x86/shadow.c     Thu Feb 16 15:46:21 2006
@@ -3743,6 +3743,7 @@
 #if ( CONFIG_PAGING_LEVELS == 3 && !defined (GUEST_PGENTRY_32) ) ||  \
     ( CONFIG_PAGING_LEVELS == 4 && defined (GUEST_PGENTRY_32) )
 
+
 /* 
  * Use GUEST_PGENTRY_32 to force PAE_SHADOW_SELF_ENTRY for L4.
  *
@@ -3756,8 +3757,8 @@
 {
     struct vcpu *v = current;
     struct domain *d = v->domain;
-    l3_pgentry_t sl3e;
-    l2_pgentry_t sl2e;
+    l3_pgentry_t sl3e, *sl3e_p;
+    l2_pgentry_t sl2e, *sl2e_p;
     l1_pgentry_t sl1e;
     unsigned long mfn, smfn;
     struct page_info *page;
@@ -3773,37 +3774,47 @@
 
     shadow_lock(d);
 
-    __shadow_get_l3e(v, vpa, &sl3e);
+    __direct_get_l3e(v, vpa, &sl3e);
 
     if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT) ) 
     {
         page = alloc_domheap_page(NULL);
         if ( !page )
-            goto fail; 
+            goto nomem; 
+
         smfn = page_to_mfn(page);
         sl3e = l3e_from_pfn(smfn, _PAGE_PRESENT);
-        __shadow_set_l3e(v, vpa, &sl3e);
-    }
-
-    __shadow_get_l2e(v, vpa, &sl2e);
+
+        sl3e_p = (l3_pgentry_t *)map_domain_page(smfn);
+        memset(sl3e_p, 0, PAGE_SIZE);
+        unmap_domain_page(sl3e_p);
+
+        __direct_set_l3e(v, vpa, &sl3e);
+    }
+
+    __direct_get_l2e(v, vpa, &sl2e);
 
     if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) ) 
     {
         page = alloc_domheap_page(NULL);
         if ( !page )
-            goto fail; 
+            goto nomem; 
+
         smfn = page_to_mfn(page);
-
         sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER);
-        __shadow_set_l2e(v, vpa, &sl2e);
-    }
-
-    __shadow_get_l1e(v, vpa, &sl1e);
+        sl2e_p = (l2_pgentry_t *)map_domain_page(smfn);
+        memset(sl2e_p, 0, PAGE_SIZE);
+        unmap_domain_page(sl2e_p);
+
+        __direct_set_l2e(v, vpa, &sl2e);
+    }
+
+    __direct_get_l1e(v, vpa, &sl1e);
 
     if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) ) 
     {
         sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER);
-        __shadow_set_l1e(v, vpa, &sl1e);
+        __direct_set_l1e(v, vpa, &sl1e);
     } 
 
     shadow_unlock(d);
@@ -3811,6 +3822,10 @@
 
 fail:
     return 0;
+
+nomem:
+    shadow_direct_map_clean(v);
+    domain_crash_synchronous();
 }
 #endif
 
diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Thu Feb 16 15:35:09 2006
+++ b/xen/arch/x86/shadow32.c   Thu Feb 16 15:46:21 2006
@@ -807,21 +807,99 @@
     v->arch.monitor_vtable = 0;
 }
 
+static int
+map_p2m_entry(
+    l1_pgentry_t *l1tab, unsigned long va, unsigned long gpa, unsigned long 
mfn)
+{
+    unsigned long *l0tab = NULL;
+    l1_pgentry_t l1e = { 0 };
+    struct page_info *page;
+
+    l1e = l1tab[l1_table_offset(va)];
+    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
+    {
+        page = alloc_domheap_page(NULL);
+        if ( !page )
+            goto fail;
+
+        if ( l0tab  )
+            unmap_domain_page(l0tab);
+        l0tab = map_domain_page(page_to_mfn(page));
+        memset(l0tab, 0, PAGE_SIZE );
+        l1e = l1tab[l1_table_offset(va)] =
+            l1e_from_page(page, __PAGE_HYPERVISOR);
+    }
+    else if ( l0tab == NULL)
+        l0tab = map_domain_page(l1e_get_pfn(l1e));
+
+    l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
+
+    if ( l0tab )
+        unmap_domain_page(l0tab);
+
+    return 1;
+
+fail:
+    return 0;
+}
+
 int
 set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
               struct domain_mmap_cache *l2cache,
               struct domain_mmap_cache *l1cache)
 {
-    unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table);
+    unsigned long tabpfn;
     l2_pgentry_t *l2, l2e;
     l1_pgentry_t *l1;
     struct page_info *l1page;
     unsigned long va = pfn << PAGE_SHIFT;
+    int error;
+
+    if ( shadow_mode_external(d) )
+    {
+        tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+        va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
+    }
+    else
+    {
+        tabpfn = pagetable_get_pfn(d->arch.phys_table);
+        va = pfn << PAGE_SHIFT;
+    }
 
     ASSERT(tabpfn != 0);
     ASSERT(shadow_lock_is_acquired(d));
 
     l2 = map_domain_page_with_cache(tabpfn, l2cache);
+
+    /*
+     * The following code covers (SHM_translate | SHM_external) mode.
+     */
+
+    if ( shadow_mode_external(d) )
+    {
+        l1_pgentry_t *l1tab = NULL;
+        l2_pgentry_t l2e;
+
+        l2e = l2[l2_table_offset(va)];
+
+        ASSERT( l2e_get_flags(l2e) & _PAGE_PRESENT );
+
+        l1tab = map_domain_page(l2e_get_pfn(l2e));
+        error = map_p2m_entry(l1tab, va, pfn, mfn);
+        if ( !error )
+            domain_crash_synchronous(); 
+
+        unmap_domain_page(l1tab);
+        unmap_domain_page_with_cache(l2, l2cache);
+
+        return 1;
+    }
+
+    /*
+     * The following code covers SHM_translate mode.
+     */
+    ASSERT(shadow_mode_translate(d));
+
     l2e = l2[l2_table_offset(va)];
     if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
     {
@@ -856,13 +934,10 @@
 
     l2_pgentry_t *l2tab = NULL;
     l1_pgentry_t *l1tab = NULL;
-    unsigned long *l0tab = NULL;
     l2_pgentry_t l2e = { 0 };
-    l1_pgentry_t l1e = { 0 };
-
     struct page_info *page;
-    unsigned long pfn;
-    int i;
+    unsigned long gpfn, mfn;
+    int error;
 
     if ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) )
     {
@@ -892,34 +967,22 @@
 
     list_ent = d->page_list.next;
 
-    for ( i = 0; list_ent != &d->page_list; i++ )
+    for ( gpfn = 0; list_ent != &d->page_list; gpfn++ )
     {
         page = list_entry(list_ent, struct page_info, list);
-        pfn = page_to_mfn(page);
-
-        l1e = l1tab[l1_table_offset(va)];
-        if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
-        {
-            page = alloc_domheap_page(NULL);
-            if ( l0tab  )
-                unmap_domain_page(l0tab);
-            l0tab = map_domain_page(page_to_mfn(page));
-            memset(l0tab, 0, PAGE_SIZE );
-            l1e = l1tab[l1_table_offset(va)] =
-                l1e_from_page(page, __PAGE_HYPERVISOR);
-        }
-        else if ( l0tab == NULL)
-            l0tab = map_domain_page(l1e_get_pfn(l1e));
-
-        l0tab[i & ((1 << PAGETABLE_ORDER) - 1) ] = pfn;
-        list_ent = frame_table[pfn].list.next;
-        va += sizeof(pfn);
+        mfn = page_to_mfn(page);
+
+        error = map_p2m_entry(l1tab, va, gpfn, mfn);
+        if ( !error )
+            domain_crash_synchronous(); 
+
+        list_ent = frame_table[mfn].list.next;
+        va += sizeof(mfn);
     }
 
     if (l2tab)
         unmap_domain_page(l2tab);
     unmap_domain_page(l1tab);
-    unmap_domain_page(l0tab);
 
     return 1;
 }
@@ -981,21 +1044,26 @@
     }
 
     shadow_lock(d);
-
-    __shadow_get_l2e(v, vpa, &sl2e);
-
-   if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
+  
+   __direct_get_l2e(v, vpa, &sl2e);
+
+    if ( !(l2e_get_flags(sl2e) & _PAGE_PRESENT) )
     {
         page = alloc_domheap_page(NULL);
         if ( !page )
-            goto fail;
+            goto nomem;
 
         smfn = page_to_mfn(page);
         sl2e = l2e_from_pfn(smfn, __PAGE_HYPERVISOR | _PAGE_USER);
-        __shadow_set_l2e(v, vpa, sl2e);
-    }
-
-    sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e));
+
+        sple = (l1_pgentry_t *)map_domain_page(smfn);
+        memset(sple, 0, PAGE_SIZE);
+        __direct_set_l2e(v, vpa, sl2e);
+    } 
+
+    if ( !sple )
+        sple = (l1_pgentry_t *)map_domain_page(l2e_get_pfn(sl2e));
+
     sl1e = sple[l1_table_offset(vpa)];
 
     if ( !(l1e_get_flags(sl1e) & _PAGE_PRESENT) )
@@ -1003,13 +1071,19 @@
         sl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR | _PAGE_USER);
         sple[l1_table_offset(vpa)] = sl1e;
     }
-    unmap_domain_page(sple);
+
+    if (sple)
+        unmap_domain_page(sple);
+
     shadow_unlock(d);
-
     return EXCRET_fault_fixed;
 
 fail:
     return 0;
+
+nomem:
+    shadow_direct_map_clean(v);
+    domain_crash_synchronous();
 }
 
 
@@ -1021,16 +1095,12 @@
     if ( !(page = alloc_domheap_page(NULL)) )
         goto fail;
 
-    root = map_domain_page_global(page_to_mfn(page));
+    root = map_domain_page(page_to_mfn(page));
     memset(root, 0, PAGE_SIZE);
+    unmap_domain_page(root);
 
     v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page));
-    /* 
-     * We need to set shadow_vtable to get __shadow_set/get_xxx
-     * working
-     */
-    v->arch.shadow_vtable = (l2_pgentry_t *) root;
-    v->arch.shadow_table = mk_pagetable(0);
+
     return 1;
 
 fail:
@@ -1042,9 +1112,8 @@
     int i;
     l2_pgentry_t *l2e;
 
-    ASSERT ( v->arch.shadow_vtable );
-
-    l2e = v->arch.shadow_vtable;
+    l2e = map_domain_page(
+      pagetable_get_pfn(v->domain->arch.phys_table));
 
     for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
     {
@@ -1055,8 +1124,7 @@
     free_domheap_page(
             mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table)));
 
-    unmap_domain_page_global(v->arch.shadow_vtable);
-    v->arch.shadow_vtable = 0;
+    unmap_domain_page(l2e);
     v->domain->arch.phys_table = mk_pagetable(0);
 }
 
@@ -1168,13 +1236,6 @@
                 printk("alloc_p2m_table failed (out-of-memory?)\n");
                 goto nomem;
             }
-        }
-        else
-        {
-            // external guests provide their own memory for their P2M maps.
-            //
-            ASSERT(d == page_get_owner(mfn_to_page(pagetable_get_pfn(
-                d->arch.phys_table))));
         }
     }
 
diff -r bee659de2a36 -r a543a4778a7d xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c      Thu Feb 16 15:35:09 2006
+++ b/xen/arch/x86/shadow_public.c      Thu Feb 16 15:46:21 2006
@@ -44,33 +44,28 @@
     if ( !(page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA)) )
         goto fail;
 
-    root = map_domain_page_global(page_to_mfn(page));
+    root = map_domain_page(page_to_mfn(page));
     memset(root, 0, PAGE_SIZE);
     root[PAE_SHADOW_SELF_ENTRY] = l3e_from_page(page, __PAGE_HYPERVISOR);
 
     v->domain->arch.phys_table = mk_pagetable(page_to_maddr(page));
-    /* 
-     * We need to set shadow_vtable to get __shadow_set/get_xxx
-     * working
-     */
-    v->arch.shadow_vtable = (l2_pgentry_t *) root;
-
+
+    unmap_domain_page(root);
     return 1;
-    
+
 fail:
     return 0;
 }
 
-static void shadow_direct_map_clean(struct vcpu *v)
+void shadow_direct_map_clean(struct vcpu *v)
 {
     l2_pgentry_t *l2e;
     l3_pgentry_t *l3e;
     int i, j;
 
-    ASSERT ( v->arch.shadow_vtable );
-
-    l3e = (l3_pgentry_t *) v->arch.shadow_vtable;
-    
+    l3e = (l3_pgentry_t *)map_domain_page(
+        pagetable_get_pfn(v->domain->arch.phys_table));
+
     for ( i = 0; i < PAE_L3_PAGETABLE_ENTRIES; i++ )
     {
         if ( l3e_get_flags(l3e[i]) & _PAGE_PRESENT )
@@ -90,8 +85,7 @@
     free_domheap_page(
         mfn_to_page(pagetable_get_pfn(v->domain->arch.phys_table)));
 
-    unmap_domain_page_global(v->arch.shadow_vtable);
-    v->arch.shadow_vtable = 0;
+    unmap_domain_page(l3e);
     v->domain->arch.phys_table = mk_pagetable(0);
 }
 
@@ -102,12 +96,7 @@
 
 int shadow_set_guest_paging_levels(struct domain *d, int levels)
 {
-    struct vcpu *v = current;
     shadow_lock(d);
-
-    if ( shadow_mode_translate(d) && 
-         !(pagetable_get_paddr(v->domain->arch.phys_table)) )
-         shadow_direct_map_clean(v);
 
     switch(levels) {
 #if CONFIG_PAGING_LEVELS == 4
@@ -1330,164 +1319,166 @@
     return shadow_mode_refcounts(d);
 }
 
-int
-set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
-              struct domain_mmap_cache *l2cache,
-              struct domain_mmap_cache *l1cache)
-{
-    unsigned long tabpfn = pagetable_get_pfn(d->arch.phys_table);
-    l2_pgentry_t *l2, l2e;
-    l1_pgentry_t *l1;
-    struct page_info *l1page;
-    unsigned long va = pfn << PAGE_SHIFT;
-
-    ASSERT(tabpfn != 0);
-
-    l2 = map_domain_page_with_cache(tabpfn, l2cache);
-    l2e = l2[l2_table_offset(va)];
-    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
-    {
-        l1page = alloc_domheap_page(NULL);
-        if ( !l1page )
-        {
-            unmap_domain_page_with_cache(l2, l2cache);
-            return 0;
-        }
-
-        l1 = map_domain_page_with_cache(page_to_mfn(l1page), l1cache);
-        memset(l1, 0, PAGE_SIZE);
-        unmap_domain_page_with_cache(l1, l1cache);
-
-        l2e = l2e_from_page(l1page, __PAGE_HYPERVISOR);
-        l2[l2_table_offset(va)] = l2e;
-    }
-    unmap_domain_page_with_cache(l2, l2cache);
-
-    l1 = map_domain_page_with_cache(l2e_get_pfn(l2e), l1cache);
-    l1[l1_table_offset(va)] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
-    unmap_domain_page_with_cache(l1, l1cache);
-
-    return 1;
-}
-
-int
-alloc_p2m_table(struct domain *d)
-{
-    struct list_head *list_ent;
-    unsigned long va = RO_MPT_VIRT_START; /*  phys_to_machine_mapping */
-
+static int
+map_p2m_entry(
+    pgentry_64_t *top_tab, unsigned long va, unsigned long gpa, unsigned long 
mfn)
+{
 #if CONFIG_PAGING_LEVELS >= 4
-    l4_pgentry_t *l4tab = NULL;
-    l4_pgentry_t l4e = { 0 };
+    pgentry_64_t l4e = { 0 };
 #endif
 #if CONFIG_PAGING_LEVELS >= 3
-    l3_pgentry_t *l3tab = NULL;
-    l3_pgentry_t l3e = { 0 };
+    pgentry_64_t *l3tab = NULL;
+    pgentry_64_t l3e = { 0 };
 #endif
     l2_pgentry_t *l2tab = NULL;
     l1_pgentry_t *l1tab = NULL;
     unsigned long *l0tab = NULL;
     l2_pgentry_t l2e = { 0 };
     l1_pgentry_t l1e = { 0 };
-
-    unsigned long pfn;
-    int i;
+    struct page_info *page;
+
+#if CONFIG_PAGING_LEVELS >= 4
+    l4e = top_tab[l4_table_offset(va)];
+    if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) ) 
+    {
+        page = alloc_domheap_page(NULL);
+        if ( !page )
+            goto nomem;
+
+        l3tab = map_domain_page(page_to_mfn(page));
+        memset(l3tab, 0, PAGE_SIZE);
+        l4e = top_tab[l4_table_offset(va)] = 
+            entry_from_page(page, __PAGE_HYPERVISOR);
+    } 
+    else if ( l3tab == NULL)
+        l3tab = map_domain_page(entry_get_pfn(l4e));
+
+    l3e = l3tab[l3_table_offset(va)];
+#else
+    l3e = top_tab[l3_table_offset(va)];
+#endif
+    if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) ) 
+    {
+        page = alloc_domheap_page(NULL);
+        if ( !page )
+            goto nomem;
+
+        l2tab = map_domain_page(page_to_mfn(page));
+        memset(l2tab, 0, PAGE_SIZE);
+        l3e = l3tab[l3_table_offset(va)] = 
+            entry_from_page(page, __PAGE_HYPERVISOR);
+    } 
+    else if ( l2tab == NULL) 
+        l2tab = map_domain_page(entry_get_pfn(l3e));
+
+    l2e = l2tab[l2_table_offset(va)];
+    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 
+    {
+        page = alloc_domheap_page(NULL);
+        if ( !page )
+            goto nomem;
+
+        l1tab = map_domain_page(page_to_mfn(page));
+        memset(l1tab, 0, PAGE_SIZE);
+        l2e = l2tab[l2_table_offset(va)] = 
+            l2e_from_page(page, __PAGE_HYPERVISOR);
+    } 
+    else if ( l1tab == NULL) 
+        l1tab = map_domain_page(l2e_get_pfn(l2e));
+
+    l1e = l1tab[l1_table_offset(va)];
+    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 
+    {
+        page = alloc_domheap_page(NULL);
+        if ( !page )
+            goto nomem;
+
+        l0tab = map_domain_page(page_to_mfn(page));
+        memset(l0tab, 0, PAGE_SIZE);
+        l1e = l1tab[l1_table_offset(va)] = 
+            l1e_from_page(page, __PAGE_HYPERVISOR);
+    }
+    else if ( l0tab == NULL) 
+        l0tab = map_domain_page(l1e_get_pfn(l1e));
+
+    l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
+
+    if ( l2tab )
+    {
+        unmap_domain_page(l2tab);
+        l2tab = NULL;
+    }
+    if ( l1tab )
+    {
+        unmap_domain_page(l1tab);
+        l1tab = NULL;
+    }
+    if ( l0tab )
+    {
+        unmap_domain_page(l0tab);
+        l0tab = NULL;
+    }
+
+    return 1;
+
+nomem:
+
+    return 0;
+}
+
+int
+set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
+              struct domain_mmap_cache *l2cache,
+              struct domain_mmap_cache *l1cache)
+{
+    unsigned long tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+    pgentry_64_t *top;
+    unsigned long va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
+    int error;
+
+    ASSERT(tabpfn != 0);
+    ASSERT(shadow_lock_is_acquired(d));
+
+    top = map_domain_page_with_cache(tabpfn, l2cache);
+    error = map_p2m_entry(top, va, pfn, mfn);
+    unmap_domain_page_with_cache(top, l2cache);
+
+    if ( !error )
+         domain_crash_synchronous();
+        
+    return 1;
+}
+
+int
+alloc_p2m_table(struct domain *d)
+{
+    struct list_head *list_ent;
+    unsigned long va = RO_MPT_VIRT_START; /*  phys_to_machine_mapping */
+    pgentry_64_t *top_tab = NULL;
+    unsigned long mfn;
+    int gpa;
 
     ASSERT ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
 
-#if CONFIG_PAGING_LEVELS >= 4
-    l4tab = map_domain_page(
+    top_tab = map_domain_page(
         pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
-#endif
-#if CONFIG_PAGING_LEVELS >= 3
-    l3tab = map_domain_page(
-        pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
-#endif
+
 
     list_ent = d->page_list.next;
 
-    for ( i = 0; list_ent != &d->page_list; i++ ) 
+    for ( gpa = 0; list_ent != &d->page_list; gpa++ ) 
     {
         struct page_info *page;
-
         page = list_entry(list_ent, struct page_info, list);
-        pfn = page_to_mfn(page);
-
-#if CONFIG_PAGING_LEVELS >= 4
-        l4e = l4tab[l4_table_offset(va)];
-        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) 
-        {
-            page = alloc_domheap_page(NULL);
-            l3tab = map_domain_page(page_to_mfn(page));
-            memset(l3tab, 0, PAGE_SIZE);
-            l4e = l4tab[l4_table_offset(va)] = 
-                l4e_from_page(page, __PAGE_HYPERVISOR);
-        } 
-        else if ( l3tab == NULL)
-            l3tab = map_domain_page(l4e_get_pfn(l4e));
-#endif
-        l3e = l3tab[l3_table_offset(va)];
-        if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) 
-        {
-            page = alloc_domheap_page(NULL);
-            l2tab = map_domain_page(page_to_mfn(page));
-            memset(l2tab, 0, PAGE_SIZE);
-            l3e = l3tab[l3_table_offset(va)] = 
-                l3e_from_page(page, __PAGE_HYPERVISOR);
-        } 
-        else if ( l2tab == NULL) 
-            l2tab = map_domain_page(l3e_get_pfn(l3e));
-
-        l2e = l2tab[l2_table_offset(va)];
-        if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) 
-        {
-            page = alloc_domheap_page(NULL);
-            l1tab = map_domain_page(page_to_mfn(page));
-            memset(l1tab, 0, PAGE_SIZE);
-            l2e = l2tab[l2_table_offset(va)] = 
-                l2e_from_page(page, __PAGE_HYPERVISOR);
-        } 
-        else if ( l1tab == NULL) 
-            l1tab = map_domain_page(l2e_get_pfn(l2e));
-
-        l1e = l1tab[l1_table_offset(va)];
-        if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) 
-        {
-            page = alloc_domheap_page(NULL);
-            l0tab = map_domain_page(page_to_mfn(page));
-            memset(l0tab, 0, PAGE_SIZE);
-            l1e = l1tab[l1_table_offset(va)] = 
-                l1e_from_page(page, __PAGE_HYPERVISOR);
-        }
-        else if ( l0tab == NULL) 
-            l0tab = map_domain_page(l1e_get_pfn(l1e));
-
-        l0tab[i & ((PAGE_SIZE / sizeof (pfn)) - 1) ] = pfn;
-        list_ent = frame_table[pfn].list.next;
-        va += sizeof (pfn);
-
-        if ( l2tab )
-        {
-            unmap_domain_page(l2tab);
-            l2tab = NULL;
-        }
-        if ( l1tab )
-        {
-            unmap_domain_page(l1tab);
-            l1tab = NULL;
-        }
-        if ( l0tab )
-        {
-            unmap_domain_page(l0tab);
-            l0tab = NULL;
-        }
-    }
-#if CONFIG_PAGING_LEVELS >= 4
-    unmap_domain_page(l4tab);
-#endif
-#if CONFIG_PAGING_LEVELS >= 3
-    unmap_domain_page(l3tab);
-#endif
+        mfn = page_to_mfn(page);
+
+        map_p2m_entry(top_tab, va, gpa, mfn);
+        list_ent = frame_table[mfn].list.next;
+        va += sizeof(mfn);
+    }
+
+    unmap_domain_page(top_tab);
+
     return 1;
 }
 
diff -r bee659de2a36 -r a543a4778a7d xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Thu Feb 16 15:35:09 2006
+++ b/xen/include/asm-x86/shadow.h      Thu Feb 16 15:46:21 2006
@@ -115,9 +115,7 @@
 #define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) 
- (_max)) << 16) | (_min))
 #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1))
 #define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) 
>> 16))
-#if CONFIG_PAGING_LEVELS == 2
 extern void shadow_direct_map_clean(struct vcpu *v);
-#endif
 extern int shadow_direct_map_init(struct vcpu *v);
 extern int shadow_direct_map_fault(
     unsigned long vpa, struct cpu_user_regs *regs);
@@ -556,6 +554,38 @@
         update_hl2e(v, va);
 
     __mark_dirty(d, pagetable_get_pfn(v->arch.guest_table));
+}
+
+static inline void
+__direct_get_l2e(
+    struct vcpu *v, unsigned long va, l2_pgentry_t *psl2e)
+{
+    l2_pgentry_t *phys_vtable;
+
+    ASSERT(shadow_mode_enabled(v->domain));
+
+    phys_vtable = map_domain_page(
+        pagetable_get_pfn(v->domain->arch.phys_table));
+
+    *psl2e = phys_vtable[l2_table_offset(va)];
+
+    unmap_domain_page(phys_vtable);
+}
+
+static inline void
+__direct_set_l2e(
+    struct vcpu *v, unsigned long va, l2_pgentry_t value)
+{
+    l2_pgentry_t *phys_vtable;
+
+    ASSERT(shadow_mode_enabled(v->domain));
+
+    phys_vtable = map_domain_page(
+        pagetable_get_pfn(v->domain->arch.phys_table));
+
+    phys_vtable[l2_table_offset(va)] = value;
+
+    unmap_domain_page(phys_vtable);
 }
 
 static inline void
diff -r bee659de2a36 -r a543a4778a7d xen/include/asm-x86/shadow_64.h
--- a/xen/include/asm-x86/shadow_64.h   Thu Feb 16 15:35:09 2006
+++ b/xen/include/asm-x86/shadow_64.h   Thu Feb 16 15:46:21 2006
@@ -66,9 +66,12 @@
 #define PAGING_L1      1UL
 #define L_MASK  0xff
 
+#define PAE_PAGING_LEVELS   3
+
 #define ROOT_LEVEL_64   PAGING_L4
 #define ROOT_LEVEL_32   PAGING_L2
 
+#define DIRECT_ENTRY    (4UL << 16)
 #define SHADOW_ENTRY    (2UL << 16)
 #define GUEST_ENTRY     (1UL << 16)
 
@@ -94,6 +97,7 @@
 #define entry_empty()           ((pgentry_64_t) { 0 })
 #define entry_from_pfn(pfn, flags)  \
     ((pgentry_64_t) { ((intpte_t)(pfn) << PAGE_SHIFT) | put_pte_flags(flags) })
+#define entry_from_page(page, flags) 
(entry_from_pfn(page_to_mfn(page),(flags)))
 #define entry_add_flags(x, flags)    ((x).lo |= put_pte_flags(flags))
 #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags))
 #define entry_has_changed(x,y,flags) \
@@ -162,16 +166,24 @@
 
     if ( flag & SHADOW_ENTRY )
     {
-       root_level =  ROOT_LEVEL_64;
-       index = table_offset_64(va, root_level);
+        root_level =  ROOT_LEVEL_64;
+        index = table_offset_64(va, root_level);
         le_e = (pgentry_64_t *)&v->arch.shadow_vtable[index];
     }
-    else /* guest entry */  
+    else if ( flag & GUEST_ENTRY )
     {
         root_level = v->domain->arch.ops->guest_paging_levels;
-       index = table_offset_64(va, root_level);
+        index = table_offset_64(va, root_level);
         le_e = (pgentry_64_t *)&v->arch.guest_vtable[index];
     }
+    else /* direct mode */
+    {
+        root_level = PAE_PAGING_LEVELS;
+        index = table_offset_64(va, root_level);
+        le_e = (pgentry_64_t *)map_domain_page(
+            pagetable_get_pfn(v->domain->arch.phys_table));
+    }
+
     /*
      * If it's not external mode, then mfn should be machine physical.
      */
@@ -241,6 +253,20 @@
 #define __guest_get_l3e(v, va, sl3e) \
   __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3)
 
+#define __direct_set_l3e(v, va, value) \
+  __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L3)
+#define __direct_get_l3e(v, va, sl3e) \
+  __rw_entry(v, va, sl3e, DIRECT_ENTRY | GET_ENTRY | PAGING_L3)
+#define __direct_set_l2e(v, va, value) \
+  __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L2)
+#define __direct_get_l2e(v, va, sl2e) \
+  __rw_entry(v, va, sl2e, DIRECT_ENTRY | GET_ENTRY | PAGING_L2)
+#define __direct_set_l1e(v, va, value) \
+  __rw_entry(v, va, value, DIRECT_ENTRY | SET_ENTRY | PAGING_L1)
+#define __direct_get_l1e(v, va, sl1e) \
+  __rw_entry(v, va, sl1e, DIRECT_ENTRY | GET_ENTRY | PAGING_L1)
+
+
 static inline int  __guest_set_l2e(
     struct vcpu *v, unsigned long va, void *value, int size)
 {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.