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-devel

[Xen-devel] [PATCH 1 of 5] mem_access: hvm changes to page faults

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1 of 5] mem_access: hvm changes to page faults
From: Joe Epstein <jepstein@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 28 Dec 2010 23:27:17 -0800
Delivery-date: Tue, 28 Dec 2010 23:29:56 -0800
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:mime-version:sender:received:from:date :x-google-sender-auth:message-id:subject:to:content-type; bh=5B5u0No06OelICHO1d5D13i2LJ8KbZGare2U9vd4MwM=; b=JpgW07D6mn1EOaZPtLk1Hv6FydLy1T8Sy9gFKaQ7rQ0n1BCUvCFXl8n1/B6Kfbl3RP jPCE5RC8YeIJmUgg1FJHPNAdN/roShrsfGOLQoI3ZEUqs0rFORXBzC372l6AqdPCaWtv qbrRi1LaDUmd3+2Itl9LxENgx/ruz2ke1yvMk=
Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:from:date:x-google-sender-auth:message-id :subject:to:content-type; b=o1g2nkWg8jAkwhJ5g/ns1XrddNrq0beV5XwxPXNx7eWNOKeqIncf9BFMqZakjofw4K vmQ0w5ZfEBtcBiDPpGQslHR9uLx4Fu3QzkX+9W0pNOiLBrkBNKWg5l9c/tPYoY5+X7vq 13XS2ehOfDk7LlGIoBTj5iY3gyrzEqWQU9VxA=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Changes the nested page fault to send memory access failures to the
event handler, if there is one.  Also adds HVMOPs to set and get memory
access.

Signed-off-by: Joe Epstein <jepstein98@xxxxxxxxx>

diff -r 4e108cf56d07 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Dec 27 08:00:09 2010 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Tue Dec 28 22:35:35 2010 -0800
@@ -1086,61 +1086,91 @@
     domain_shutdown(v->domain, SHUTDOWN_reboot);
 }

-bool_t hvm_hap_nested_page_fault(unsigned long gfn)
+bool_t hvm_hap_nested_page_fault(unsigned long gpa,
+                                 bool_t gla_valid,
+                                 unsigned long gla,
+                                 bool_t access_r,
+                                 bool_t access_w,
+                                 bool_t access_x)
 {
+    unsigned long gfn = gpa >> PAGE_SHIFT;
     p2m_type_t p2mt;
     mfn_t mfn;
     struct vcpu *v = current;
     struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
+    int guest_fault = 0;

     mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);

-    /*
-     * If this GFN is emulated MMIO or marked as read-only, pass the fault
-     * to the mmio handler.
-     */
-    if ( (p2mt == p2m_mmio_dm) || (p2mt == p2m_ram_ro) )
+#ifdef __x86_64__
+    /* Check if the page has been paged out */
+    if ( p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_out) )
     {
-        if ( !handle_mmio() )
-            hvm_inject_exception(TRAP_gp_fault, 0, 0);
+        p2m_mem_paging_populate(p2m, gfn);
         return 1;
     }

-#ifdef __x86_64__
-    /* Check if the page has been paged out */
-    if ( p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_out) )
-        p2m_mem_paging_populate(p2m, gfn);
-
     /* Mem sharing: unshare the page and try again */
-    if ( p2mt == p2m_ram_shared )
+    if ( p2mt == p2m_ram_shared && access_w )
     {
         mem_sharing_unshare_page(p2m, gfn, 0);
         return 1;
     }
 #endif
-
-    /* Spurious fault? PoD and log-dirty also take this path. */
-    if ( p2m_is_ram(p2mt) )
+
+    /*
+     * If this GFN is emulated MMIO or marked as read-only (which old
MMIO is),
+     * pass the fault to the mmio handler first.
+     */
+    if ( (p2mt == p2m_mmio_dm) || (p2mt == p2m_ram_ro) )
     {
-        /*
-         * Page log dirty is always done with order 0. If this mfn resides in
-         * a large page, we do not change other pages type within that large
-         * page.
-         */
-        paging_mark_dirty(v->domain, mfn_x(mfn));
-        p2m_change_type(p2m, gfn, p2m_ram_logdirty, p2m_ram_rw);
+        if ( !handle_mmio() )
+        {
+            guest_fault = 1;
+            goto check_access_handler;
+        }
         return 1;
     }

-    /* Shouldn't happen: Maybe the guest was writing to a r/o grant mapping? */
-    if ( p2mt == p2m_grant_map_ro )
+    /* Was it a write access: log-dirty, etc... */
+    if ( access_w ) {
+        /* PoD and log-dirty also take this path. */
+        if ( p2mt != p2m_ram_rw && p2m_is_ram(p2mt) )
+        {
+            /*
+             * Page log dirty is always done with order 0. If this
mfn resides in
+             * a large page, we do not change other pages type within
that large
+             * page.
+             */
+            paging_mark_dirty(v->domain, mfn_x(mfn));
+            p2m_change_type(p2m, gfn, p2m_ram_logdirty, p2m_ram_rw);
+            return 1;
+        }
+
+        /* Shouldn't happen: Maybe the guest was writing to a r/o
grant mapping? */
+        if ( p2mt == p2m_grant_map_ro )
+        {
+            gdprintk(XENLOG_WARNING,
+                     "trying to write to read-only grant mapping\n");
+            guest_fault = 1;
+            goto check_access_handler;
+        }
+    } /* end access_w */
+
+ check_access_handler:
+    /* Even if it is the guest's "fault", check with the mem_event
interface instead if
+     * one is there */
+    if ( p2m_mem_access_check(gpa, gla_valid, gla, access_r,
access_w, access_x) )
+        return 1;
+
+    /* If there is no handler, then fault if guest_fault = 1 */
+    if ( guest_fault )
     {
-        gdprintk(XENLOG_WARNING,
-                 "trying to write to read-only grant mapping\n");
         hvm_inject_exception(TRAP_gp_fault, 0, 0);
         return 1;
     }

+    /* Nothing handled it: it must be an access error with no memory
handler, so fail */
     return 0;
 }

@@ -3412,6 +3442,143 @@
         break;
     }

+    case HVMOP_set_mem_access:
+    {
+        struct xen_hvm_set_mem_access a;
+        struct domain *d;
+        struct p2m_domain *p2m;
+        unsigned long pfn;
+
+        p2m_access_t memaccess[] = {
+            p2m_access_n,
+            p2m_access_r,
+            p2m_access_w,
+            p2m_access_rw,
+            p2m_access_x,
+            p2m_access_rx,
+            p2m_access_wx,
+            p2m_access_rwx,
+            p2m_access_rx2rw,
+            0,  /* HVMMEM_access_default -- will get set below */
+        };
+
+        if ( copy_from_guest(&a, arg, 1) )
+            return -EFAULT;
+
+        rc = rcu_lock_target_domain_by_id(a.domid, &d);
+        if ( rc != 0 )
+            return rc;
+
+        rc = -EINVAL;
+        if ( !is_hvm_domain(d) )
+            goto param_fail5;
+
+        p2m = p2m_get_hostp2m(d);
+        memaccess[HVMMEM_access_default] = p2m->default_access;
+
+        /* If request to set default access */
+        if ( a.first_pfn == ~0ull )
+        {
+            rc = 0;
+            p2m->default_access = memaccess[a.hvmmem_access];
+            goto param_fail5;
+        }
+
+        rc = -EINVAL;
+        if ( (a.first_pfn > domain_get_maximum_gpfn(d)) ||
+             ((a.first_pfn + a.nr - 1) < a.first_pfn) ||
+             ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) )
+            goto param_fail5;
+
+        if ( a.hvmmem_access >= ARRAY_SIZE(memaccess) )
+            goto param_fail5;
+
+        for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
+        {
+            p2m_type_t t;
+            mfn_t mfn;
+            int success;
+
+            mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0);
+
+            p2m_lock(p2m);
+            success = p2m->set_entry(p2m, pfn, mfn, 0, t,
memaccess[a.hvmmem_access]);
+            p2m_unlock(p2m);
+            if ( !success )
+                goto param_fail5;
+        }
+
+        rc = 0;
+
+    param_fail5:
+        rcu_unlock_domain(d);
+        break;
+    }
+
+    case HVMOP_get_mem_access:
+    {
+        struct xen_hvm_get_mem_access a;
+        struct domain *d;
+        struct p2m_domain *p2m;
+        p2m_type_t t;
+        p2m_access_t ac;
+        mfn_t mfn;
+
+        /* Interface access to internal p2m accesses */
+        hvmmem_access_t memaccess[] = {
+            HVMMEM_access_n,
+            HVMMEM_access_r,
+            HVMMEM_access_w,
+            HVMMEM_access_rw,
+            HVMMEM_access_x,
+            HVMMEM_access_rx,
+            HVMMEM_access_wx,
+            HVMMEM_access_rwx,
+            HVMMEM_access_rx2rw
+        };
+
+        if ( copy_from_guest(&a, arg, 1) )
+            return -EFAULT;
+
+        rc = rcu_lock_target_domain_by_id(a.domid, &d);
+        if ( rc != 0 )
+            return rc;
+
+        rc = -EINVAL;
+        if ( !is_hvm_domain(d) )
+            goto param_fail6;
+
+        p2m = p2m_get_hostp2m(d);
+
+        if ( a.pfn == ~0ull )
+        {
+            a.hvmmem_access = memaccess[p2m->default_access];
+        }
+        else {
+            rc = -EINVAL;
+            if ( (a.pfn > domain_get_maximum_gpfn(d)) )
+                goto param_fail6;
+
+            rc = -ESRCH;
+            mfn = p2m->get_entry(p2m, a.pfn, &t, &ac, p2m_query);
+
+            if ( mfn_x(mfn) == INVALID_MFN )
+                goto param_fail6;
+
+            rc = -ERANGE;
+            if ( ac >= ARRAY_SIZE(memaccess) )
+                goto param_fail6;
+
+            a.hvmmem_access = memaccess[ac];
+        }
+
+        rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
+
+    param_fail6:
+        rcu_unlock_domain(d);
+        break;
+    }
+
     case HVMOP_pagetable_dying:
     {
         struct xen_hvm_pagetable_dying a;
@@ -3426,12 +3593,12 @@

         rc = -EINVAL;
         if ( !is_hvm_domain(d) || !paging_mode_shadow(d) )
-            goto param_fail5;
+            goto param_fail7;

         rc = 0;
         pagetable_dying(d, a.gpa);

-    param_fail5:
+    param_fail7:
         rcu_unlock_domain(d);
         break;
     }
diff -r 4e108cf56d07 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Dec 27 08:00:09 2010 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Dec 28 22:35:35 2010 -0800
@@ -979,7 +979,7 @@
         __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d);
     }

-    if ( hvm_hap_nested_page_fault(gfn) )
+    if ( hvm_hap_nested_page_fault(gpa, 0, ~0ull, 0, 0, 0) )
         return;

     /* Everything else is an error. */
diff -r 4e108cf56d07 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Dec 27 08:00:09 2010 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue Dec 28 22:35:35 2010 -0800
@@ -2079,7 +2079,13 @@
         __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d);
     }

-    if ( hvm_hap_nested_page_fault(gfn) )
+    if ( hvm_hap_nested_page_fault(gpa,
+                                   qualification & EPT_GLA_VALID       ? 1 : 0,
+                                   qualification & EPT_GLA_VALID
+                                     ? __vmread(GUEST_LINEAR_ADDRESS) : ~0ull,
+                                   qualification & EPT_READ_VIOLATION  ? 1 : 0,
+                                   qualification & EPT_WRITE_VIOLATION ? 1 : 0,
+                                   qualification & EPT_EXEC_VIOLATION
 ? 1 : 0) )
         return;

     /* Everything else is an error. */
diff -r 4e108cf56d07 xen/arch/ia64/vmx/vmx_hypercall.c
--- a/xen/arch/ia64/vmx/vmx_hypercall.c Mon Dec 27 08:00:09 2010 +0000
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c Tue Dec 28 22:38:13 2010 -0800
@@ -218,6 +218,9 @@
     }

     case HVMOP_set_mem_type:
+    case HVMOP_set_mem_access:
+    case HVMOP_get_mem_access:
+
         rc = -ENOSYS;
         break;

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 1 of 5] mem_access: hvm changes to page faults, Joe Epstein <=