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

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

To: Joe Epstein <jepstein98@xxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH 4 of 7] REDO2: mem_access & mem_access 2: HVMOPs for setting mem access
From: Ian Campbell <Ian.Campbell@xxxxxxxxxx>
Date: Thu, 6 Jan 2011 09:54:32 +0000
Cc: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Thu, 06 Jan 2011 01:55:31 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <AANLkTim+a+gP4nmjwCPCZb18RZYRUjCXi7ygA=UEQUK4@xxxxxxxxxxxxxx>
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>
Organization: Citrix Systems, Inc.
References: <AANLkTim+a+gP4nmjwCPCZb18RZYRUjCXi7ygA=UEQUK4@xxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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

<Prev in Thread] Current Thread [Next in Thread>