# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 0d10fac284274733fe67cf5384fe032508c13766
# Parent 2b0078f771cc1152a003721e20c3972fe7cf6ea8
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@xxxxxxxxxxxxx>
diff -r 2b0078f771cc -r 0d10fac28427 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Thu Feb 16 16:37:21 2006
+++ b/tools/libxc/xc_domain.c Thu Feb 16 17:52:06 2006
@@ -326,6 +326,53 @@
return err;
}
+int xc_domain_memory_populate_physmap(int xc_handle,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int address_bits,
+ unsigned long *extent_start)
+{
+ int err;
+ struct xen_memory_reservation reservation = {
+ .extent_start = extent_start,
+ .nr_extents = nr_extents,
+ .extent_order = extent_order,
+ .address_bits = address_bits,
+ .domid = domid
+ };
+
+ err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
+ if ( err == nr_extents )
+ return 0;
+
+ if ( err > 0 )
+ {
+ fprintf(stderr,"Failed deallocation for dom %d: %ld pages order %d\n",
+ domid, nr_extents, extent_order);
+ errno = EBUSY;
+ err = -1;
+ }
+
+ return err;
+}
+
+int xc_domain_translate_gpfn_list(int xc_handle,
+ uint32_t domid,
+ unsigned long nr_gpfns,
+ unsigned long *gpfn_list,
+ unsigned long *mfn_list)
+{
+ struct xen_translate_gpfn_list op = {
+ .domid = domid,
+ .nr_gpfns = nr_gpfns,
+ .gpfn_list = gpfn_list,
+ .mfn_list = mfn_list
+ };
+
+ return xc_memory_op(xc_handle, XENMEM_translate_gpfn_list, &op);
+}
+
int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
{
DECLARE_DOM0_OP;
diff -r 2b0078f771cc -r 0d10fac28427 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Thu Feb 16 16:37:21 2006
+++ b/tools/libxc/xc_private.c Thu Feb 16 17:52:06 2006
@@ -191,6 +191,7 @@
DECLARE_HYPERCALL;
struct xen_memory_reservation *reservation = arg;
struct xen_machphys_mfn_list *xmml = arg;
+ struct xen_translate_gpfn_list *trans = arg;
long ret = -EINVAL;
hypercall.op = __HYPERVISOR_memory_op;
@@ -234,6 +235,26 @@
if ( mlock(arg, sizeof(struct xen_reserved_phys_area)) )
{
PERROR("Could not mlock");
+ goto out1;
+ }
+ break;
+ case XENMEM_translate_gpfn_list:
+ if ( mlock(trans, sizeof(*trans)) != 0 )
+ {
+ PERROR("Could not mlock");
+ goto out1;
+ }
+ if ( mlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long)) != 0 )
+ {
+ PERROR("Could not mlock");
+ safe_munlock(trans, sizeof(*trans));
+ goto out1;
+ }
+ if ( mlock(trans->mfn_list, trans->nr_gpfns * sizeof(long)) != 0 )
+ {
+ PERROR("Could not mlock");
+ safe_munlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long));
+ safe_munlock(trans, sizeof(*trans));
goto out1;
}
break;
@@ -258,6 +279,11 @@
break;
case XENMEM_reserved_phys_area:
safe_munlock(arg, sizeof(struct xen_reserved_phys_area));
+ break;
+ case XENMEM_translate_gpfn_list:
+ safe_munlock(trans->mfn_list, trans->nr_gpfns * sizeof(long));
+ safe_munlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long));
+ safe_munlock(trans, sizeof(*trans));
break;
}
diff -r 2b0078f771cc -r 0d10fac28427 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu Feb 16 16:37:21 2006
+++ b/tools/libxc/xenctrl.h Thu Feb 16 17:52:06 2006
@@ -373,6 +373,19 @@
unsigned int extent_order,
unsigned long *extent_start);
+int xc_domain_memory_populate_physmap(int xc_handle,
+ uint32_t domid,
+ unsigned long nr_extents,
+ unsigned int extent_order,
+ unsigned int address_bits,
+ unsigned long *extent_start);
+
+int xc_domain_translate_gpfn_list(int xc_handle,
+ uint32_t domid,
+ unsigned long nr_gpfns,
+ unsigned long *gpfn_list,
+ unsigned long *mfn_list);
+
int xc_domain_ioport_permission(int xc_handle,
uint32_t domid,
uint32_t first_port,
diff -r 2b0078f771cc -r 0d10fac28427 xen/common/memory.c
--- a/xen/common/memory.c Thu Feb 16 16:37:21 2006
+++ b/xen/common/memory.c Thu Feb 16 17:52:06 2006
@@ -19,6 +19,13 @@
#include <asm/current.h>
#include <asm/hardirq.h>
#include <public/memory.h>
+
+/*
+ * To allow safe resume of do_memory_op() after preemption, we need to know
+ * at what point in the page list to resume. For this purpose I steal the
+ * high-order bits of the @cmd parameter, which are otherwise unused and zero.
+ */
+#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
static long
increase_reservation(
@@ -188,17 +195,74 @@
return nr_extents;
}
-/*
- * To allow safe resume of do_memory_op() after preemption, we need to know
- * at what point in the page list to resume. For this purpose I steal the
- * high-order bits of the @cmd parameter, which are otherwise unused and zero.
- */
-#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
-
-long do_memory_op(int cmd, void *arg)
-{
+static long
+translate_gpfn_list(
+ struct xen_translate_gpfn_list *uop, unsigned long *progress)
+{
+ struct xen_translate_gpfn_list op;
+ unsigned long i, gpfn, mfn;
struct domain *d;
- int rc, start_extent, op, flags = 0, preempted = 0;
+
+ if ( copy_from_user(&op, uop, sizeof(op)) )
+ return -EFAULT;
+
+ /* Is size too large for us to encode a continuation? */
+ if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) )
+ return -EINVAL;
+
+ if ( !array_access_ok(op.gpfn_list, op.nr_gpfns, sizeof(*op.gpfn_list)) ||
+ !array_access_ok(op.mfn_list, op.nr_gpfns, sizeof(*op.mfn_list)) )
+ return -EFAULT;
+
+ if ( op.domid == DOMID_SELF )
+ op.domid = current->domain->domain_id;
+ else if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if ( (d = find_domain_by_id(op.domid)) == NULL )
+ return -ESRCH;
+
+ if ( !shadow_mode_translate(d) )
+ {
+ put_domain(d);
+ return -EINVAL;
+ }
+
+ for ( i = *progress; i < op.nr_gpfns; i++ )
+ {
+ if ( hypercall_preempt_check() )
+ {
+ put_domain(d);
+ *progress = i;
+ return -EAGAIN;
+ }
+
+ if ( unlikely(__copy_from_user(&gpfn, &op.gpfn_list[i],
+ sizeof(gpfn))) )
+ {
+ put_domain(d);
+ return -EFAULT;
+ }
+
+ mfn = gmfn_to_mfn(d, gpfn);
+
+ if ( unlikely(__copy_to_user(&op.mfn_list[i], &mfn,
+ sizeof(mfn))) )
+ {
+ put_domain(d);
+ return -EFAULT;
+ }
+ }
+
+ put_domain(d);
+ return 0;
+}
+
+long do_memory_op(unsigned long cmd, void *arg)
+{
+ struct domain *d;
+ int rc, op, flags = 0, preempted = 0;
+ unsigned long start_extent, progress;
struct xen_memory_reservation reservation;
domid_t domid;
@@ -211,6 +275,10 @@
case XENMEM_populate_physmap:
if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
return -EFAULT;
+
+ /* Is size too large for us to encode a continuation? */
+ if ( reservation.nr_extents > (ULONG_MAX >> START_EXTENT_SHIFT) )
+ return -EINVAL;
start_extent = cmd >> START_EXTENT_SHIFT;
if ( unlikely(start_extent > reservation.nr_extents) )
@@ -302,6 +370,16 @@
break;
+ case XENMEM_translate_gpfn_list:
+ progress = cmd >> START_EXTENT_SHIFT;
+ rc = translate_gpfn_list(arg, &progress);
+ if ( rc == -EAGAIN )
+ return hypercall2_create_continuation(
+ __HYPERVISOR_memory_op,
+ op | (progress << START_EXTENT_SHIFT),
+ arg);
+ break;
+
default:
rc = arch_memory_op(op, arg);
break;
diff -r 2b0078f771cc -r 0d10fac28427 xen/include/public/memory.h
--- a/xen/include/public/memory.h Thu Feb 16 16:37:21 2006
+++ b/xen/include/public/memory.h Thu Feb 16 17:52:06 2006
@@ -101,7 +101,7 @@
*/
#define XENMEM_reserved_phys_area 7
typedef struct xen_reserved_phys_area {
- /* Which request to report about? */
+ /* Which domain to report about? */
domid_t domid;
/*
@@ -114,6 +114,28 @@
unsigned long first_gpfn, nr_gpfns;
} xen_reserved_phys_area_t;
+/*
+ * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
+ * code on failure. This call only works for auto-translated guests.
+ */
+#define XENMEM_translate_gpfn_list 8
+typedef struct xen_translate_gpfn_list {
+ /* Which domain to translate for? */
+ domid_t domid;
+
+ /* Length of list. */
+ unsigned long nr_gpfns;
+
+ /* List of GPFNs to translate. */
+ unsigned long *gpfn_list;
+
+ /*
+ * Output list to contain MFN translations. May be the same as the input
+ * list (in which case each input GPFN is overwritten with the output MFN).
+ */
+ unsigned long *mfn_list;
+} xen_translate_gpfn_list_t;
+
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|