* 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>  
 
 
  diff -r 281e5488ee97 -r 98c86c674ba3 tools/libxc/Makefile --- a/tools/libxc/Makefile    Wed Jan 05 18:50:54 2011 -0800 
+++ b/tools/libxc/Makefile    Wed Jan 05 18:53:22 2011 -0800 @@ -28,6 +28,7 @@ CTRL_SRCS-y       += xc_resume.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 281e5488ee97 -r 98c86c674ba3 tools/libxc/xc_domain.c 
--- a/tools/libxc/xc_domain.c    Wed Jan 05 18:50:54 2011 -0800 +++ b/tools/libxc/xc_domain.c    Wed Jan 05 18:53:22 2011 -0800 @@ -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 281e5488ee97 -r 98c86c674ba3 tools/libxc/xc_mem_access.c 
--- /dev/null    Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/xc_mem_access.c    Wed Jan 05 18:53:22 2011 -0800 @@ -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 281e5488ee97 -r 98c86c674ba3 tools/libxc/xc_misc.c 
--- a/tools/libxc/xc_misc.c    Wed Jan 05 18:50:54 2011 -0800 +++ b/tools/libxc/xc_misc.c    Wed Jan 05 18:53:22 2011 -0800 @@ -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 281e5488ee97 -r 98c86c674ba3 tools/libxc/xenctrl.h 
--- a/tools/libxc/xenctrl.h    Wed Jan 05 18:50:54 2011 -0800 +++ b/tools/libxc/xenctrl.h    Wed Jan 05 18:53:22 2011 -0800 @@ -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_modified_memory(  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 @@ -1704,6 +1730,8 @@ int xc_mem_paging_evict(xc_interface *xc  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); 
   /**   * memshr operations diff -r 281e5488ee97 -r 98c86c674ba3 xen/arch/ia64/vmx/vmx_hypercall.c --- a/xen/arch/ia64/vmx/vmx_hypercall.c    Wed Jan 05 18:50:54 2011 -0800 +++ b/xen/arch/ia64/vmx/vmx_hypercall.c    Wed Jan 05 18:53:22 2011 -0800 
@@ -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 281e5488ee97 -r 98c86c674ba3 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c    Wed Jan 05 18:50:54 2011 -0800 +++ b/xen/arch/x86/hvm/hvm.c    Wed Jan 05 18:53:22 2011 -0800 @@ -3466,6 +3466,149 @@ long do_hvm_op(unsigned long op, XEN_GUE 
         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; + +        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; @@ -3480,12 +3623,12 @@ long do_hvm_op(unsigned long op, XEN_GUE 
           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 281e5488ee97 -r 98c86c674ba3 xen/arch/x86/mm/mem_sharing.c --- a/xen/arch/x86/mm/mem_sharing.c    Wed Jan 05 18:50:54 2011 -0800 
+++ b/xen/arch/x86/mm/mem_sharing.c    Wed Jan 05 18:53:22 2011 -0800 @@ -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 281e5488ee97 -r 98c86c674ba3 xen/arch/x86/mm/p2m.c 
--- a/xen/arch/x86/mm/p2m.c    Wed Jan 05 18:50:54 2011 -0800 +++ b/xen/arch/x86/mm/p2m.c    Wed Jan 05 18:53:22 2011 -0800 @@ -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 281e5488ee97 -r 98c86c674ba3 xen/include/public/hvm/hvm_op.h 
--- a/xen/include/public/hvm/hvm_op.h    Wed Jan 05 18:50:54 2011 -0800 +++ b/xen/include/public/hvm/hvm_op.h    Wed Jan 05 18:53:22 2011 -0800 @@ -158,4 +158,46 @@ struct xen_hvm_xentrace {  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__ */
  
 
4.patch 
Description: Text Data 
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
 
 |