ia64/xen-unstable
changeset 8871: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>
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 + if ( copy_from_user(&op, uop, sizeof(op)) ) 4.36 + return -EFAULT; 4.37 + 4.38 + /* Is size too large for us to encode a continuation? */ 4.39 + if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) ) 4.40 + return -EINVAL; 4.41 + 4.42 + if ( !array_access_ok(op.gpfn_list, op.nr_gpfns, sizeof(*op.gpfn_list)) || 4.43 + !array_access_ok(op.mfn_list, op.nr_gpfns, sizeof(*op.mfn_list)) ) 4.44 + return -EFAULT; 4.45 + 4.46 + if ( op.domid == DOMID_SELF ) 4.47 + op.domid = current->domain->domain_id; 4.48 + else if ( !IS_PRIV(current->domain) ) 4.49 + return -EPERM; 4.50 + 4.51 + if ( (d = find_domain_by_id(op.domid)) == NULL ) 4.52 + return -ESRCH; 4.53 4.54 -long do_memory_op(int cmd, void *arg) 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 /*