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

[Xen-changelog] [xen-unstable] mem_access: HVMOPs for setting mem access



# HG changeset patch
# User Joe Epstein <jepstein98@xxxxxxxxx>
# Date 1294401285 0
# Node ID 76e07538870e593c1563a7af08b394e8797f6e48
# Parent  8af5bab1bf43cc793ea9b342a7929827782b8628
mem_access: HVMOPs for setting mem access

* Creates HVMOPs for setting and getting memory access.  The hypercalls
  can set individual pages or the default access for new/refreshed
  pages.

* Added functions to libxc to access these hypercalls.

Signed-off-by: Joe Epstein <jepstein98@xxxxxxxxx>
Reviewed-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Acked-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Acked-by: Keir Fraser <keir@xxxxxxx>
Acked-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
 tools/libxc/Makefile              |    1 
 tools/libxc/xc_domain.c           |   11 ++
 tools/libxc/xc_mem_access.c       |   42 ++++++++++
 tools/libxc/xc_misc.c             |   60 ++++++++++++++
 tools/libxc/xenctrl.h             |   28 ++++++
 xen/arch/ia64/vmx/vmx_hypercall.c |    3 
 xen/arch/x86/hvm/hvm.c            |  153 ++++++++++++++++++++++++++++++++++++--
 xen/arch/x86/mm/mem_sharing.c     |    2 
 xen/arch/x86/mm/p2m.c             |    1 
 xen/include/public/hvm/hvm_op.h   |   42 ++++++++++
 10 files changed, 338 insertions(+), 5 deletions(-)

diff -r 8af5bab1bf43 -r 76e07538870e tools/libxc/Makefile
--- a/tools/libxc/Makefile      Fri Jan 07 11:54:42 2011 +0000
+++ b/tools/libxc/Makefile      Fri Jan 07 11:54:45 2011 +0000
@@ -28,6 +28,7 @@ CTRL_SRCS-y       += xc_tmem.c
 CTRL_SRCS-y       += xc_tmem.c
 CTRL_SRCS-y       += xc_mem_event.c
 CTRL_SRCS-y       += xc_mem_paging.c
+CTRL_SRCS-y       += xc_mem_access.c
 CTRL_SRCS-y       += xc_memshr.c
 CTRL_SRCS-y       += xc_hcall_buf.c
 CTRL_SRCS-y       += xc_foreign_memory.c
diff -r 8af5bab1bf43 -r 76e07538870e tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Fri Jan 07 11:54:42 2011 +0000
+++ b/tools/libxc/xc_domain.c   Fri Jan 07 11:54:45 2011 +0000
@@ -1442,6 +1442,17 @@ int xc_domain_debug_control(xc_interface
     return do_domctl(xc, &domctl);
 }
 
+int xc_domain_set_access_required(xc_interface *xch,
+                                  uint32_t domid,
+                                  unsigned int required)
+{
+    DECLARE_DOMCTL;
+
+    domctl.cmd = XEN_DOMCTL_set_access_required;
+    domctl.domain = domid;
+    domctl.u.access_required.access_required = required;
+    return do_domctl(xch, &domctl);
+}
 
 /*
  * Local variables:
diff -r 8af5bab1bf43 -r 76e07538870e tools/libxc/xc_mem_access.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_mem_access.c       Fri Jan 07 11:54:45 2011 +0000
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ * tools/libxc/xc_mem_access.c
+ *
+ * Interface to low-level memory access mode functionality
+ *
+ * Copyright (c) 2011 Virtuata, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+ */
+
+#include "xc_private.h"
+
+
+int xc_mem_access_resume(xc_interface *xch, domid_t domain_id, unsigned long 
gfn)
+{
+    return xc_mem_event_control(xch, domain_id,
+                                XEN_DOMCTL_MEM_EVENT_OP_ACCESS_RESUME,
+                                XEN_DOMCTL_MEM_EVENT_OP_ACCESS, NULL, NULL,
+                                gfn);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End: 
+ */
diff -r 8af5bab1bf43 -r 76e07538870e tools/libxc/xc_misc.c
--- a/tools/libxc/xc_misc.c     Fri Jan 07 11:54:42 2011 +0000
+++ b/tools/libxc/xc_misc.c     Fri Jan 07 11:54:45 2011 +0000
@@ -511,6 +511,66 @@ int xc_hvm_set_mem_type(
     return rc;
 }
 
+int xc_hvm_set_mem_access(
+    xc_interface *xch, domid_t dom, hvmmem_access_t mem_access, uint64_t 
first_pfn, uint64_t nr)
+{
+    DECLARE_HYPERCALL;
+    DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_mem_access, arg);
+    int rc;
+
+    arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+    if ( arg == NULL )
+    {
+        PERROR("Could not allocate memory for xc_hvm_set_mem_access 
hypercall");
+        return -1;
+    }
+
+    arg->domid         = dom;
+    arg->hvmmem_access = mem_access;
+    arg->first_pfn     = first_pfn;
+    arg->nr            = nr;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_set_mem_access;
+    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+    rc = do_xen_hypercall(xch, &hypercall);
+
+    xc_hypercall_buffer_free(xch, arg);
+
+    return rc;
+}
+
+int xc_hvm_get_mem_access(
+    xc_interface *xch, domid_t dom, uint64_t pfn, hvmmem_access_t* mem_access)
+{
+    DECLARE_HYPERCALL;
+    DECLARE_HYPERCALL_BUFFER(struct xen_hvm_get_mem_access, arg);
+    int rc;
+
+    arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+    if ( arg == NULL )
+    {
+        PERROR("Could not allocate memory for xc_hvm_get_mem_access 
hypercall");
+        return -1;
+    }
+
+    arg->domid       = dom;
+    arg->pfn         = pfn;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_get_mem_access;
+    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+
+    rc = do_xen_hypercall(xch, &hypercall);
+
+    if ( !rc )
+        *mem_access = arg->hvmmem_access;
+
+    xc_hypercall_buffer_free(xch, arg);
+
+    return rc;
+}
 
 /*
  * Local variables:
diff -r 8af5bab1bf43 -r 76e07538870e tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Fri Jan 07 11:54:42 2011 +0000
+++ b/tools/libxc/xenctrl.h     Fri Jan 07 11:54:45 2011 +0000
@@ -701,6 +701,19 @@ int xc_domain_setdebugging(xc_interface 
                            uint32_t domid,
                            unsigned int enable);
 
+/**
+ * This function sets or clears the requirement that an access memory
+ * event listener is required on the domain.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain id to send trigger
+ * @parm enable true to require a listener
+ * return 0 on success, -1 on failure
+ */
+int xc_domain_set_access_required(xc_interface *xch,
+                                 uint32_t domid,
+                                 unsigned int required);
+
 /*
  * CPUPOOL MANAGEMENT FUNCTIONS
  */
@@ -1398,6 +1411,19 @@ int xc_hvm_set_mem_type(
 int xc_hvm_set_mem_type(
     xc_interface *xch, domid_t dom, hvmmem_type_t memtype, uint64_t first_pfn, 
uint64_t nr);
 
+/*
+ * Set a range of memory to a specific access.
+ * Allowed types are HVMMEM_access_default, HVMMEM_access_n, any combination 
of 
+ * HVM_access_ + (rwx), and HVM_access_rx2rw
+ */
+int xc_hvm_set_mem_access(
+    xc_interface *xch, domid_t dom, hvmmem_access_t memaccess, uint64_t 
first_pfn, uint64_t nr);
+
+/*
+ * Gets the mem access for the given page (returned in memacess on success)
+ */
+int xc_hvm_get_mem_access(
+    xc_interface *xch, domid_t dom, uint64_t pfn, hvmmem_access_t* memaccess);
 
 /*
  *  LOGGING AND ERROR REPORTING
@@ -1703,6 +1729,8 @@ int xc_mem_paging_evict(xc_interface *xc
 int xc_mem_paging_evict(xc_interface *xch, domid_t domain_id, unsigned long 
gfn);
 int xc_mem_paging_prep(xc_interface *xch, domid_t domain_id, unsigned long 
gfn);
 int xc_mem_paging_resume(xc_interface *xch, domid_t domain_id,
+                         unsigned long gfn);
+int xc_mem_access_resume(xc_interface *xch, domid_t domain_id,
                          unsigned long gfn);
 
 /**
diff -r 8af5bab1bf43 -r 76e07538870e xen/arch/ia64/vmx/vmx_hypercall.c
--- a/xen/arch/ia64/vmx/vmx_hypercall.c Fri Jan 07 11:54:42 2011 +0000
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c Fri Jan 07 11:54:45 2011 +0000
@@ -218,6 +218,9 @@ do_hvm_op(unsigned long op, XEN_GUEST_HA
     }
 
     case HVMOP_set_mem_type:
+    case HVMOP_set_mem_access:
+    case HVMOP_get_mem_access:
+
         rc = -ENOSYS;
         break;
 
diff -r 8af5bab1bf43 -r 76e07538870e xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Fri Jan 07 11:54:42 2011 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Fri Jan 07 11:54:45 2011 +0000
@@ -3464,26 +3464,169 @@ long do_hvm_op(unsigned long op, XEN_GUE
         break;
     }
 
-    case HVMOP_pagetable_dying:
-    {
-        struct xen_hvm_pagetable_dying a;
+    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;
+
+        if ( current->domain->domain_id == a.domid )
+            return -EPERM;
 
         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;
+
+        if ( current->domain->domain_id == a.domid )
+            return -EPERM;
+
+        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;
+        struct domain *d;
+
+        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) || !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 8af5bab1bf43 -r 76e07538870e xen/arch/x86/mm/mem_sharing.c
--- a/xen/arch/x86/mm/mem_sharing.c     Fri Jan 07 11:54:42 2011 +0000
+++ b/xen/arch/x86/mm/mem_sharing.c     Fri Jan 07 11:54:45 2011 +0000
@@ -304,6 +304,8 @@ static struct page_info* mem_sharing_all
     if(page != NULL) return page;
 
     memset(&req, 0, sizeof(req));
+    req.type = MEM_EVENT_TYPE_SHARED;
+
     if(must_succeed) 
     {
         /* We do not support 'must_succeed' any more. External operations such
diff -r 8af5bab1bf43 -r 76e07538870e xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c     Fri Jan 07 11:54:42 2011 +0000
+++ b/xen/arch/x86/mm/p2m.c     Fri Jan 07 11:54:45 2011 +0000
@@ -2781,6 +2781,7 @@ void p2m_mem_paging_populate(struct p2m_
         return;
 
     memset(&req, 0, sizeof(req));
+    req.type = MEM_EVENT_TYPE_PAGING;
 
     /* Fix p2m mapping */
     /* XXX: It seems inefficient to have this here, as it's only needed
diff -r 8af5bab1bf43 -r 76e07538870e xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h   Fri Jan 07 11:54:42 2011 +0000
+++ b/xen/include/public/hvm/hvm_op.h   Fri Jan 07 11:54:45 2011 +0000
@@ -158,4 +158,46 @@ typedef struct xen_hvm_xentrace xen_hvm_
 typedef struct xen_hvm_xentrace xen_hvm_xentrace_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
 
+#define HVMOP_set_mem_access        12
+typedef enum {
+    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,       /* Page starts off as read-execute, but 
automatically change
+                               * to read-write on a write */
+    HVMMEM_access_default      /* Take the domain default */
+} hvmmem_access_t;
+/* Notify that a region of memory is to have specific access types */
+struct xen_hvm_set_mem_access {
+    /* Domain to be updated. */
+    domid_t domid;
+    uint16_t pad[3]; /* align next field on 8-byte boundary */
+    /* Memory type */
+    uint64_t hvmmem_access; /* hvm_access_t */
+    /* First pfn, or ~0ull to set the default access for new pages */
+    uint64_t first_pfn;
+    /* Number of pages, ignored on setting default access */
+    uint64_t nr;
+};
+typedef struct xen_hvm_set_mem_access xen_hvm_set_mem_access_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_access_t);
+
+#define HVMOP_get_mem_access        13
+/* Get the specific access type for that region of memory */
+struct xen_hvm_get_mem_access {
+    /* Domain to be queried. */
+    domid_t domid;
+    uint16_t pad[3]; /* align next field on 8-byte boundary */
+    /* Memory type: OUT */
+    uint64_t hvmmem_access; /* hvm_access_t */
+    /* pfn, or ~0ull for default access for new pages.  IN */
+    uint64_t pfn;
+};
+typedef struct xen_hvm_get_mem_access xen_hvm_get_mem_access_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_access_t);
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */

_______________________________________________
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®.