WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Memory paging support for HVM guest emula

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Memory paging support for HVM guest emulation.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 16 Dec 2009 22:40:31 -0800
Delivery-date: Wed, 16 Dec 2009 22:42:09 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1261031275 0
# Node ID 410eb65969cb142b8b32490d7f1454859cc3a7f2
# Parent  1165acfea711ef33798d12fb5078e3b31faa3e44
Memory paging support for HVM guest emulation.

A new HVMCOPY return value, HVMCOPY_gfn_paged_out is defined to indicate that
a gfn was paged out. This value and PFEC_page_paged, as appropriate, are
caught and passed up as X86EMUL_RETRY to the emulator. This will cause the
emulator to keep retrying the operation until is succeeds (once the page has
been paged in).

Signed-off-by: Patrick Colp <Patrick.Colp@xxxxxxxxxx>
---
 xen/arch/x86/hvm/emulate.c        |   21 +++++++++++++++++
 xen/arch/x86/hvm/hvm.c            |   22 ++++++++++++++++++
 xen/arch/x86/hvm/intercept.c      |   45 +++++++++++++++++++++-----------------
 xen/arch/x86/hvm/io.c             |   42 ++++++++++++++++++++++-------------
 xen/include/asm-x86/hvm/support.h |    3 +-
 5 files changed, 97 insertions(+), 36 deletions(-)

diff -r 1165acfea711 -r 410eb65969cb xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c        Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/arch/x86/hvm/emulate.c        Thu Dec 17 06:27:55 2009 +0000
@@ -56,7 +56,18 @@ static int hvmemul_do_io(
     int value_is_ptr = (p_data == NULL);
     struct vcpu *curr = current;
     ioreq_t *p = get_ioreq(curr);
+    unsigned long ram_gfn = paddr_to_pfn(ram_gpa);
+    p2m_type_t p2mt;
+    mfn_t ram_mfn;
     int rc;
+
+    /* Check for paged out page */
+    ram_mfn = gfn_to_mfn(current->domain, ram_gfn, &p2mt);
+    if ( p2m_is_paging(p2mt) )
+    {
+        p2m_mem_paging_populate(curr->domain, ram_gfn);
+        return X86EMUL_RETRY;
+    }
 
     /*
      * Weird-sized accesses have undefined behaviour: we discard writes
@@ -271,6 +282,8 @@ static int hvmemul_linear_to_phys(
     }
     else if ( (pfn = paging_gva_to_gfn(curr, addr, &pfec)) == INVALID_GFN )
     {
+        if ( pfec == PFEC_page_paged )
+            return X86EMUL_RETRY;
         hvm_inject_exception(TRAP_page_fault, pfec, addr);
         return X86EMUL_EXCEPTION;
     }
@@ -286,6 +299,8 @@ static int hvmemul_linear_to_phys(
         /* Is it contiguous with the preceding PFNs? If not then we're done. */
         if ( (npfn == INVALID_GFN) || (npfn != (pfn + (reverse ? -i : i))) )
         {
+            if ( pfec == PFEC_page_paged )
+                return X86EMUL_RETRY;
             done /= bytes_per_rep;
             if ( done == 0 )
             {
@@ -424,6 +439,8 @@ static int __hvmemul_read(
         if ( rc != X86EMUL_OKAY )
             return rc;
         return hvmemul_do_mmio(gpa, &reps, bytes, 0, IOREQ_READ, 0, p_data);
+    case HVMCOPY_gfn_paged_out:
+        return X86EMUL_RETRY;
     default:
         break;
     }
@@ -514,6 +531,8 @@ static int hvmemul_write(
             return rc;
         return hvmemul_do_mmio(gpa, &reps, bytes, 0,
                                IOREQ_WRITE, 0, p_data);
+    case HVMCOPY_gfn_paged_out:
+        return X86EMUL_RETRY;
     default:
         break;
     }
@@ -687,6 +706,8 @@ static int hvmemul_rep_movs(
 
     xfree(buf);
 
+    if ( rc == HVMCOPY_gfn_paged_out )
+        return X86EMUL_RETRY;
     if ( rc != HVMCOPY_okay )
     {
         gdprintk(XENLOG_WARNING, "Failed memory-to-memory REP MOVS: sgpa=%"
diff -r 1165acfea711 -r 410eb65969cb xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Thu Dec 17 06:27:55 2009 +0000
@@ -314,6 +314,11 @@ static int hvm_set_ioreq_page(
     mfn = mfn_x(gfn_to_mfn(d, gmfn, &p2mt));
     if ( !p2m_is_ram(p2mt) )
         return -EINVAL;
+    if ( p2m_is_paging(p2mt) )
+    {
+        p2m_mem_paging_populate(d, gmfn);
+        return -ENOENT;
+    }
     ASSERT(mfn_valid(mfn));
 
     page = mfn_to_page(mfn);
@@ -1318,6 +1323,8 @@ static void *hvm_map_entry(unsigned long
      * we still treat it as a kernel-mode read (i.e. no access checks). */
     pfec = PFEC_page_present;
     gfn = paging_gva_to_gfn(current, va, &pfec);
+    if ( pfec == PFEC_page_paged )
+        return NULL;
     mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
     if ( p2m_is_paging(p2mt) )
     {
@@ -1546,6 +1553,8 @@ void hvm_task_switch(
         &tss, prev_tr.base, sizeof(tss), PFEC_page_present);
     if ( rc == HVMCOPY_bad_gva_to_gfn )
         goto out;
+    if ( rc == HVMCOPY_gfn_paged_out )
+        goto out;
 
     eflags = regs->eflags;
     if ( taskswitch_reason == TSW_iret )
@@ -1582,10 +1591,14 @@ void hvm_task_switch(
         prev_tr.base, &tss, sizeof(tss), PFEC_page_present);
     if ( rc == HVMCOPY_bad_gva_to_gfn )
         goto out;
+    if ( rc == HVMCOPY_gfn_paged_out )
+        goto out;
 
     rc = hvm_copy_from_guest_virt(
         &tss, tr.base, sizeof(tss), PFEC_page_present);
     if ( rc == HVMCOPY_bad_gva_to_gfn )
+        goto out;
+    if ( rc == HVMCOPY_gfn_paged_out )
         goto out;
 
     if ( hvm_set_cr3(tss.cr3) )
@@ -1622,6 +1635,8 @@ void hvm_task_switch(
         tr.base, &tss, sizeof(tss), PFEC_page_present);
     if ( rc == HVMCOPY_bad_gva_to_gfn )
         exn_raised = 1;
+    if ( rc == HVMCOPY_gfn_paged_out )
+        goto out;
 
     if ( (tss.trace & 1) && !exn_raised )
         hvm_inject_exception(TRAP_debug, tss_sel & 0xfff8, 0);
@@ -1681,6 +1696,8 @@ static enum hvm_copy_result __hvm_copy(
             gfn = paging_gva_to_gfn(curr, addr, &pfec);
             if ( gfn == INVALID_GFN )
             {
+                if ( pfec == PFEC_page_paged )
+                    return HVMCOPY_gfn_paged_out;
                 if ( flags & HVMCOPY_fault )
                     hvm_inject_exception(TRAP_page_fault, pfec, addr);
                 return HVMCOPY_bad_gva_to_gfn;
@@ -1693,6 +1710,11 @@ static enum hvm_copy_result __hvm_copy(
 
         mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
 
+        if ( p2m_is_paging(p2mt) )
+        {
+            p2m_mem_paging_populate(curr->domain, gfn);
+            return HVMCOPY_gfn_paged_out;
+        }
         if ( p2m_is_grant(p2mt) )
             return HVMCOPY_unhandleable;
         if ( !p2m_is_ram(p2mt) )
diff -r 1165acfea711 -r 410eb65969cb xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/arch/x86/hvm/intercept.c      Thu Dec 17 06:27:55 2009 +0000
@@ -72,30 +72,31 @@ static int hvm_mmio_access(struct vcpu *
     {
         for ( i = 0; i < p->count; i++ )
         {
-            rc = read_handler(
-                v,
-                p->addr + (sign * i * p->size),
-                p->size, &data);
-            if ( rc != X86EMUL_OKAY )
-                break;
-            (void)hvm_copy_to_guest_phys(
-                p->data + (sign * i * p->size),
-                &data,
-                p->size);
+            rc = read_handler(v, p->addr + (sign * i * p->size), p->size,
+                              &data);
+            if ( rc != X86EMUL_OKAY )
+                break;
+            if ( hvm_copy_to_guest_phys(p->data + (sign * i * p->size), &data,
+                                        p->size) == HVMCOPY_gfn_paged_out )
+            {
+                rc = X86EMUL_RETRY;
+                break;
+            }
         }
     }
     else
     {
         for ( i = 0; i < p->count; i++ )
         {
-            (void)hvm_copy_from_guest_phys(
-                &data,
-                p->data + (sign * i * p->size),
-                p->size);
-            rc = write_handler(
-                v,
-                p->addr + (sign * i * p->size),
-                p->size, data);
+            if ( hvm_copy_from_guest_phys(&data,
+                                          p->data + (sign * i * p->size),
+                                          p->size) == HVMCOPY_gfn_paged_out )
+            {
+                rc = X86EMUL_RETRY;
+                break;
+            }
+            rc = write_handler(v, p->addr + (sign * i * p->size), p->size,
+                               data);
             if ( rc != X86EMUL_OKAY )
                 break;
         }
@@ -190,8 +191,12 @@ int hvm_io_intercept(ioreq_t *p, int typ
     int i;
     unsigned long addr, size;
 
-    if ( (type == HVM_PORTIO) && (dpci_ioport_intercept(p)) )
-        return X86EMUL_OKAY;
+    if ( type == HVM_PORTIO )
+    {
+        int rc = dpci_ioport_intercept(p);
+        if ( (rc == X86EMUL_OKAY) || (rc == X86EMUL_RETRY) )
+            return rc;
+    }
 
     for ( i = 0; i < handler->num_slot; i++ )
     {
diff -r 1165acfea711 -r 410eb65969cb xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/arch/x86/hvm/io.c     Thu Dec 17 06:27:55 2009 +0000
@@ -239,7 +239,7 @@ void hvm_io_assist(void)
         vcpu_end_shutdown_deferral(curr);
 }
 
-static void dpci_ioport_read(uint32_t mport, ioreq_t *p)
+static int dpci_ioport_read(uint32_t mport, ioreq_t *p)
 {
     int i, sign = p->df ? -1 : 1;
     uint32_t data = 0;
@@ -262,14 +262,19 @@ static void dpci_ioport_read(uint32_t mp
         }
 
         if ( p->data_is_ptr )
-            (void)hvm_copy_to_guest_phys(
-                p->data + (sign * i * p->size), &data, p->size);
+        {
+            if ( hvm_copy_to_guest_phys(p->data + (sign * i * p->size), &data,
+                                        p->size) ==  HVMCOPY_gfn_paged_out )
+                return X86EMUL_RETRY;
+        }
         else
             p->data = data;
     }
-}
-
-static void dpci_ioport_write(uint32_t mport, ioreq_t *p)
+    
+    return X86EMUL_OKAY;
+}
+
+static int dpci_ioport_write(uint32_t mport, ioreq_t *p)
 {
     int i, sign = p->df ? -1 : 1;
     uint32_t data;
@@ -278,8 +283,11 @@ static void dpci_ioport_write(uint32_t m
     {
         data = p->data;
         if ( p->data_is_ptr )
-            (void)hvm_copy_from_guest_phys(
-                &data, p->data + (sign * i * p->size), p->size);
+        {
+            if ( hvm_copy_from_guest_phys(&data, p->data + (sign * i * 
p->size),
+                                          p->size) ==  HVMCOPY_gfn_paged_out )
+                return X86EMUL_RETRY;
+        }
 
         switch ( p->size )
         {
@@ -296,6 +304,8 @@ static void dpci_ioport_write(uint32_t m
             BUG();
         }
     }
+
+    return X86EMUL_OKAY;
 }
 
 int dpci_ioport_intercept(ioreq_t *p)
@@ -305,6 +315,7 @@ int dpci_ioport_intercept(ioreq_t *p)
     struct g2m_ioport *g2m_ioport;
     unsigned int mport, gport = p->addr;
     unsigned int s = 0, e = 0;
+    int rc;
 
     list_for_each_entry( g2m_ioport, &hd->g2m_ioport_list, list )
     {
@@ -314,7 +325,7 @@ int dpci_ioport_intercept(ioreq_t *p)
             goto found;
     }
 
-    return 0;
+    return X86EMUL_UNHANDLEABLE;
 
  found:
     mport = (gport - s) + g2m_ioport->mport;
@@ -323,22 +334,23 @@ int dpci_ioport_intercept(ioreq_t *p)
     {
         gdprintk(XENLOG_ERR, "Error: access to gport=0x%x denied!\n",
                  (uint32_t)p->addr);
-        return 0;
+        return X86EMUL_UNHANDLEABLE;
     }
 
     switch ( p->dir )
     {
     case IOREQ_READ:
-        dpci_ioport_read(mport, p);
+        rc = dpci_ioport_read(mport, p);
         break;
     case IOREQ_WRITE:
-        dpci_ioport_write(mport, p);
+        rc = dpci_ioport_write(mport, p);
         break;
     default:
         gdprintk(XENLOG_ERR, "Error: couldn't handle p->dir = %d", p->dir);
-    }
-
-    return 1;
+        rc = X86EMUL_UNHANDLEABLE;
+    }
+
+    return rc;
 }
 
 /*
diff -r 1165acfea711 -r 410eb65969cb xen/include/asm-x86/hvm/support.h
--- a/xen/include/asm-x86/hvm/support.h Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/include/asm-x86/hvm/support.h Thu Dec 17 06:27:55 2009 +0000
@@ -72,7 +72,8 @@ enum hvm_copy_result {
     HVMCOPY_okay = 0,
     HVMCOPY_bad_gva_to_gfn,
     HVMCOPY_bad_gfn_to_mfn,
-    HVMCOPY_unhandleable
+    HVMCOPY_unhandleable,
+    HVMCOPY_gfn_paged_out,
 };
 
 /*

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Memory paging support for HVM guest emulation., Xen patchbot-unstable <=