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

[Xen-devel] [PATCH 04 of 11] x86/hvm: Use get_page_from_gfn() instead of get_gfn()/put_gfn



# HG changeset patch
# User Tim Deegan <tim@xxxxxxx>
# Date 1336661656 -3600
# Node ID 9da426cdc7e478e426bcbd5391b8deacdc85db1e
# Parent  d774bb5c6326d1a7e88a3bfadc546d154a2ad895
x86/hvm: Use get_page_from_gfn() instead of get_gfn()/put_gfn.

Signed-off-by: Tim Deegan <tim@xxxxxxx>
Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>

diff -r d774bb5c6326 -r 9da426cdc7e4 xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c        Thu May 10 15:54:16 2012 +0100
+++ b/xen/arch/x86/hvm/emulate.c        Thu May 10 15:54:16 2012 +0100
@@ -60,34 +60,25 @@ static int hvmemul_do_io(
     ioreq_t *p = get_ioreq(curr);
     unsigned long ram_gfn = paddr_to_pfn(ram_gpa);
     p2m_type_t p2mt;
-    mfn_t ram_mfn;
+    struct page_info *ram_page;
     int rc;
 
     /* Check for paged out page */
-    ram_mfn = get_gfn_unshare(curr->domain, ram_gfn, &p2mt);
+    ram_page = get_page_from_gfn(curr->domain, ram_gfn, &p2mt, P2M_UNSHARE);
     if ( p2m_is_paging(p2mt) )
     {
-        put_gfn(curr->domain, ram_gfn); 
+        if ( ram_page )
+            put_page(ram_page);
         p2m_mem_paging_populate(curr->domain, ram_gfn);
         return X86EMUL_RETRY;
     }
     if ( p2m_is_shared(p2mt) )
     {
-        put_gfn(curr->domain, ram_gfn); 
+        if ( ram_page )
+            put_page(ram_page);
         return X86EMUL_RETRY;
     }
 
-    /* Maintain a ref on the mfn to ensure liveness. Put the gfn
-     * to avoid potential deadlock wrt event channel lock, later. */
-    if ( mfn_valid(mfn_x(ram_mfn)) )
-        if ( !get_page(mfn_to_page(mfn_x(ram_mfn)),
-             curr->domain) )
-        {
-            put_gfn(curr->domain, ram_gfn);
-            return X86EMUL_RETRY;
-        }
-    put_gfn(curr->domain, ram_gfn);
-
     /*
      * Weird-sized accesses have undefined behaviour: we discard writes
      * and read all-ones.
@@ -98,8 +89,8 @@ static int hvmemul_do_io(
         ASSERT(p_data != NULL); /* cannot happen with a REP prefix */
         if ( dir == IOREQ_READ )
             memset(p_data, ~0, size);
-        if ( mfn_valid(mfn_x(ram_mfn)) )
-            put_page(mfn_to_page(mfn_x(ram_mfn)));
+        if ( ram_page )
+            put_page(ram_page);
         return X86EMUL_UNHANDLEABLE;
     }
 
@@ -120,8 +111,8 @@ static int hvmemul_do_io(
             unsigned int bytes = vio->mmio_large_write_bytes;
             if ( (addr >= pa) && ((addr + size) <= (pa + bytes)) )
             {
-                if ( mfn_valid(mfn_x(ram_mfn)) )
-                    put_page(mfn_to_page(mfn_x(ram_mfn)));
+                if ( ram_page )
+                    put_page(ram_page);
                 return X86EMUL_OKAY;
             }
         }
@@ -133,8 +124,8 @@ static int hvmemul_do_io(
             {
                 memcpy(p_data, &vio->mmio_large_read[addr - pa],
                        size);
-                if ( mfn_valid(mfn_x(ram_mfn)) )
-                    put_page(mfn_to_page(mfn_x(ram_mfn)));
+                if ( ram_page )
+                    put_page(ram_page);
                 return X86EMUL_OKAY;
             }
         }
@@ -148,8 +139,8 @@ static int hvmemul_do_io(
         vio->io_state = HVMIO_none;
         if ( p_data == NULL )
         {
-            if ( mfn_valid(mfn_x(ram_mfn)) )
-                put_page(mfn_to_page(mfn_x(ram_mfn)));
+            if ( ram_page )
+                put_page(ram_page);
             return X86EMUL_UNHANDLEABLE;
         }
         goto finish_access;
@@ -159,13 +150,13 @@ static int hvmemul_do_io(
              (addr == (vio->mmio_large_write_pa +
                        vio->mmio_large_write_bytes)) )
         {
-            if ( mfn_valid(mfn_x(ram_mfn)) )
-                put_page(mfn_to_page(mfn_x(ram_mfn)));
+            if ( ram_page )
+                put_page(ram_page);
             return X86EMUL_RETRY;
         }
     default:
-        if ( mfn_valid(mfn_x(ram_mfn)) )
-            put_page(mfn_to_page(mfn_x(ram_mfn)));
+        if ( ram_page )
+            put_page(ram_page);
         return X86EMUL_UNHANDLEABLE;
     }
 
@@ -173,8 +164,8 @@ static int hvmemul_do_io(
     {
         gdprintk(XENLOG_WARNING, "WARNING: io already pending (%d)?\n",
                  p->state);
-        if ( mfn_valid(mfn_x(ram_mfn)) )
-            put_page(mfn_to_page(mfn_x(ram_mfn)));
+        if ( ram_page )
+            put_page(ram_page);
         return X86EMUL_UNHANDLEABLE;
     }
 
@@ -226,8 +217,8 @@ static int hvmemul_do_io(
 
     if ( rc != X86EMUL_OKAY )
     {
-        if ( mfn_valid(mfn_x(ram_mfn)) )
-            put_page(mfn_to_page(mfn_x(ram_mfn)));
+        if ( ram_page )
+            put_page(ram_page);
         return rc;
     }
 
@@ -263,8 +254,8 @@ static int hvmemul_do_io(
         }
     }
 
-    if ( mfn_valid(mfn_x(ram_mfn)) )
-        put_page(mfn_to_page(mfn_x(ram_mfn)));
+    if ( ram_page )
+        put_page(ram_page);
     return X86EMUL_OKAY;
 }
 
diff -r d774bb5c6326 -r 9da426cdc7e4 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu May 10 15:54:16 2012 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Thu May 10 15:54:16 2012 +0100
@@ -395,48 +395,41 @@ int prepare_ring_for_helper(
 {
     struct page_info *page;
     p2m_type_t p2mt;
-    unsigned long mfn;
     void *va;
 
-    mfn = mfn_x(get_gfn_unshare(d, gmfn, &p2mt));
-    if ( !p2m_is_ram(p2mt) )
-    {
-        put_gfn(d, gmfn);
-        return -EINVAL;
-    }
+    page = get_page_from_gfn(d, gmfn, &p2mt, P2M_UNSHARE);
     if ( p2m_is_paging(p2mt) )
     {
-        put_gfn(d, gmfn);
+        if ( page )
+            put_page(page);
         p2m_mem_paging_populate(d, gmfn);
         return -ENOENT;
     }
     if ( p2m_is_shared(p2mt) )
     {
-        put_gfn(d, gmfn);
+        if ( page )
+            put_page(page);
         return -ENOENT;
     }
-    ASSERT(mfn_valid(mfn));
-
-    page = mfn_to_page(mfn);
-    if ( !get_page_and_type(page, d, PGT_writable_page) )
+    if ( !page )
+        return -EINVAL;
+
+    if ( !get_page_type(page, PGT_writable_page) )
     {
-        put_gfn(d, gmfn);
+        put_page(page);
         return -EINVAL;
     }
 
-    va = map_domain_page_global(mfn);
+    va = __map_domain_page_global(page);
     if ( va == NULL )
     {
         put_page_and_type(page);
-        put_gfn(d, gmfn);
         return -ENOMEM;
     }
 
     *_va = va;
     *_page = page;
 
-    put_gfn(d, gmfn);
-
     return 0;
 }
 
@@ -1607,8 +1600,8 @@ int hvm_mov_from_cr(unsigned int cr, uns
 int hvm_set_cr0(unsigned long value)
 {
     struct vcpu *v = current;
-    p2m_type_t p2mt;
-    unsigned long gfn, mfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
+    unsigned long gfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
+    struct page_info *page;
 
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
 
@@ -1647,23 +1640,20 @@ int hvm_set_cr0(unsigned long value)
         {
             /* The guest CR3 must be pointing to the guest physical. */
             gfn = v->arch.hvm_vcpu.guest_cr[3]>>PAGE_SHIFT;
-            mfn = mfn_x(get_gfn(v->domain, gfn, &p2mt));
-            if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
-                 !get_page(mfn_to_page(mfn), v->domain))
+            page = get_page_from_gfn(v->domain, gfn, NULL, P2M_ALLOC);
+            if ( !page )
             {
-                put_gfn(v->domain, gfn);
-                gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n",
-                         v->arch.hvm_vcpu.guest_cr[3], mfn);
+                gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx\n",
+                         v->arch.hvm_vcpu.guest_cr[3]);
                 domain_crash(v->domain);
                 return X86EMUL_UNHANDLEABLE;
             }
 
             /* Now arch.guest_table points to machine physical. */
-            v->arch.guest_table = pagetable_from_pfn(mfn);
+            v->arch.guest_table = pagetable_from_page(page);
 
             HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
-                        v->arch.hvm_vcpu.guest_cr[3], mfn);
-            put_gfn(v->domain, gfn);
+                        v->arch.hvm_vcpu.guest_cr[3], page_to_mfn(page));
         }
     }
     else if ( !(value & X86_CR0_PG) && (old_value & X86_CR0_PG) )
@@ -1738,26 +1728,21 @@ int hvm_set_cr0(unsigned long value)
 
 int hvm_set_cr3(unsigned long value)
 {
-    unsigned long mfn;
-    p2m_type_t p2mt;
     struct vcpu *v = current;
+    struct page_info *page;
 
     if ( hvm_paging_enabled(v) && !paging_mode_hap(v->domain) &&
          (value != v->arch.hvm_vcpu.guest_cr[3]) )
     {
         /* Shadow-mode CR3 change. Check PDBR and update refcounts. */
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
-        mfn = mfn_x(get_gfn(v->domain, value >> PAGE_SHIFT, &p2mt));
-        if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
-             !get_page(mfn_to_page(mfn), v->domain) )
-        {
-              put_gfn(v->domain, value >> PAGE_SHIFT);
-              goto bad_cr3;
-        }
+        page = get_page_from_gfn(v->domain, value >> PAGE_SHIFT,
+                                 NULL, P2M_ALLOC);
+        if ( !page )
+            goto bad_cr3;
 
         put_page(pagetable_get_page(v->arch.guest_table));
-        v->arch.guest_table = pagetable_from_pfn(mfn);
-        put_gfn(v->domain, value >> PAGE_SHIFT);
+        v->arch.guest_table = pagetable_from_page(page);
 
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
     }
@@ -1914,46 +1899,29 @@ int hvm_virtual_to_linear_addr(
 static void *__hvm_map_guest_frame(unsigned long gfn, bool_t writable)
 {
     void *map;
-    unsigned long mfn;
     p2m_type_t p2mt;
-    struct page_info *pg;
+    struct page_info *page;
     struct domain *d = current->domain;
-    int rc;
-
-    mfn = mfn_x(writable
-                ? get_gfn_unshare(d, gfn, &p2mt)
-                : get_gfn(d, gfn, &p2mt));
-    if ( (p2m_is_shared(p2mt) && writable) || !p2m_is_ram(p2mt) )
+
+    page = get_page_from_gfn(d, gfn, &p2mt,
+                             writable ? P2M_UNSHARE : P2M_ALLOC);
+    if ( (p2m_is_shared(p2mt) && writable) || !page )
     {
-        put_gfn(d, gfn);
+        if ( page )
+            put_page(page);
         return NULL;
     }
     if ( p2m_is_paging(p2mt) )
     {
-        put_gfn(d, gfn);
+        put_page(page);
         p2m_mem_paging_populate(d, gfn);
         return NULL;
     }
 
-    ASSERT(mfn_valid(mfn));
-
     if ( writable )
-        paging_mark_dirty(d, mfn);
-
-    /* Get a ref on the page, considering that it could be shared */
-    pg = mfn_to_page(mfn);
-    rc = get_page(pg, d);
-    if ( !rc && !writable )
-        /* Page could be shared */
-        rc = get_page(pg, dom_cow);
-    if ( !rc )
-    {
-        put_gfn(d, gfn);
-        return NULL;
-    }
-
-    map = map_domain_page(mfn);
-    put_gfn(d, gfn);
+        paging_mark_dirty(d, page_to_mfn(page));
+
+    map = __map_domain_page(page);
     return map;
 }
 
@@ -2358,7 +2326,8 @@ static enum hvm_copy_result __hvm_copy(
     void *buf, paddr_t addr, int size, unsigned int flags, uint32_t pfec)
 {
     struct vcpu *curr = current;
-    unsigned long gfn, mfn;
+    unsigned long gfn;
+    struct page_info *page;
     p2m_type_t p2mt;
     char *p;
     int count, todo = size;
@@ -2402,32 +2371,33 @@ static enum hvm_copy_result __hvm_copy(
             gfn = addr >> PAGE_SHIFT;
         }
 
-        mfn = mfn_x(get_gfn_unshare(curr->domain, gfn, &p2mt));
+        page = get_page_from_gfn(curr->domain, gfn, &p2mt, P2M_UNSHARE);
 
         if ( p2m_is_paging(p2mt) )
         {
-            put_gfn(curr->domain, gfn);
+            if ( page )
+                put_page(page);
             p2m_mem_paging_populate(curr->domain, gfn);
             return HVMCOPY_gfn_paged_out;
         }
         if ( p2m_is_shared(p2mt) )
         {
-            put_gfn(curr->domain, gfn);
+            if ( page )
+                put_page(page);
             return HVMCOPY_gfn_shared;
         }
         if ( p2m_is_grant(p2mt) )
         {
-            put_gfn(curr->domain, gfn);
+            if ( page )
+                put_page(page);
             return HVMCOPY_unhandleable;
         }
-        if ( !p2m_is_ram(p2mt) )
+        if ( !page )
         {
-            put_gfn(curr->domain, gfn);
             return HVMCOPY_bad_gfn_to_mfn;
         }
-        ASSERT(mfn_valid(mfn));
-
-        p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK);
+
+        p = (char *)__map_domain_page(page) + (addr & ~PAGE_MASK);
 
         if ( flags & HVMCOPY_to_guest )
         {
@@ -2437,12 +2407,12 @@ static enum hvm_copy_result __hvm_copy(
                 if ( xchg(&lastpage, gfn) != gfn )
                     gdprintk(XENLOG_DEBUG, "guest attempted write to read-only"
                              " memory page. gfn=%#lx, mfn=%#lx\n",
-                             gfn, mfn);
+                             gfn, page_to_mfn(page));
             }
             else
             {
                 memcpy(p, buf, count);
-                paging_mark_dirty(curr->domain, mfn);
+                paging_mark_dirty(curr->domain, page_to_mfn(page));
             }
         }
         else
@@ -2455,7 +2425,7 @@ static enum hvm_copy_result __hvm_copy(
         addr += count;
         buf  += count;
         todo -= count;
-        put_gfn(curr->domain, gfn);
+        put_page(page);
     }
 
     return HVMCOPY_okay;
@@ -2464,7 +2434,8 @@ static enum hvm_copy_result __hvm_copy(
 static enum hvm_copy_result __hvm_clear(paddr_t addr, int size)
 {
     struct vcpu *curr = current;
-    unsigned long gfn, mfn;
+    unsigned long gfn;
+    struct page_info *page;
     p2m_type_t p2mt;
     char *p;
     int count, todo = size;
@@ -2500,32 +2471,35 @@ static enum hvm_copy_result __hvm_clear(
             return HVMCOPY_bad_gva_to_gfn;
         }
 
-        mfn = mfn_x(get_gfn_unshare(curr->domain, gfn, &p2mt));
+        page = get_page_from_gfn(curr->domain, gfn, &p2mt, P2M_UNSHARE);
 
         if ( p2m_is_paging(p2mt) )
         {
+            if ( page )
+                put_page(page);
             p2m_mem_paging_populate(curr->domain, gfn);
-            put_gfn(curr->domain, gfn);
             return HVMCOPY_gfn_paged_out;
         }
         if ( p2m_is_shared(p2mt) )
         {
-            put_gfn(curr->domain, gfn);
+            if ( page )
+                put_page(page);
             return HVMCOPY_gfn_shared;
         }
         if ( p2m_is_grant(p2mt) )
         {
-            put_gfn(curr->domain, gfn);
+            if ( page )
+                put_page(page);
             return HVMCOPY_unhandleable;
         }
-        if ( !p2m_is_ram(p2mt) )
+        if ( !page )
         {
-            put_gfn(curr->domain, gfn);
+            if ( page )
+                put_page(page);
             return HVMCOPY_bad_gfn_to_mfn;
         }
-        ASSERT(mfn_valid(mfn));
-
-        p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK);
+
+        p = (char *)__map_domain_page(page) + (addr & ~PAGE_MASK);
 
         if ( p2mt == p2m_ram_ro )
         {
@@ -2533,19 +2507,19 @@ static enum hvm_copy_result __hvm_clear(
             if ( xchg(&lastpage, gfn) != gfn )
                 gdprintk(XENLOG_DEBUG, "guest attempted write to read-only"
                         " memory page. gfn=%#lx, mfn=%#lx\n",
-                        gfn, mfn);
+                         gfn, page_to_mfn(page));
         }
         else
         {
             memset(p, 0x00, count);
-            paging_mark_dirty(curr->domain, mfn);
+            paging_mark_dirty(curr->domain, page_to_mfn(page));
         }
 
         unmap_domain_page(p);
 
         addr += count;
         todo -= count;
-        put_gfn(curr->domain, gfn);
+        put_page(page);
     }
 
     return HVMCOPY_okay;
@@ -4000,35 +3974,16 @@ long do_hvm_op(unsigned long op, XEN_GUE
 
         for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
         {
-            p2m_type_t t;
-            mfn_t mfn = get_gfn_unshare(d, pfn, &t);
-            if ( p2m_is_paging(t) )
+            struct page_info *page;
+            page = get_page_from_gfn(d, pfn, NULL, P2M_UNSHARE);
+            if ( page )
             {
-                put_gfn(d, pfn);
-                p2m_mem_paging_populate(d, pfn);
-                rc = -EINVAL;
-                goto param_fail3;
-            }
-            if( p2m_is_shared(t) )
-            {
-                /* If it insists on not unsharing itself, crash the domain 
-                 * rather than crashing the host down in mark dirty */
-                gdprintk(XENLOG_WARNING,
-                         "shared pfn 0x%lx modified?\n", pfn);
-                domain_crash(d);
-                put_gfn(d, pfn);
-                rc = -EINVAL;
-                goto param_fail3;
-            }
-            
-            if ( mfn_x(mfn) != INVALID_MFN )
-            {
-                paging_mark_dirty(d, mfn_x(mfn));
+                paging_mark_dirty(d, page_to_mfn(page));
                 /* These are most probably not page tables any more */
                 /* don't take a long time and don't die either */
-                sh_remove_shadows(d->vcpu[0], mfn, 1, 0);
+                sh_remove_shadows(d->vcpu[0], _mfn(page_to_mfn(page)), 1, 0);
+                put_page(page);
             }
-            put_gfn(d, pfn);
         }
 
     param_fail3:
diff -r d774bb5c6326 -r 9da426cdc7e4 xen/arch/x86/hvm/stdvga.c
--- a/xen/arch/x86/hvm/stdvga.c Thu May 10 15:54:16 2012 +0100
+++ b/xen/arch/x86/hvm/stdvga.c Thu May 10 15:54:16 2012 +0100
@@ -482,7 +482,8 @@ static int mmio_move(struct hvm_hw_stdvg
                 if ( hvm_copy_to_guest_phys(data, &tmp, p->size) !=
                      HVMCOPY_okay )
                 {
-                    (void)get_gfn(d, data >> PAGE_SHIFT, &p2mt);
+                    struct page_info *dp = get_page_from_gfn(
+                            d, data >> PAGE_SHIFT, &p2mt, P2M_ALLOC);
                     /*
                      * The only case we handle is vga_mem <-> vga_mem.
                      * Anything else disables caching and leaves it to qemu-dm.
@@ -490,11 +491,12 @@ static int mmio_move(struct hvm_hw_stdvg
                     if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) ||
                          ((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) )
                     {
-                        put_gfn(d, data >> PAGE_SHIFT);
+                        if ( dp )
+                            put_page(dp);
                         return 0;
                     }
+                    ASSERT(!dp);
                     stdvga_mem_write(data, tmp, p->size);
-                    put_gfn(d, data >> PAGE_SHIFT);
                 }
                 data += sign * p->size;
                 addr += sign * p->size;
@@ -508,15 +510,16 @@ static int mmio_move(struct hvm_hw_stdvg
                 if ( hvm_copy_from_guest_phys(&tmp, data, p->size) !=
                      HVMCOPY_okay )
                 {
-                    (void)get_gfn(d, data >> PAGE_SHIFT, &p2mt);
+                    struct page_info *dp = get_page_from_gfn(
+                        d, data >> PAGE_SHIFT, &p2mt, P2M_ALLOC);
                     if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) ||
                          ((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) )
                     {
-                        put_gfn(d, data >> PAGE_SHIFT);
+                        if ( dp )
+                            put_page(dp);
                         return 0;
                     }
                     tmp = stdvga_mem_read(data, p->size);
-                    put_gfn(d, data >> PAGE_SHIFT);
                 }
                 stdvga_mem_write(addr, tmp, p->size);
                 data += sign * p->size;
diff -r d774bb5c6326 -r 9da426cdc7e4 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Thu May 10 15:54:16 2012 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Thu May 10 15:54:16 2012 +0100
@@ -232,8 +232,7 @@ static int svm_vmcb_save(struct vcpu *v,
 
 static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
 {
-    unsigned long mfn = 0;
-    p2m_type_t p2mt;
+    struct page_info *page = NULL;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
 
@@ -250,10 +249,10 @@ static int svm_vmcb_restore(struct vcpu 
     {
         if ( c->cr0 & X86_CR0_PG )
         {
-            mfn = mfn_x(get_gfn(v->domain, c->cr3 >> PAGE_SHIFT, &p2mt));
-            if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
+            page = get_page_from_gfn(v->domain, c->cr3 >> PAGE_SHIFT,
+                                     NULL, P2M_ALLOC);
+            if ( !page )
             {
-                put_gfn(v->domain, c->cr3 >> PAGE_SHIFT);
                 gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",
                          c->cr3);
                 return -EINVAL;
@@ -263,9 +262,8 @@ static int svm_vmcb_restore(struct vcpu 
         if ( v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG )
             put_page(pagetable_get_page(v->arch.guest_table));
 
-        v->arch.guest_table = pagetable_from_pfn(mfn);
-        if ( c->cr0 & X86_CR0_PG )
-            put_gfn(v->domain, c->cr3 >> PAGE_SHIFT);
+        v->arch.guest_table =
+            page ? pagetable_from_page(page) : pagetable_null();
     }
 
     v->arch.hvm_vcpu.guest_cr[0] = c->cr0 | X86_CR0_ET;
diff -r d774bb5c6326 -r 9da426cdc7e4 xen/arch/x86/hvm/viridian.c
--- a/xen/arch/x86/hvm/viridian.c       Thu May 10 15:54:16 2012 +0100
+++ b/xen/arch/x86/hvm/viridian.c       Thu May 10 15:54:16 2012 +0100
@@ -134,18 +134,19 @@ void dump_apic_assist(struct vcpu *v)
 static void enable_hypercall_page(struct domain *d)
 {
     unsigned long gmfn = d->arch.hvm_domain.viridian.hypercall_gpa.fields.pfn;
-    unsigned long mfn = get_gfn_untyped(d, gmfn);
+    struct page_info *page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
     uint8_t *p;
 
-    if ( !mfn_valid(mfn) ||
-         !get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) )
+    if ( !page || !get_page_type(page, PGT_writable_page) )
     {
-        put_gfn(d, gmfn); 
-        gdprintk(XENLOG_WARNING, "Bad GMFN %lx (MFN %lx)\n", gmfn, mfn);
+        if ( page )
+            put_page(page);
+        gdprintk(XENLOG_WARNING, "Bad GMFN %lx (MFN %lx)\n", gmfn,
+                 page_to_mfn(page));
         return;
     }
 
-    p = map_domain_page(mfn);
+    p = __map_domain_page(page);
 
     /*
      * We set the bit 31 in %eax (reserved field in the Viridian hypercall
@@ -162,15 +163,14 @@ static void enable_hypercall_page(struct
 
     unmap_domain_page(p);
 
-    put_page_and_type(mfn_to_page(mfn));
-    put_gfn(d, gmfn); 
+    put_page_and_type(page);
 }
 
 void initialize_apic_assist(struct vcpu *v)
 {
     struct domain *d = v->domain;
     unsigned long gmfn = v->arch.hvm_vcpu.viridian.apic_assist.fields.pfn;
-    unsigned long mfn = get_gfn_untyped(d, gmfn);
+    struct page_info *page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
     uint8_t *p;
 
     /*
@@ -183,22 +183,22 @@ void initialize_apic_assist(struct vcpu 
      * details of how Windows uses the page.
      */
 
-    if ( !mfn_valid(mfn) ||
-         !get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) )
+    if ( !page || !get_page_type(page, PGT_writable_page) )
     {
-        put_gfn(d, gmfn); 
-        gdprintk(XENLOG_WARNING, "Bad GMFN %lx (MFN %lx)\n", gmfn, mfn);
+        if ( page )
+            put_page(page);
+        gdprintk(XENLOG_WARNING, "Bad GMFN %lx (MFN %lx)\n", gmfn,
+                 page_to_mfn(page));
         return;
     }
 
-    p = map_domain_page(mfn);
+    p = __map_domain_page(page);
 
     *(u32 *)p = 0;
 
     unmap_domain_page(p);
 
-    put_page_and_type(mfn_to_page(mfn));
-    put_gfn(d, gmfn); 
+    put_page_and_type(page);
 }
 
 int wrmsr_viridian_regs(uint32_t idx, uint64_t val)
diff -r d774bb5c6326 -r 9da426cdc7e4 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu May 10 15:54:16 2012 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu May 10 15:54:16 2012 +0100
@@ -480,17 +480,16 @@ static void vmx_vmcs_save(struct vcpu *v
 static int vmx_restore_cr0_cr3(
     struct vcpu *v, unsigned long cr0, unsigned long cr3)
 {
-    unsigned long mfn = 0;
-    p2m_type_t p2mt;
+    struct page_info *page = NULL;
 
     if ( paging_mode_shadow(v->domain) )
     {
         if ( cr0 & X86_CR0_PG )
         {
-            mfn = mfn_x(get_gfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
-            if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
+            page = get_page_from_gfn(v->domain, cr3 >> PAGE_SHIFT,
+                                     NULL, P2M_ALLOC);
+            if ( !page )
             {
-                put_gfn(v->domain, cr3 >> PAGE_SHIFT);
                 gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%lx\n", cr3);
                 return -EINVAL;
             }
@@ -499,9 +498,8 @@ static int vmx_restore_cr0_cr3(
         if ( hvm_paging_enabled(v) )
             put_page(pagetable_get_page(v->arch.guest_table));
 
-        v->arch.guest_table = pagetable_from_pfn(mfn);
-        if ( cr0 & X86_CR0_PG )
-            put_gfn(v->domain, cr3 >> PAGE_SHIFT);
+        v->arch.guest_table =
+            page ? pagetable_from_page(page) : pagetable_null();
     }
 
     v->arch.hvm_vcpu.guest_cr[0] = cr0 | X86_CR0_ET;
@@ -1035,8 +1033,9 @@ static void vmx_set_interrupt_shadow(str
 
 static void vmx_load_pdptrs(struct vcpu *v)
 {
-    unsigned long cr3 = v->arch.hvm_vcpu.guest_cr[3], mfn;
+    unsigned long cr3 = v->arch.hvm_vcpu.guest_cr[3];
     uint64_t *guest_pdptrs;
+    struct page_info *page;
     p2m_type_t p2mt;
     char *p;
 
@@ -1047,24 +1046,19 @@ static void vmx_load_pdptrs(struct vcpu 
     if ( (cr3 & 0x1fUL) && !hvm_pcid_enabled(v) )
         goto crash;
 
-    mfn = mfn_x(get_gfn_unshare(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
-    if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) || 
-         /* If we didn't succeed in unsharing, get_page will fail
-          * (page still belongs to dom_cow) */
-         !get_page(mfn_to_page(mfn), v->domain) )
+    page = get_page_from_gfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt, P2M_UNSHARE);
+    if ( !page )
     {
         /* Ideally you don't want to crash but rather go into a wait 
          * queue, but this is the wrong place. We're holding at least
          * the paging lock */
         gdprintk(XENLOG_ERR,
-                 "Bad cr3 on load pdptrs gfn %lx mfn %lx type %d\n",
-                 cr3 >> PAGE_SHIFT, mfn, (int) p2mt);
-        put_gfn(v->domain, cr3 >> PAGE_SHIFT);
+                 "Bad cr3 on load pdptrs gfn %lx type %d\n",
+                 cr3 >> PAGE_SHIFT, (int) p2mt);
         goto crash;
     }
-    put_gfn(v->domain, cr3 >> PAGE_SHIFT);
-
-    p = map_domain_page(mfn);
+
+    p = __map_domain_page(page);
 
     guest_pdptrs = (uint64_t *)(p + (cr3 & ~PAGE_MASK));
 
@@ -1090,7 +1084,7 @@ static void vmx_load_pdptrs(struct vcpu 
     vmx_vmcs_exit(v);
 
     unmap_domain_page(p);
-    put_page(mfn_to_page(mfn));
+    put_page(page);
     return;
 
  crash:

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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