direct-io.hg

changeset 8856:0d10fac28427

New memory_op subcall XENMEM_translate_gpfn_list.

Allows translation from GPFNs to MFNs for an auto-translated
guest.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 16 18:52:06 2006 +0100 (2006-02-16)
parents 2b0078f771cc
children 40d7eef7d3f5
files tools/libxc/xc_domain.c tools/libxc/xc_private.c tools/libxc/xenctrl.h xen/common/memory.c xen/include/public/memory.h
line diff
     1.1 --- a/tools/libxc/xc_domain.c	Thu Feb 16 17:37:21 2006 +0100
     1.2 +++ b/tools/libxc/xc_domain.c	Thu Feb 16 18:52:06 2006 +0100
     1.3 @@ -326,6 +326,53 @@ int xc_domain_memory_decrease_reservatio
     1.4      return err;
     1.5  }
     1.6  
     1.7 +int xc_domain_memory_populate_physmap(int xc_handle,
     1.8 +                                          uint32_t domid,
     1.9 +                                          unsigned long nr_extents,
    1.10 +                                          unsigned int extent_order,
    1.11 +                                          unsigned int address_bits,
    1.12 +                                          unsigned long *extent_start)
    1.13 +{
    1.14 +    int err;
    1.15 +    struct xen_memory_reservation reservation = {
    1.16 +        .extent_start = extent_start,
    1.17 +        .nr_extents   = nr_extents,
    1.18 +        .extent_order = extent_order,
    1.19 +        .address_bits = address_bits,
    1.20 +        .domid        = domid
    1.21 +    };
    1.22 +
    1.23 +    err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
    1.24 +    if ( err == nr_extents )
    1.25 +        return 0;
    1.26 +
    1.27 +    if ( err > 0 )
    1.28 +    {
    1.29 +        fprintf(stderr,"Failed deallocation for dom %d: %ld pages order %d\n",
    1.30 +                domid, nr_extents, extent_order);
    1.31 +        errno = EBUSY;
    1.32 +        err = -1;
    1.33 +    }
    1.34 +
    1.35 +    return err;
    1.36 +}
    1.37 +
    1.38 +int xc_domain_translate_gpfn_list(int xc_handle,
    1.39 +                                  uint32_t domid,
    1.40 +                                  unsigned long nr_gpfns,
    1.41 +                                  unsigned long *gpfn_list,
    1.42 +                                  unsigned long *mfn_list)
    1.43 +{
    1.44 +    struct xen_translate_gpfn_list op = {
    1.45 +        .domid        = domid,
    1.46 +        .nr_gpfns     = nr_gpfns,
    1.47 +        .gpfn_list    = gpfn_list,
    1.48 +        .mfn_list     = mfn_list
    1.49 +    };
    1.50 +
    1.51 +    return xc_memory_op(xc_handle, XENMEM_translate_gpfn_list, &op);
    1.52 +}
    1.53 +
    1.54  int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
    1.55  {
    1.56      DECLARE_DOM0_OP;
     2.1 --- a/tools/libxc/xc_private.c	Thu Feb 16 17:37:21 2006 +0100
     2.2 +++ b/tools/libxc/xc_private.c	Thu Feb 16 18:52:06 2006 +0100
     2.3 @@ -191,6 +191,7 @@ int xc_memory_op(int xc_handle,
     2.4      DECLARE_HYPERCALL;
     2.5      struct xen_memory_reservation *reservation = arg;
     2.6      struct xen_machphys_mfn_list *xmml = arg;
     2.7 +    struct xen_translate_gpfn_list *trans = arg;
     2.8      long ret = -EINVAL;
     2.9  
    2.10      hypercall.op     = __HYPERVISOR_memory_op;
    2.11 @@ -237,6 +238,26 @@ int xc_memory_op(int xc_handle,
    2.12              goto out1;
    2.13          }
    2.14          break;
    2.15 +    case XENMEM_translate_gpfn_list:
    2.16 +        if ( mlock(trans, sizeof(*trans)) != 0 )
    2.17 +        {
    2.18 +            PERROR("Could not mlock");
    2.19 +            goto out1;
    2.20 +        }
    2.21 +        if ( mlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long)) != 0 )
    2.22 +        {
    2.23 +            PERROR("Could not mlock");
    2.24 +            safe_munlock(trans, sizeof(*trans));
    2.25 +            goto out1;
    2.26 +        }
    2.27 +        if ( mlock(trans->mfn_list, trans->nr_gpfns * sizeof(long)) != 0 )
    2.28 +        {
    2.29 +            PERROR("Could not mlock");
    2.30 +            safe_munlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long));
    2.31 +            safe_munlock(trans, sizeof(*trans));
    2.32 +            goto out1;
    2.33 +        }
    2.34 +        break;
    2.35      }
    2.36  
    2.37      ret = do_xen_hypercall(xc_handle, &hypercall);
    2.38 @@ -259,6 +280,11 @@ int xc_memory_op(int xc_handle,
    2.39      case XENMEM_reserved_phys_area:
    2.40          safe_munlock(arg, sizeof(struct xen_reserved_phys_area));
    2.41          break;
    2.42 +    case XENMEM_translate_gpfn_list:
    2.43 +            safe_munlock(trans->mfn_list, trans->nr_gpfns * sizeof(long));
    2.44 +            safe_munlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long));
    2.45 +            safe_munlock(trans, sizeof(*trans));
    2.46 +        break;
    2.47      }
    2.48  
    2.49   out1:
     3.1 --- a/tools/libxc/xenctrl.h	Thu Feb 16 17:37:21 2006 +0100
     3.2 +++ b/tools/libxc/xenctrl.h	Thu Feb 16 18:52:06 2006 +0100
     3.3 @@ -373,6 +373,19 @@ int xc_domain_memory_decrease_reservatio
     3.4                                            unsigned int extent_order,
     3.5  					  unsigned long *extent_start);
     3.6  
     3.7 +int xc_domain_memory_populate_physmap(int xc_handle,
     3.8 +                                      uint32_t domid,
     3.9 +                                      unsigned long nr_extents,
    3.10 +                                      unsigned int extent_order,
    3.11 +                                      unsigned int address_bits,
    3.12 +                                      unsigned long *extent_start);
    3.13 +
    3.14 +int xc_domain_translate_gpfn_list(int xc_handle,
    3.15 +                                  uint32_t domid,
    3.16 +                                  unsigned long nr_gpfns,
    3.17 +                                  unsigned long *gpfn_list,
    3.18 +                                  unsigned long *mfn_list);
    3.19 +
    3.20  int xc_domain_ioport_permission(int xc_handle,
    3.21                                  uint32_t domid,
    3.22                                  uint32_t first_port,
     4.1 --- a/xen/common/memory.c	Thu Feb 16 17:37:21 2006 +0100
     4.2 +++ b/xen/common/memory.c	Thu Feb 16 18:52:06 2006 +0100
     4.3 @@ -20,6 +20,13 @@
     4.4  #include <asm/hardirq.h>
     4.5  #include <public/memory.h>
     4.6  
     4.7 +/*
     4.8 + * To allow safe resume of do_memory_op() after preemption, we need to know 
     4.9 + * at what point in the page list to resume. For this purpose I steal the 
    4.10 + * high-order bits of the @cmd parameter, which are otherwise unused and zero.
    4.11 + */
    4.12 +#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
    4.13 +
    4.14  static long
    4.15  increase_reservation(
    4.16      struct domain *d, 
    4.17 @@ -188,17 +195,74 @@ decrease_reservation(
    4.18      return nr_extents;
    4.19  }
    4.20  
    4.21 -/*
    4.22 - * To allow safe resume of do_memory_op() after preemption, we need to know 
    4.23 - * at what point in the page list to resume. For this purpose I steal the 
    4.24 - * high-order bits of the @cmd parameter, which are otherwise unused and zero.
    4.25 - */
    4.26 -#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
    4.27 +static long
    4.28 +translate_gpfn_list(
    4.29 +    struct xen_translate_gpfn_list *uop, unsigned long *progress)
    4.30 +{
    4.31 +    struct xen_translate_gpfn_list op;
    4.32 +    unsigned long i, gpfn, mfn;
    4.33 +    struct domain *d;
    4.34  
    4.35 -long do_memory_op(int cmd, void *arg)
    4.36 +    if ( copy_from_user(&op, uop, sizeof(op)) )
    4.37 +        return -EFAULT;
    4.38 +
    4.39 +    /* Is size too large for us to encode a continuation? */
    4.40 +    if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) )
    4.41 +        return -EINVAL;
    4.42 +
    4.43 +    if ( !array_access_ok(op.gpfn_list, op.nr_gpfns, sizeof(*op.gpfn_list)) ||
    4.44 +         !array_access_ok(op.mfn_list, op.nr_gpfns, sizeof(*op.mfn_list)) )
    4.45 +        return -EFAULT;
    4.46 +
    4.47 +    if ( op.domid == DOMID_SELF )
    4.48 +        op.domid = current->domain->domain_id;
    4.49 +    else if ( !IS_PRIV(current->domain) )
    4.50 +        return -EPERM;
    4.51 +
    4.52 +    if ( (d = find_domain_by_id(op.domid)) == NULL )
    4.53 +        return -ESRCH;
    4.54 +
    4.55 +    if ( !shadow_mode_translate(d) )
    4.56 +    {
    4.57 +        put_domain(d);
    4.58 +        return -EINVAL;
    4.59 +    }
    4.60 +
    4.61 +    for ( i = *progress; i < op.nr_gpfns; i++ )
    4.62 +    {
    4.63 +        if ( hypercall_preempt_check() )
    4.64 +        {
    4.65 +            put_domain(d);
    4.66 +            *progress = i;
    4.67 +            return -EAGAIN;
    4.68 +        }
    4.69 +
    4.70 +        if ( unlikely(__copy_from_user(&gpfn, &op.gpfn_list[i],
    4.71 +                                       sizeof(gpfn))) )
    4.72 +        {
    4.73 +            put_domain(d);
    4.74 +            return -EFAULT;
    4.75 +        }
    4.76 +
    4.77 +        mfn = gmfn_to_mfn(d, gpfn);
    4.78 +
    4.79 +        if ( unlikely(__copy_to_user(&op.mfn_list[i], &mfn,
    4.80 +                                     sizeof(mfn))) )
    4.81 +        {
    4.82 +            put_domain(d);
    4.83 +            return -EFAULT;
    4.84 +        }
    4.85 +    }
    4.86 +
    4.87 +    put_domain(d);
    4.88 +    return 0;
    4.89 +}
    4.90 +
    4.91 +long do_memory_op(unsigned long cmd, void *arg)
    4.92  {
    4.93      struct domain *d;
    4.94 -    int rc, start_extent, op, flags = 0, preempted = 0;
    4.95 +    int rc, op, flags = 0, preempted = 0;
    4.96 +    unsigned long start_extent, progress;
    4.97      struct xen_memory_reservation reservation;
    4.98      domid_t domid;
    4.99  
   4.100 @@ -212,6 +276,10 @@ long do_memory_op(int cmd, void *arg)
   4.101          if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
   4.102              return -EFAULT;
   4.103  
   4.104 +        /* Is size too large for us to encode a continuation? */
   4.105 +        if ( reservation.nr_extents > (ULONG_MAX >> START_EXTENT_SHIFT) )
   4.106 +            return -EINVAL;
   4.107 +
   4.108          start_extent = cmd >> START_EXTENT_SHIFT;
   4.109          if ( unlikely(start_extent > reservation.nr_extents) )
   4.110              return -EINVAL;
   4.111 @@ -302,6 +370,16 @@ long do_memory_op(int cmd, void *arg)
   4.112  
   4.113          break;
   4.114  
   4.115 +    case XENMEM_translate_gpfn_list:
   4.116 +        progress = cmd >> START_EXTENT_SHIFT;
   4.117 +        rc = translate_gpfn_list(arg, &progress);
   4.118 +        if ( rc == -EAGAIN )
   4.119 +            return hypercall2_create_continuation(
   4.120 +                __HYPERVISOR_memory_op,
   4.121 +                op | (progress << START_EXTENT_SHIFT),
   4.122 +                arg);
   4.123 +        break;
   4.124 +
   4.125      default:
   4.126          rc = arch_memory_op(op, arg);
   4.127          break;
     5.1 --- a/xen/include/public/memory.h	Thu Feb 16 17:37:21 2006 +0100
     5.2 +++ b/xen/include/public/memory.h	Thu Feb 16 18:52:06 2006 +0100
     5.3 @@ -101,7 +101,7 @@ typedef struct xen_machphys_mfn_list {
     5.4   */
     5.5  #define XENMEM_reserved_phys_area   7
     5.6  typedef struct xen_reserved_phys_area {
     5.7 -    /* Which request to report about? */
     5.8 +    /* Which domain to report about? */
     5.9      domid_t domid;
    5.10  
    5.11      /*
    5.12 @@ -114,6 +114,28 @@ typedef struct xen_reserved_phys_area {
    5.13      unsigned long first_gpfn, nr_gpfns;
    5.14  } xen_reserved_phys_area_t;
    5.15  
    5.16 +/*
    5.17 + * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
    5.18 + * code on failure. This call only works for auto-translated guests.
    5.19 + */
    5.20 +#define XENMEM_translate_gpfn_list  8
    5.21 +typedef struct xen_translate_gpfn_list {
    5.22 +    /* Which domain to translate for? */
    5.23 +    domid_t domid;
    5.24 +
    5.25 +    /* Length of list. */
    5.26 +    unsigned long nr_gpfns;
    5.27 +
    5.28 +    /* List of GPFNs to translate. */
    5.29 +    unsigned long *gpfn_list;
    5.30 +
    5.31 +    /*
    5.32 +     * Output list to contain MFN translations. May be the same as the input
    5.33 +     * list (in which case each input GPFN is overwritten with the output MFN).
    5.34 +     */
    5.35 +    unsigned long *mfn_list;
    5.36 +} xen_translate_gpfn_list_t;
    5.37 +
    5.38  #endif /* __XEN_PUBLIC_MEMORY_H__ */
    5.39  
    5.40  /*