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] mem_access: HVMOPs for setting mem access

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] mem_access: HVMOPs for setting mem access
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 17 Jan 2011 07:58:52 -0800
Delivery-date: Mon, 17 Jan 2011 08:05:58 -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 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] mem_access: HVMOPs for setting mem access, Xen patchbot-unstable <=