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

Re: [Xen-devel] [PATCH 4 of 7] REDO2: mem_access & mem_access 2: HVMOPs for setting mem access



On Thu, 2011-01-06 at 03:53 +0000, Joe Epstein wrote:
> * 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.

The tools/libxc/* bits look good to me, except perhaps
xc_domain_set_access_required perhaps belongs in the previous patch?

Reviewed-by: Ian Campbell <ian.campbell@xxxxxxxxxx>

> 
> 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__ */
> 



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.