Hi,

these are the patches to port xencomm on ia64.  This is just an RFC.  I have 
to clean-up the code so that it could be shared between ia64 and ppc.

I have added the xencomm_inline feature which makes (IMHO) hcall.c more 
readable and safer (particularly at boot time).  Wether or not xencomm_mini 
should be deprecated is a question for ppc people (xencomm_mini is buggy: the 
area should be reserved as an array of struct xencomm_mini for alignment).

I have also fixed a few bugs in guest_access.h

Many files should be shared between ia64 and ppc.
In xen:
* guest_access.h should be the same.  I will propose to put as 
include/xen/xencomm_access.h
* usercopy.c sould be shared too.  The paddr_to_maddr() function should be 
defined in arch files as xencomm_paddr_to_maddr.  I will propose to put this 
file into xen/common/xencomm.c

In linux:
* drivers/xen/core/xencomm.c should be shared.  We just need to agree on
xen_pa().  On linux-ia64, __pa() doesn't work for this use.  asm/xencomm.h 
should define this macro/function.
* hcall.c should be shared because it is the biggest and the most boring file.  
This won't be that easy, but it will try to made a proposal soon.

Tristan.
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/Kconfig
--- a/linux-2.6-xen-sparse/arch/ia64/Kconfig	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig	Fri Aug 18 14:26:09 2006 +0200
@@ -530,6 +530,9 @@ config XEN_REBOOT
 
 config XEN_SMPBOOT
 	default n
+
+config XEN_XENCOMM
+	default y
 endif
 
 source "drivers/xen/Kconfig"
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c	Fri Aug 18 14:26:09 2006 +0200
@@ -433,6 +433,9 @@ setup_arch (char **cmdline_p)
 
 #ifdef CONFIG_XEN
 	if (is_running_on_xen()) {
+		extern unsigned long kernel_start_pa;
+
+		kernel_start_pa = KERNEL_START - ia64_tpa (KERNEL_START);
 		setup_xen_features();
 		/* Register a call for panic conditions. */
 		notifier_chain_register(&panic_notifier_list, &xen_panic_block);
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/Makefile
--- a/linux-2.6-xen-sparse/arch/ia64/xen/Makefile	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/Makefile	Fri Aug 18 14:26:09 2006 +0200
@@ -3,6 +3,6 @@
 #
 
 obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \
-	 hypervisor.o pci-dma-xen.o util.o
+	 hypervisor.o pci-dma-xen.o util.o hcall.o
 
 pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c	Fri Aug 18 14:26:09 2006 +0200
@@ -371,8 +371,6 @@ int
 int
 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
 {
-	__u64 va1, va2, pa1, pa2;
-
 	if (cmd == GNTTABOP_map_grant_ref) {
 		unsigned int i;
 		for (i = 0; i < count; i++) {
@@ -380,29 +378,7 @@ HYPERVISOR_grant_table_op(unsigned int c
 				(struct gnttab_map_grant_ref*)uop + i);
 		}
 	}
-	va1 = (__u64)uop & PAGE_MASK;
-	pa1 = pa2 = 0;
-	if ((REGION_NUMBER(va1) == 5) &&
-	    ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) {
-		pa1 = ia64_tpa(va1);
-		if (cmd <= GNTTABOP_transfer) {
-			static uint32_t uop_size[GNTTABOP_transfer + 1] = {
-				sizeof(struct gnttab_map_grant_ref),
-				sizeof(struct gnttab_unmap_grant_ref),
-				sizeof(struct gnttab_setup_table),
-				sizeof(struct gnttab_dump_table),
-				sizeof(struct gnttab_transfer),
-			};
-			va2 = (__u64)uop + (uop_size[cmd] * count) - 1;
-			va2 &= PAGE_MASK;
-			if (va1 != va2) {
-				/* maximum size of uop is 2pages */
-				BUG_ON(va2 > va1 + PAGE_SIZE);
-				pa2 = ia64_tpa(va2);
-			}
-		}
-	}
-	return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2);
+	return ____HYPERVISOR_grant_table_op(cmd, uop, count);
 }
 EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
 
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig	Fri Aug 18 14:26:09 2006 +0200
@@ -257,4 +257,7 @@ config XEN_SMPBOOT
 	default y
 	depends on SMP
 
+config XEN_XENCOMM
+	bool
+	default n
 endif
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/core/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile	Fri Aug 18 14:26:09 2006 +0200
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SKBUFF)	+= skbuff.o
 obj-$(CONFIG_XEN_SKBUFF)	+= skbuff.o
 obj-$(CONFIG_XEN_REBOOT)	+= reboot.o
 obj-$(CONFIG_XEN_SMPBOOT)	+= smpboot.o
+obj-$(CONFIG_XEN_XENCOMM)       += xencomm.o
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Fri Aug 18 14:26:09 2006 +0200
@@ -34,6 +34,8 @@
 
 static struct proc_dir_entry *privcmd_intf;
 static struct proc_dir_entry *capabilities_intf;
+
+extern int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall);
 
 #define NR_HYPERCALLS 64
 static DECLARE_BITMAP(hypercall_permission_map, NR_HYPERCALLS);
@@ -92,18 +94,7 @@ static int privcmd_ioctl(struct inode *i
 				: "r8", "r10", "memory" );
 		}
 #elif defined (__ia64__)
-		__asm__ __volatile__ (
-			";; mov r14=%2; mov r15=%3; "
-			"mov r16=%4; mov r17=%5; mov r18=%6;"
-			"mov r2=%1; break 0x1000;; mov %0=r8 ;;"
-			: "=r" (ret)
-			: "r" (hypercall.op),
-			"r" (hypercall.arg[0]),
-			"r" (hypercall.arg[1]),
-			"r" (hypercall.arg[2]),
-			"r" (hypercall.arg[3]),
-			"r" (hypercall.arg[4])
-			: "r14","r15","r16","r17","r18","r2","r8","memory");
+		ret = xencomm_privcmd_hypercall (&hypercall);
 #endif
 	}
 	break;
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h	Fri Aug 18 14:26:09 2006 +0200
@@ -157,19 +157,13 @@
 	(type)__res;                                            \
 })
 
-static inline int
-HYPERVISOR_sched_op_compat(
-    int cmd, unsigned long arg)
-{
-	return _hypercall2(int, sched_op_compat, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_sched_op(
-	int cmd, void *arg)
-{
-	return _hypercall2(int, sched_op, cmd, arg);
-}
+#if 0
+extern int
+HYPERVISOR_sched_op_compat(int cmd, unsigned long arg);
+#endif
+
+extern int
+HYPERVISOR_sched_op(int cmd, void *arg);
 
 static inline long
 HYPERVISOR_set_timer_op(
@@ -180,29 +174,16 @@ HYPERVISOR_set_timer_op(
     return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
 }
 
-static inline int
-HYPERVISOR_dom0_op(
-    dom0_op_t *dom0_op)
-{
-    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
-    return _hypercall1(int, dom0_op, dom0_op);
-}
-
-static inline int
-HYPERVISOR_multicall(
-    void *call_list, int nr_calls)
-{
-    return _hypercall2(int, multicall, call_list, nr_calls);
-}
+extern int
+HYPERVISOR_dom0_op(dom0_op_t *dom0_op);
+
+extern int
+HYPERVISOR_multicall(multicall_entry_t *call_list, int nr_calls);
 
 //XXX xen/ia64 copy_from_guest() is broken.
 //    This is a temporal work around until it is fixed.
-static inline int
-____HYPERVISOR_memory_op(
-    unsigned int cmd, void *arg)
-{
-    return _hypercall2(int, memory_op, cmd, arg);
-}
+extern int
+____HYPERVISOR_memory_op(unsigned int cmd, void *arg);
 
 #include <xen/interface/memory.h>
 int ia64_xenmem_reservation_op(unsigned long op,
@@ -223,81 +204,33 @@ HYPERVISOR_memory_op(
     /* NOTREACHED */
 }
 
-static inline int
-HYPERVISOR_event_channel_op(
-    int cmd, void *arg)
-{
-    int rc = _hypercall2(int, event_channel_op, cmd, arg);
-    if (unlikely(rc == -ENOSYS)) {
-        struct evtchn_op op;
-        op.cmd = cmd;
-        memcpy(&op.u, arg, sizeof(op.u));
-        rc = _hypercall1(int, event_channel_op_compat, &op);
-    }
-    return rc;
-}
-
-static inline int
-HYPERVISOR_acm_op(
-	unsigned int cmd, void *arg)
-{
-    return _hypercall2(int, acm_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_xen_version(
-    int cmd, void *arg)
-{
-    return _hypercall2(int, xen_version, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_console_io(
-    int cmd, int count, char *str)
-{
-    return _hypercall3(int, console_io, cmd, count, str);
-}
-
-static inline int
-HYPERVISOR_physdev_op(
-    int cmd, void *arg)
-{
-    int rc = _hypercall2(int, physdev_op, cmd, arg);
-    if (unlikely(rc == -ENOSYS)) {
-        struct physdev_op op;
-        op.cmd = cmd;
-        memcpy(&op.u, arg, sizeof(op.u));
-        rc = _hypercall1(int, physdev_op_compat, &op);
-    }
-    return rc;
-}
+extern int
+HYPERVISOR_event_channel_op(int cmd, void *arg);
+
+extern int
+HYPERVISOR_acm_op(unsigned int cmd, void *arg);
+
+extern int
+HYPERVISOR_xen_version(int cmd, void *arg);
+
+extern int
+HYPERVISOR_console_io(int cmd, int count, char *str);
+
+extern int
+HYPERVISOR_physdev_op(int cmd, void *arg);
 
 //XXX __HYPERVISOR_grant_table_op is used for this hypercall constant.
-static inline int
-____HYPERVISOR_grant_table_op(
-    unsigned int cmd, void *uop, unsigned int count,
-    unsigned long pa1, unsigned long pa2)
-{
-    return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2);
-}
+extern int
+____HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+//    unsigned long pa1, unsigned long pa2);
 
 int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
 
-static inline int
-HYPERVISOR_vcpu_op(
-	int cmd, int vcpuid, void *extra_args)
-{
-    return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
-}
+extern int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
 
 extern int HYPERVISOR_suspend(unsigned long srec);
 
-static inline int
-HYPERVISOR_callback_op(
-	int cmd, void *arg)
-{
-	return _hypercall2(int, callback_op, cmd, arg);
-}
+extern int HYPERVISOR_callback_op(int cmd, void *arg);
 
 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
 static inline void exit_idle(void) {}
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Fri Aug 18 14:26:09 2006 +0200
@@ -70,9 +70,6 @@ HYPERVISOR_yield(
 {
 	int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
 
-	if (rc == -ENOSYS)
-		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
-
 	return rc;
 }
 
@@ -81,9 +78,6 @@ HYPERVISOR_block(
 	void)
 {
 	int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
-
-	if (rc == -ENOSYS)
-		rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
 
 	return rc;
 }
@@ -97,9 +91,6 @@ HYPERVISOR_shutdown(
 	};
 
 	int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
-
-	if (rc == -ENOSYS)
-		rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
 
 	return rc;
 }
@@ -117,8 +108,6 @@ HYPERVISOR_poll(
 
 	set_xen_guest_handle(sched_poll.ports, ports);
 	rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
-	if (rc == -ENOSYS)
-		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
 
 	return rc;
 }
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/hcall.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hcall.c	Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,669 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/dom0_ops.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/xencomm.h>
+#include <xen/interface/version.h>
+#include <xen/interface/sched.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/callback.h>
+#include <xen/interface/acm_ops.h>
+#include <xen/public/privcmd.h>
+#include <asm/hypercall.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <xen/xencomm.h>
+
+#ifdef __ia64__
+extern unsigned long xen_pa(void *ptr);
+#endif
+
+#define xen_guest_handle(hnd)  ((hnd).p)
+
+/* Xencomm notes:
+ *
+ * Some hypercalls are made before the memory subsystem is up, so instead of
+ * calling xencomm_create(), we allocate XENCOMM_MINI_AREA bytes from the stack
+ * to hold the xencomm descriptor.
+ *
+ * In general, we need a xencomm descriptor to cover the top-level data
+ * structure (e.g. the dom0 op), plus another for every embedded pointer to
+ * another data structure (i.e. for every GUEST_HANDLE).
+ */
+
+int HYPERVISOR_console_io(int cmd, int count, char *str)
+{
+	struct xencomm_desc *desc;
+	int rc;
+
+	desc = xencomm_create_inline (str, count);
+
+	rc = _hypercall3(int, console_io, cmd, count, desc);
+
+	return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_console_io);
+
+int HYPERVISOR_event_channel_op(int cmd, void *op)
+{
+	struct xencomm_desc *desc;
+	int rc;
+
+	desc = xencomm_create_inline(op, sizeof(evtchn_op_t));
+
+	rc = _hypercall2(int, event_channel_op, cmd, desc);
+
+	return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_event_channel_op);
+
+int HYPERVISOR_xen_version(int cmd, void *arg)
+{
+	struct xencomm_desc *desc;
+	int argsize;
+	int rc;
+
+	switch (cmd) {
+	case XENVER_version:
+		/* do not actually pass an argument */
+		return _hypercall2(int, xen_version, cmd, 0);
+	case XENVER_extraversion:
+		argsize = sizeof(xen_extraversion_t);
+		break;
+	case XENVER_compile_info:
+		argsize = sizeof(xen_compile_info_t);
+		break;
+	case XENVER_capabilities:
+		argsize = sizeof(xen_capabilities_info_t);
+		break;
+	case XENVER_changeset:
+		argsize = sizeof(xen_changeset_info_t);
+		break;
+	case XENVER_platform_parameters:
+		argsize = sizeof(xen_platform_parameters_t);
+		break;
+	case XENVER_pagesize:
+		argsize = (arg == NULL) ? 0 : sizeof(void *);
+		break;
+	case XENVER_get_features:
+		argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
+		break;
+	default:
+		printk("%s: unknown version cmd %d\n", __func__, cmd);
+		return -ENOSYS;
+	}
+
+	desc = xencomm_create_inline(arg, argsize);
+
+	rc = _hypercall2(int, xen_version, cmd, desc);
+
+	return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_xen_version);
+
+int HYPERVISOR_physdev_op(int cmd, void *op)
+{
+	struct xencomm_desc *desc;
+	int rc;
+
+	desc = xencomm_create_inline(op, sizeof(physdev_op_t));
+
+	rc = _hypercall2(int, physdev_op, cmd, desc);
+
+	return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_physdev_op);
+
+int ____HYPERVISOR_grant_table_op(unsigned int cmd, void *op,
+				  unsigned int count)
+{
+	struct xencomm_desc *desc;
+	struct xencomm_desc *frame_list;
+	long rc;
+	int argsize;
+
+	switch (cmd) {
+	case GNTTABOP_map_grant_ref:
+		argsize = sizeof(struct gnttab_map_grant_ref);
+		break;
+	case GNTTABOP_unmap_grant_ref:
+		argsize = sizeof(struct gnttab_unmap_grant_ref);
+		break;
+	case GNTTABOP_setup_table:
+	{
+		struct gnttab_setup_table *setup = op;
+		argsize = sizeof(struct gnttab_setup_table);
+
+		frame_list = xencomm_create_inline
+			(xen_guest_handle(setup->frame_list),
+			 setup->nr_frames 
+			 * sizeof(*xen_guest_handle(setup->frame_list)));
+
+		set_xen_guest_handle(setup->frame_list, (void *)frame_list);
+		break;
+	}
+	case GNTTABOP_dump_table:
+		argsize = sizeof(struct gnttab_dump_table);
+		break;
+	case GNTTABOP_transfer:
+		argsize = sizeof(struct gnttab_transfer);
+		break;
+	default:
+		printk("%s: unknown grant table op %d\n", __func__, cmd);
+		return -ENOSYS;
+	}
+
+	desc = xencomm_create_inline(op, count * argsize);
+
+	rc = _hypercall3(int, grant_table_op, cmd, desc, count);
+
+	return rc;
+}
+/*EXPORT_SYMBOL(HYPERVISOR_grant_table_op);*/
+
+int HYPERVISOR_sched_op(int cmd, void *arg)
+{
+	int rc;
+	struct xencomm_desc *desc;
+	ulong argsize;
+
+	switch (cmd) {
+	case SCHEDOP_yield:
+	case SCHEDOP_block:
+	        return _hypercall2(int, sched_op, cmd, 0);
+		break;
+
+	case SCHEDOP_shutdown:
+		argsize = sizeof(sched_shutdown_t);
+		break;
+	case SCHEDOP_poll:
+		argsize = sizeof(sched_poll_t);
+		break;
+	case SCHEDOP_remote_shutdown:
+		argsize = sizeof(sched_remote_shutdown_t);
+		break;
+	default:
+		printk("%s: unknown sched op %d\n", __func__, cmd);
+		return -ENOSYS;
+	}
+	
+	desc = xencomm_create_inline(arg, argsize);
+
+	rc = _hypercall2(int, sched_op, cmd, desc);
+
+	return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_sched_op);
+
+int HYPERVISOR_multicall(multicall_entry_t *call_list, int nr_calls)
+{
+	int i;
+	multicall_entry_t *mce;
+	struct xencomm_desc *desc;
+
+	for (i = 0; i < nr_calls; i++) {
+		mce = call_list + i;
+
+		switch (mce->op) {
+		case __HYPERVISOR_update_va_mapping:
+		case __HYPERVISOR_mmu_update:
+			/* No-op on ia64.  */
+			break;
+		case __HYPERVISOR_memory_op:
+		default:
+			printk("%s: unhandled multicall op entry op %lu from %p\n",
+			       __func__, mce->op, __builtin_return_address (0));
+			return -ENOSYS;
+		}
+	}
+
+	desc = xencomm_create_inline
+		(call_list, nr_calls * sizeof(multicall_entry_t));
+
+	return _hypercall2(int, multicall, desc, nr_calls);
+}
+EXPORT_SYMBOL(HYPERVISOR_multicall);
+
+int
+HYPERVISOR_callback_op(
+	int cmd, void *arg)
+{
+	int rc;
+	struct xencomm_desc *desc;
+
+	switch (cmd)
+	{
+	case CALLBACKOP_register:
+		desc = xencomm_create_inline
+			(arg, sizeof(callback_register_t));
+		break;
+	case CALLBACKOP_unregister:
+		desc = xencomm_create_inline
+			(arg, sizeof(callback_unregister_t));
+		break;
+	default:
+		printk("%s: unknown callback op %d\n", __func__, cmd);
+		return -ENOSYS;
+	}
+
+	rc = _hypercall2(int, callback_op, cmd, desc);
+
+	return rc;
+}
+
+static void xencommize_memory_reservation (xen_memory_reservation_t *mop)
+{
+	if (xen_guest_handle(mop->extent_start)) {
+		struct xencomm_desc *desc;
+		void * addr;
+
+		addr = xen_guest_handle(mop->extent_start);
+		desc = xencomm_create_inline
+			(addr,
+			 mop->nr_extents *
+			 sizeof(*xen_guest_handle(mop->extent_start)));
+		set_xen_guest_handle(mop->extent_start, (void *)desc);
+	}
+}
+
+int ____HYPERVISOR_memory_op(unsigned int cmd, void *arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case XENMEM_increase_reservation:
+	case XENMEM_decrease_reservation:
+	case XENMEM_populate_physmap:
+	{
+		struct xencomm_desc *desc;
+
+		desc = xencomm_create_inline
+			(arg, sizeof(xen_memory_reservation_t));
+
+		xencommize_memory_reservation
+			((xen_memory_reservation_t *)arg);
+
+		ret = _hypercall2(int, memory_op, cmd, desc);
+	}
+	break;
+		
+	case XENMEM_maximum_ram_page:
+		/* arg is NULL so we can call thru here */
+		ret = _hypercall2(int, memory_op, cmd, NULL);
+
+		break;
+
+	case XENMEM_exchange:
+	{
+		struct xencomm_desc *desc;
+
+		desc = xencomm_create_inline 
+			(arg, sizeof (xen_memory_exchange_t));
+
+		xencommize_memory_reservation
+			(&((xen_memory_exchange_t *)arg)->in);
+		xencommize_memory_reservation
+			(&((xen_memory_exchange_t *)arg)->out);
+
+		ret = _hypercall2(int, memory_op, cmd, desc);
+	}
+	break;
+
+	default:
+		printk("%s: unknown memory op %d\n", __func__, cmd);
+		ret = -ENOSYS;
+	}
+	return ret;
+
+}
+/* EXPORT_SYMBOL(HYPERVISOR_memory_op);*/
+
+static int xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall)
+{
+	dom0_op_t kern_op;
+	dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0];
+	struct xencomm_desc *op_desc;
+	struct xencomm_desc *desc = NULL;
+	int ret = 0;
+
+	if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t)))
+		return -EFAULT;
+
+	if (kern_op.interface_version != DOM0_INTERFACE_VERSION)
+		return -EACCES;
+
+	op_desc = xencomm_create_inline (&kern_op, sizeof(dom0_op_t));
+
+	switch (kern_op.cmd) {
+	case DOM0_GETMEMLIST:
+	{
+		unsigned long nr_pages = kern_op.u.getmemlist.max_pfns;
+#ifdef __ia64__
+		/* Xen/ia64 pass first_page and nr_pages in max_pfns!  */
+		nr_pages &= 0xffffffff;
+#endif
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.getmemlist.buffer),
+			nr_pages * sizeof(unsigned long),
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.getmemlist.buffer,
+				     (void *)xen_pa(desc));
+		break;
+	}
+	case DOM0_SETVCPUCONTEXT:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.setvcpucontext.ctxt),
+			sizeof(vcpu_guest_context_t),
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.setvcpucontext.ctxt,
+				     (void *)xen_pa(desc));
+		break;
+	case DOM0_READCONSOLE:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.readconsole.buffer),
+			kern_op.u.readconsole.count,
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.readconsole.buffer,
+				     (void *)xen_pa(desc));
+		break;
+	case DOM0_GETPAGEFRAMEINFO2:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.getpageframeinfo2.array),
+			kern_op.u.getpageframeinfo2.num,
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
+				     (void *)xen_pa(desc));
+		break;
+	case DOM0_PERFCCONTROL:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.perfccontrol.desc),
+			kern_op.u.perfccontrol.nr_counters *
+			sizeof(dom0_perfc_desc_t),
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.perfccontrol.desc,
+				     (void *)xen_pa(desc));
+		break;
+	case DOM0_GETVCPUCONTEXT:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.getvcpucontext.ctxt),
+			sizeof(vcpu_guest_context_t),
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.getvcpucontext.ctxt,
+				     (void *)xen_pa(desc));
+		break;
+	case DOM0_GETDOMAININFOLIST:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
+			kern_op.u.getdomaininfolist.num_domains *
+			sizeof(dom0_getdomaininfo_t),
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
+				     (void *)xen_pa(desc));
+		break;
+	case DOM0_PHYSICAL_MEMORY_MAP:
+		ret = xencomm_create(
+			xen_guest_handle(kern_op.u.physical_memory_map.memory_map),
+			kern_op.u.physical_memory_map.nr_map_entries *
+			sizeof(struct dom0_memory_map_entry),
+			&desc, GFP_KERNEL);
+		set_xen_guest_handle(kern_op.u.physical_memory_map.memory_map,
+				     (void *)xen_pa(desc));
+		break;
+
+	case DOM0_SCHEDCTL:
+	case DOM0_ADJUSTDOM:
+	case DOM0_CREATEDOMAIN:
+	case DOM0_DESTROYDOMAIN:
+	case DOM0_PAUSEDOMAIN:
+	case DOM0_UNPAUSEDOMAIN:
+	case DOM0_GETDOMAININFO:
+	case DOM0_MSR:
+	case DOM0_SETTIME:
+	case DOM0_GETPAGEFRAMEINFO:
+	case DOM0_SETVCPUAFFINITY:
+	case DOM0_TBUFCONTROL:
+	case DOM0_PHYSINFO:
+	case DOM0_SCHED_ID:
+	case DOM0_SETDOMAINMAXMEM:
+	case DOM0_ADD_MEMTYPE:
+	case DOM0_DEL_MEMTYPE:
+	case DOM0_READ_MEMTYPE:
+	case DOM0_IOPORT_PERMISSION:
+	case DOM0_GETVCPUINFO:
+	case DOM0_PLATFORM_QUIRK:
+	case DOM0_MAX_VCPUS:
+	case DOM0_SETDOMAINHANDLE:
+	case DOM0_SETDEBUGGING:
+	case DOM0_DOMAIN_SETUP:
+		/* no munging needed */
+		break;
+
+	default:
+		printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
+		return -ENOSYS;
+	}
+
+	if (ret)
+		goto out; /* error mapping the nested pointer */
+
+	ret = _hypercall1(int, dom0_op, op_desc);
+
+	/* FIXME: should we restore the handle?  */
+	if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t)))
+		ret = -EFAULT;
+
+	if (desc)
+		xencomm_free(desc);
+out:
+	return ret;
+}
+
+static int xencomm_privcmd_acm_op(privcmd_hypercall_t *hypercall)
+{
+	int cmd = hypercall->arg[0];
+	void __user *arg = (void __user *)hypercall->arg[1];
+	struct xencomm_desc *op_desc;
+	struct xencomm_desc *desc = NULL;
+	int ret;
+
+	switch (cmd) {
+	case ACMOP_getssid:
+	{
+		struct acm_getssid kern_arg;
+
+		if (copy_from_user (&kern_arg, arg, sizeof (kern_arg)))
+			return -EFAULT;
+
+		op_desc = xencomm_create_inline (&kern_arg, sizeof(kern_arg));
+
+		ret = xencomm_create(xen_guest_handle(kern_arg.ssidbuf),
+				     kern_arg.ssidbuf_size,
+				     &desc, GFP_KERNEL);
+		if (ret)
+			return ret;
+
+		set_xen_guest_handle(kern_arg.ssidbuf, (void *)xen_pa(desc));
+
+		ret = _hypercall1(int, acm_op, op_desc);
+
+		xencomm_free (desc);
+
+		if (copy_to_user (arg, &kern_arg, sizeof (kern_arg)))
+			return -EFAULT;
+
+		return ret;
+	}
+	default:
+		printk("%s: unknown acm_op cmd %d\n", __func__, cmd);
+		return -ENOSYS;
+	}
+
+	return ret;
+}
+
+static int xencomm_privcmd_memory_op(privcmd_hypercall_t *hypercall)
+{
+	const unsigned long cmd = hypercall->arg[0];
+	int ret = 0;
+
+	switch (cmd) {
+	case XENMEM_increase_reservation:
+	case XENMEM_decrease_reservation:
+	{
+		xen_memory_reservation_t kern_op;
+		xen_memory_reservation_t __user *user_op;
+		struct xencomm_desc *desc = NULL;
+		struct xencomm_desc *desc_op;
+
+		user_op = (xen_memory_reservation_t __user *)hypercall->arg[1];
+		if (copy_from_user(&kern_op, user_op,
+				   sizeof(xen_memory_reservation_t)))
+			return -EFAULT;
+		desc_op = xencomm_create_inline (&kern_op, sizeof (kern_op));
+
+		if (xen_guest_handle(kern_op.extent_start)) {
+			void * addr;
+
+			addr = xen_guest_handle(kern_op.extent_start);
+			ret = xencomm_create
+				(addr,
+				 kern_op.nr_extents *
+				 sizeof(*xen_guest_handle
+					(kern_op.extent_start)),
+				 &desc, GFP_KERNEL);
+			if (ret)
+				return ret;
+			set_xen_guest_handle(kern_op.extent_start,
+					     (void *)xen_pa (desc));
+		}
+
+		ret = _hypercall2(int, memory_op, cmd, desc_op);
+
+		if (desc)
+			xencomm_free (desc);
+
+		if (ret != 0)
+			return ret;
+
+		if (copy_to_user(user_op, &kern_op,
+				 sizeof(xen_memory_reservation_t)))
+			return -EFAULT;
+
+		return ret;
+	}
+	default:
+		printk("%s: unknown memory op %lu\n", __func__, cmd);
+		ret = -ENOSYS;
+	}
+	return ret;
+}
+
+static int xencomm_privcmd_version(privcmd_hypercall_t *hypercall)
+{
+	int cmd = hypercall->arg[0];
+	void __user *arg = (void __user *)hypercall->arg[1];
+	struct xencomm_desc *desc;
+	size_t argsize;
+	int rc;
+
+	switch (cmd) {
+	case XENVER_version:
+		/* do not actually pass an argument */
+		return _hypercall2(int, xen_version, cmd, 0);
+	case XENVER_extraversion:
+		argsize = sizeof(xen_extraversion_t);
+		break;
+	case XENVER_compile_info:
+		argsize = sizeof(xen_compile_info_t);
+		break;
+	case XENVER_capabilities:
+		argsize = sizeof(xen_capabilities_info_t);
+		break;
+	case XENVER_changeset:
+		argsize = sizeof(xen_changeset_info_t);
+		break;
+	case XENVER_platform_parameters:
+		argsize = sizeof(xen_platform_parameters_t);
+		break;
+	case XENVER_pagesize:
+		argsize = (arg == NULL) ? 0 : sizeof(void *);
+		break;
+	case XENVER_get_features:
+		argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
+		break;
+
+	default:
+		printk("%s: unknown version op %d\n", __func__, cmd);
+		return -ENOSYS;
+	}
+
+	rc = xencomm_create(arg, argsize, &desc, GFP_KERNEL);
+	if (rc)
+		return rc;
+
+	rc = _hypercall2(int, xen_version, cmd, xen_pa (desc));
+
+	xencomm_free(desc);
+
+	return rc;
+}
+
+static int xencomm_privcmd_event_channel_op(privcmd_hypercall_t *hypercall)
+{
+	int cmd = hypercall->arg[0];
+	struct xencomm_desc *desc;
+	unsigned int argsize;
+	int ret;
+
+	switch (cmd) {
+	case EVTCHNOP_alloc_unbound:
+		argsize = sizeof(evtchn_alloc_unbound_t);
+		break;
+
+	case EVTCHNOP_status:
+		argsize = sizeof(evtchn_status_t);
+		break;
+
+	default:
+		printk("%s: unknown EVTCHNOP %d\n", __func__, cmd);
+		return -EINVAL;
+	}
+
+	ret = xencomm_create((void *)hypercall->arg[1], argsize,
+			     &desc, GFP_KERNEL);
+	if (ret)
+		return ret;
+
+	ret = _hypercall2(int, event_channel_op, cmd, xen_pa (desc));
+
+	xencomm_free(desc);
+	return ret;
+}
+
+int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall)
+{
+	switch (hypercall->op) {
+	case __HYPERVISOR_dom0_op:
+		return xencomm_privcmd_dom0_op(hypercall);
+        case __HYPERVISOR_acm_op:
+		return xencomm_privcmd_acm_op(hypercall);
+	case __HYPERVISOR_xen_version:
+		return xencomm_privcmd_version(hypercall);
+	case __HYPERVISOR_memory_op:
+		return xencomm_privcmd_memory_op(hypercall);
+	case __HYPERVISOR_event_channel_op:
+		return xencomm_privcmd_event_channel_op(hypercall);
+	default:
+		printk("%s: unknown hcall (%ld)\n", __func__, hypercall->op);
+		return -ENOSYS;
+		/* fallthru */
+		/* below are the hcalls we know will fail and its ok */
+	}
+}
+
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/core/xencomm.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/xencomm.c	Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <[EMAIL PROTECTED]>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <xen/xencomm.h>
+
+int xencomm_debug;
+
+#ifdef __ia64__
+unsigned long kernel_start_pa;
+
+unsigned long xen_pa(void *ptr)
+{
+	unsigned long addr = (unsigned long)ptr;
+
+	if (addr >= KERNEL_START
+	    && addr < (KERNEL_START + KERNEL_TR_PAGE_SIZE))
+		return addr - kernel_start_pa;
+	else
+		return __pa(addr);
+}
+#else
+#define xen_pa(addr) __pa(addr)
+#endif
+
+/* translate virtual address to physical address */
+static unsigned long __vaddr_to_paddr(unsigned long vaddr)
+{
+	struct page *page;
+	struct vm_area_struct *vma;
+
+	if (vaddr > TASK_SIZE) {
+		/* kernel address */
+		return xen_pa((void *)vaddr);
+	}
+
+	/* XXX double-check (lack of) locking */
+	vma = find_extend_vma(current->mm, vaddr);
+	if (!vma)
+		return ~0UL;
+
+	page = follow_page(vma, vaddr, 0);
+	if (!page)
+		return ~0UL;
+
+	return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+}
+
+/* for use with kernel buffers before __vaddr_to_paddr works (e.g. boot
+ * console) */
+static unsigned long __kern_paddr(unsigned long vaddr)
+{
+	return xen_pa((void *)vaddr);
+}
+
+static int __xencomm_init(struct xencomm_desc *desc, void *buffer,
+		unsigned long bytes, unsigned long (*to_phys)(unsigned long))
+{
+	unsigned long recorded = 0;
+	int i = 0;
+
+	BUG_ON((buffer == NULL) && (bytes > 0));
+
+	/* record the physical pages used */
+	if (buffer == NULL)
+		desc->nr_addrs = 0;
+
+	while ((recorded < bytes) && (i < desc->nr_addrs)) {
+		unsigned long vaddr = (unsigned long)buffer + recorded;
+		unsigned long paddr;
+		int offset;
+		int chunksz;
+
+		offset = vaddr % PAGE_SIZE; /* handle partial pages */
+		chunksz = min(PAGE_SIZE - offset, bytes - recorded);
+
+		paddr = to_phys(vaddr);
+		if (paddr == ~0UL) {
+			printk("%s: couldn't translate vaddr %lx\n",
+			       __func__, vaddr);
+			return -EINVAL;
+		}
+
+		desc->address[i++] = paddr;
+		recorded += chunksz;
+	}
+
+	if (recorded < bytes) {
+		printk("%s: could only translate %ld of %ld bytes\n",
+		       __func__, recorded, bytes);
+		return -ENOSPC;
+	}
+
+	/* mark remaining addresses invalid (just for safety) */
+	while (i < desc->nr_addrs)
+		desc->address[i++] = XENCOMM_INVALID;
+
+	desc->magic = XENCOMM_MAGIC;
+
+	return 0;
+}
+
+/* XXX use slab allocator */
+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask)
+{
+	struct xencomm_desc *desc;
+
+	/* XXX could we call this from irq context? */
+	desc = (struct xencomm_desc *)__get_free_page(gfp_mask);
+	if (desc == NULL)
+		return NULL;
+	desc->nr_addrs = (PAGE_SIZE - sizeof(struct xencomm_desc)) /
+			sizeof(*desc->address);
+
+	return desc;
+}
+
+void xencomm_free(struct xencomm_desc *desc)
+{
+	if (desc)
+		free_page((unsigned long)desc);
+}
+
+int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask)
+{
+	struct xencomm_desc *desc;
+	int rc;
+
+	if (xencomm_debug) {
+		if ((!buffer) || (bytes == 0)) {
+			printk(KERN_ERR "%s: NULL buffer\n", __func__);
+			return 0;
+		}
+		printk("%s: %p[%ld]\n", __func__, buffer, bytes);
+	}
+
+	if (buffer == NULL || bytes == 0) {
+		*ret = NULL;
+		return 0;
+	}
+
+	desc = xencomm_alloc(gfp_mask);
+	if (!desc) {
+		printk("%s failure from %p\n", "xencomm_alloc",
+		       __builtin_return_address (0));
+		return -ENOMEM;
+	}
+
+	rc = __xencomm_init(desc, buffer, bytes, __vaddr_to_paddr);
+	if (rc) {
+		printk("%s failure: %d\n", "__xencomm_init", rc);
+		xencomm_free(desc);
+		return rc;
+	}
+
+	*ret = desc;
+	return 0;
+}
+
+/* "mini" routines, for stack-based communications: */
+
+static void *__xencomm_alloc_mini(void *area, int arealen)
+{
+	unsigned long base = (unsigned long)area;
+	unsigned int pageoffset;
+
+	pageoffset = base % PAGE_SIZE;
+
+	/* we probably fit right at the front of area */
+	if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini)) {
+		return area;
+	}
+
+	/* if not, see if area is big enough to advance to the next page */
+	if ((arealen - pageoffset) >= sizeof(struct xencomm_mini))
+		return (void *)(base + pageoffset);
+
+	/* area was too small */
+	return NULL;
+}
+
+int xencomm_create_mini(void *area, int arealen, void *buffer,
+		unsigned long bytes, struct xencomm_desc **ret)
+{
+	struct xencomm_desc *desc;
+	int rc;
+
+	desc = __xencomm_alloc_mini(area, arealen);
+	if (!desc)
+		return -ENOMEM;
+	desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+	rc = __xencomm_init(desc, buffer, bytes, __kern_paddr);
+	if (rc)
+		return rc;
+
+	*ret = desc;
+	return 0;
+}
+
+struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long bytes)
+{
+	return (struct xencomm_desc *)
+		(__kern_paddr((unsigned long)buffer) | XENCOMM_INLINE);
+}
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/xen/xencomm.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/xen/xencomm.h	Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <[EMAIL PROTECTED]>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _LINUX_XENCOMM_H_
+#define _LINUX_XENCOMM_H_
+
+#include <xen/interface/xencomm.h>
+
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+    struct xencomm_desc _desc;
+    uint64_t address[XENCOMM_MINI_ADDRS];
+};
+#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2)
+
+extern int xencomm_create(void *buffer, unsigned long bytes,
+			  struct xencomm_desc **desc, gfp_t type);
+extern void xencomm_free(struct xencomm_desc *desc);
+extern int xencomm_create_mini(void *area, int arealen, void *buffer,
+            unsigned long bytes, struct xencomm_desc **ret);
+struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long bytes);
+
+#endif /* _LINUX_XENCOMM_H_ */
diff -r 8c6bb45901e7 xen/arch/ia64/xen/Makefile
--- a/xen/arch/ia64/xen/Makefile	Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/arch/ia64/xen/Makefile	Fri Aug 18 14:26:09 2006 +0200
@@ -25,5 +25,6 @@ obj-y += xentime.o
 obj-y += xentime.o
 obj-y += flushd.o
 obj-y += privop_stat.o
+obj-y += usercopy.o
 
 obj-$(crash_debug) += gdbstub.o
diff -r 8c6bb45901e7 xen/arch/ia64/xen/faults.c
--- a/xen/arch/ia64/xen/faults.c	Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/arch/ia64/xen/faults.c	Fri Aug 18 14:26:09 2006 +0200
@@ -225,10 +228,10 @@ void ia64_do_page_fault (unsigned long a
 			// indicate a bad xen pointer
 			printk("*** xen_handle_domain_access: exception table"
 			       " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
-				iip, address);
+			       iip, address);
 			panic_domain(regs,"*** xen_handle_domain_access: exception table"
-			       " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
-				iip, address);
+				     " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
+				     iip, address);
 		}
 		return;
 	}
diff -r 8c6bb45901e7 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c	Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/arch/ia64/xen/hypercall.c	Fri Aug 18 14:26:09 2006 +0200
@@ -29,7 +30,6 @@
 #include <public/callback.h>
 #include <xen/event.h>
 
-static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop);
 static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
 static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
 
@@ -51,10 +51,10 @@ const hypercall_t ia64_hypercall_table[N
 	(hypercall_t)do_multicall,
 	(hypercall_t)do_ni_hypercall,		/* do_update_va_mapping */
 	(hypercall_t)do_ni_hypercall,		/* do_set_timer_op */  /* 15 */
-	(hypercall_t)do_event_channel_op_compat,
+	(hypercall_t)do_ni_hypercall,
 	(hypercall_t)do_xen_version,
 	(hypercall_t)do_console_io,
-	(hypercall_t)do_physdev_op_compat,
+	(hypercall_t)do_ni_hypercall,
 	(hypercall_t)do_grant_table_op,				       /* 20 */
 	(hypercall_t)do_ni_hypercall,		/* do_vm_assist */
 	(hypercall_t)do_ni_hypercall,		/* do_update_va_mapping_othe */
@@ -105,19 +105,6 @@ xen_hypercall (struct pt_regs *regs)
 xen_hypercall (struct pt_regs *regs)
 {
 	uint32_t cmd = (uint32_t)regs->r2;
-	struct vcpu *v = current;
-
-	if (cmd == __HYPERVISOR_grant_table_op) {
-		XEN_GUEST_HANDLE(void) uop;
-
-		v->arch.hypercall_param.va = regs->r15;
-		v->arch.hypercall_param.pa1 = regs->r17;
-		v->arch.hypercall_param.pa2 = regs->r18;
-		set_xen_guest_handle(uop, (void *)regs->r15);
-		regs->r8 = do_grant_table_op(regs->r14, uop, regs->r16);
-		v->arch.hypercall_param.va = 0;
-		return IA64_NO_FAULT;
-	}
 
 	if (cmd < NR_hypercalls) {
 		perfc_incra(hypercalls, cmd);
@@ -130,7 +117,7 @@ xen_hypercall (struct pt_regs *regs)
 			regs->r19);
 	} else
 		regs->r8 = -ENOSYS;
-
+	
 	return IA64_NO_FAULT;
 }
 
@@ -456,28 +443,6 @@ static long do_physdev_op(int cmd, XEN_G
     return ret;
 }
 
-/* Legacy hypercall (as of 0x00030202). */
-static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop)
-{
-    struct physdev_op op;
-
-    if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
-        return -EFAULT;
-
-    return do_physdev_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
-}
-
-/* Legacy hypercall (as of 0x00030202). */
-long do_event_channel_op_compat(XEN_GUEST_HANDLE(evtchn_op_t) uop)
-{
-    struct evtchn_op op;
-
-    if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
-        return -EFAULT;
-
-    return do_event_channel_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
-}
-
 static long register_guest_callback(struct callback_register *reg)
 {
     long ret = 0;
diff -r 8c6bb45901e7 xen/include/asm-ia64/guest_access.h
--- a/xen/include/asm-ia64/guest_access.h	Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/include/asm-ia64/guest_access.h	Fri Aug 18 14:26:09 2006 +0200
@@ -1,91 +1,103 @@
-/******************************************************************************
- * guest_access.h
- * 
- * Copyright (c) 2006, K A Fraser
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
  */
 
-#ifndef __ASM_IA64_GUEST_ACCESS_H__
-#define __ASM_IA64_GUEST_ACCESS_H__
+#ifndef __ASM_GUEST_ACCESS_H__
+#define __ASM_GUEST_ACCESS_H__
 
-#include <asm/uaccess.h>
+extern unsigned long xencomm_copy_to_guest(void *to, const void *from,
+        unsigned int len, unsigned int skip); 
+extern unsigned long xencomm_copy_from_guest(void *to, const void *from,
+        unsigned int len, unsigned int skip); 
+extern void *xencomm_add_offset(void *handle, unsigned int bytes);
+extern int xencomm_handle_is_null(void *ptr);
+
 
 /* Is the guest handle a NULL reference? */
-#define guest_handle_is_null(hnd)        ((hnd).p == NULL)
+#define guest_handle_is_null(hnd) \
+    ((hnd).p == NULL || xencomm_handle_is_null((hnd).p))
 
 /* Offset the given guest handle into the array it refers to. */
-#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr))
+#define guest_handle_add_offset(hnd, nr) ({         \
+    const typeof((hnd).p) _ptr = (hnd).p;           \
+    (hnd).p = xencomm_add_offset(_ptr, nr * sizeof(*_ptr));   \
+})
 
 /* Cast a guest handle to the specified type of handle. */
 #define guest_handle_cast(hnd, type) ({         \
     type *_x = (hnd).p;                         \
-    (XEN_GUEST_HANDLE(type)) { _x };                \
+    XEN_GUEST_HANDLE(type) _y; \
+    set_xen_guest_handle(_y, _x); \
+    _y; \
 })
 
-#define guest_handle_from_ptr(ptr, type) ((XEN_GUEST_HANDLE(type)) { (type *)ptr })
+
+/* Since we run in real mode, we can safely access all addresses. That also
+ * means our __routines are identical to our "normal" routines. */
+#define guest_handle_okay(hnd, nr) 1
 
 /*
- * Copy an array of objects to guest context via a guest handle,
- * specifying an offset into the guest array.
+ * Copy an array of objects to guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
  */
-#define copy_to_guest_offset(hnd, off, ptr, nr) ({      \
-    const typeof(ptr) _x = (hnd).p;                     \
-    const typeof(ptr) _y = (ptr);                       \
-    copy_to_user(_x+(off), _y, sizeof(*_x)*(nr));       \
+#define copy_to_guest_offset(hnd, idx, ptr, nr) \
+    __copy_to_guest_offset(hnd, idx, ptr, nr)
+
+/* Copy sub-field of a structure to guest context via a guest handle. */
+#define copy_field_to_guest(hnd, ptr, field) \
+    __copy_field_to_guest(hnd, ptr, field)
+
+/*
+ * Copy an array of objects from guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
+ */
+#define copy_from_guest_offset(ptr, hnd, idx, nr) \
+    __copy_from_guest_offset(ptr, hnd, idx, nr)
+
+/* Copy sub-field of a structure from guest context via a guest handle. */
+#define copy_field_from_guest(ptr, hnd, field) \
+    __copy_field_from_guest(ptr, hnd, field)
+
+#define __copy_to_guest_offset(hnd, idx, ptr, nr) ({                \
+    const typeof(ptr) _d = (hnd).p;                                 \
+    const typeof(ptr) _s = (ptr);                                   \
+    xencomm_copy_to_guest(_d, _s, sizeof(*_s)*(nr), sizeof(*_s)*(idx)); \
 })
 
-/*
- * Copy an array of objects from guest context via a guest handle,
- * specifying an offset into the guest array.
- */
-#define copy_from_guest_offset(ptr, hnd, off, nr) ({    \
-    const typeof(ptr) _x = (hnd).p;                     \
-    const typeof(ptr) _y = (ptr);                       \
-    copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));     \
+#define __copy_field_to_guest(hnd, ptr, field) ({                   \
+    const int _off = offsetof(typeof(*ptr), field);                 \
+    const typeof(ptr) _d = (hnd).p;                                 \
+    const typeof(&(ptr)->field) _s = &(ptr)->field;                 \
+    xencomm_copy_to_guest(_d, _s, sizeof(*_s), _off); \
 })
 
-/* Copy sub-field of a structure to guest context via a guest handle. */
-#define copy_field_to_guest(hnd, ptr, field) ({         \
-    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
-    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    copy_to_user(_x, _y, sizeof(*_x));                  \
+#define __copy_from_guest_offset(ptr, hnd, idx, nr) ({              \
+    const typeof(ptr) _s = (hnd).p;                                 \
+    const typeof(ptr) _d = (ptr);                                   \
+    xencomm_copy_from_guest(_d, _s, sizeof(*_s)*(nr), sizeof(*_s)*(idx));  \
 })
 
-/* Copy sub-field of a structure from guest context via a guest handle. */
-#define copy_field_from_guest(ptr, hnd, field) ({       \
-    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
-    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    copy_from_user(_y, _x, sizeof(*_x));                \
+#define __copy_field_from_guest(ptr, hnd, field) ({                 \
+    const int _off = offsetof(typeof(*ptr), field);                 \
+    const typeof(ptr) _s = (hnd).p;                                 \
+    const typeof(&(ptr)->field) _d = &(ptr)->field;                 \
+    xencomm_copy_from_guest(_d, _s, sizeof(*_d), _off); \
 })
 
-/*
- * Pre-validate a guest handle.
- * Allows use of faster __copy_* functions.
- */
-#define guest_handle_okay(hnd, nr)                      \
-    array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))
-
-#define __copy_to_guest_offset(hnd, off, ptr, nr) ({    \
-    const typeof(ptr) _x = (hnd).p;                     \
-    const typeof(ptr) _y = (ptr);                       \
-    __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr));     \
-})
-
-#define __copy_from_guest_offset(ptr, hnd, off, nr) ({  \
-    const typeof(ptr) _x = (hnd).p;                     \
-    const typeof(ptr) _y = (ptr);                       \
-    __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));   \
-})
-
-#define __copy_field_to_guest(hnd, ptr, field) ({       \
-    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
-    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    __copy_to_user(_x, _y, sizeof(*_x));                \
-})
-
-#define __copy_field_from_guest(ptr, hnd, field) ({     \
-    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
-    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
-    __copy_from_user(_y, _x, sizeof(*_x));              \
-})
-
-#endif /* __ASM_IA64_GUEST_ACCESS_H__ */
+#endif /* __ASM_GUEST_ACCESS_H__ */
diff -r 8c6bb45901e7 xen/include/public/xencomm.h
--- a/xen/include/public/xencomm.h	Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/include/public/xencomm.h	Fri Aug 18 14:26:09 2006 +0200
@@ -34,4 +34,10 @@ struct xencomm_desc {
     uint64_t address[0];
 };
 
+/* If the inline flag is set, the descriptor is simply the physical address
+   of the buffer which is known to be contiguous in physical memory.
+   Because the kernels are often 1:1 mapped, this is interesting for kernel
+   issued hypercalls.  */
+#define XENCOMM_INLINE (1UL << 63)
+
 #endif /* _XEN_XENCOMM_H_ */
diff -r 8c6bb45901e7 xen/arch/ia64/xen/usercopy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/usercopy.c	Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,303 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
+ */
+
+#include <xen/config.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <asm/current.h>
+#include <asm/guest_access.h>
+#include <public/xen.h>
+#include <public/xencomm.h>
+
+#undef DEBUG
+#ifdef DEBUG
+static int xencomm_debug = 1; /* extremely verbose */
+#else
+#define xencomm_debug 0
+#endif
+
+/* XXX need to return error, not panic, if domain passed a bad pointer */
+static unsigned long paddr_to_maddr(unsigned long paddr)
+{
+    struct vcpu *v = current;
+    struct domain *d = v->domain;
+    u64 pa;
+
+    pa = ____lookup_domain_mpa (d, paddr);
+    if (pa == INVALID_MFN)
+	    panic_domain(NULL,
+			 "%s: called with bad memory address type: 0x%lx\n",
+			 __func__, paddr);
+    return __va_ul ((pa & _PFN_MASK) | (paddr & ~PAGE_MASK));
+}
+
+/**
+ * xencomm_copy_from_guest: Copy a block of data from domain space.
+ * @to:   Machine address.
+ * @from: Physical address to a xencomm buffer descriptor.
+ * @n:    Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from domain to hypervisor.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_from_guest(void *to, const void *from, unsigned int n,
+        unsigned int skip)
+{
+    struct xencomm_desc *desc;
+    unsigned int from_pos = 0;
+    unsigned int to_pos = 0;
+    unsigned int i = 0;
+
+    if (xencomm_debug)
+	    printf ("xencomm_copy_from_guest: from=%lx+%u n=%u\n",
+		    (unsigned long)from, skip, n);
+
+    if ((unsigned long)from & XENCOMM_INLINE) {
+	    unsigned long src_paddr = (unsigned long)from & ~XENCOMM_INLINE;
+	    
+	    src_paddr += skip;
+
+	    while (n > 0) {
+		    unsigned int chunksz;
+		    unsigned long src_maddr;
+		    unsigned int bytes;
+
+		    chunksz = PAGE_SIZE - (src_paddr % PAGE_SIZE);
+
+		    bytes = min(chunksz, n);
+
+		    src_maddr = paddr_to_maddr(src_paddr);
+		    if (xencomm_debug > 1)
+			    printk("%lx[%d] -> %lx\n",
+				   src_maddr, bytes, (unsigned long)to);
+		    memcpy(to, (void *)src_maddr, bytes);
+		    src_paddr += bytes;
+		    to += bytes;
+		    n -= bytes;
+	    }
+
+	    /* Always successful.  */
+	    return 0;
+    }
+
+    /* first we need to access the descriptor */
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)from);
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s: error: %p magic was 0x%x\n",
+               __func__, desc, desc->magic);
+        return n;
+    }
+
+    /* iterate through the descriptor, copying up to a page at a time */
+    while ((to_pos < n) && (i < desc->nr_addrs)) {
+        unsigned long src_paddr = desc->address[i];
+        unsigned int pgoffset;
+        unsigned int chunksz;
+        unsigned int chunk_skip;
+
+        if (src_paddr == XENCOMM_INVALID) {
+            i++;
+            continue;
+        }
+
+        pgoffset = src_paddr % PAGE_SIZE;
+        chunksz = PAGE_SIZE - pgoffset;
+
+        chunk_skip = min(chunksz, skip);
+        from_pos += chunk_skip;
+        chunksz -= chunk_skip;
+        skip -= chunk_skip;
+
+        if (skip == 0) {
+            unsigned long src_maddr;
+            unsigned long dest = (unsigned long)to + to_pos;
+            unsigned int bytes = min(chunksz, n - to_pos);
+
+            if (xencomm_debug > 1)
+		    printf ("src_paddr=%lx i=%d, skip=%d\n",
+			    src_paddr, i, chunk_skip);
+            src_maddr = paddr_to_maddr(src_paddr + chunk_skip);
+            if (xencomm_debug > 1)
+                printk("%lx[%d] -> %lx\n", src_maddr, bytes, dest);
+            memcpy((void *)dest, (void *)src_maddr, bytes);
+            from_pos += bytes;
+            to_pos += bytes;
+        }
+
+        i++;
+    }
+
+    return n - to_pos;
+}
+
+/**
+ * xencomm_copy_to_guest: Copy a block of data to domain space.
+ * @to:     Physical address to xencomm buffer descriptor.
+ * @from:   Machine address.
+ * @n:      Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from hypervisor to domain.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_to_guest(void *to, const void *from, unsigned int n,
+        unsigned int skip)
+{
+    struct xencomm_desc *desc;
+    unsigned int from_pos = 0;
+    unsigned int to_pos = 0;
+    unsigned int i = 0;
+
+    if (xencomm_debug)
+	    printf ("xencomm_copy_to_guest: to=%lx+%u n=%u\n",
+		    (unsigned long)to, skip, n);
+
+    if ((unsigned long)to & XENCOMM_INLINE) {
+	    unsigned long dest_paddr = (unsigned long)to & ~XENCOMM_INLINE;
+	    
+	    dest_paddr += skip;
+
+	    while (n > 0) {
+		    unsigned int chunksz;
+		    unsigned long dest_maddr;
+		    unsigned int bytes;
+
+		    chunksz = PAGE_SIZE - (dest_paddr % PAGE_SIZE);
+
+		    bytes = min(chunksz, n);
+
+		    dest_maddr = paddr_to_maddr(dest_paddr);
+		    if (xencomm_debug > 1)
+			    printk("%lx[%d] -> %lx\n",
+				   (unsigned long)from, bytes, dest_maddr);
+		    memcpy((void *)dest_maddr, (void *)from, bytes);
+		    dest_paddr += bytes;
+		    from += bytes;
+		    n -= bytes;
+	    }
+
+	    /* Always successful.  */
+	    return 0;
+    }
+
+    /* first we need to access the descriptor */
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)to);
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+        return n;
+    }
+
+    /* iterate through the descriptor, copying up to a page at a time */
+    while ((from_pos < n) && (i < desc->nr_addrs)) {
+        unsigned long dest_paddr = desc->address[i];
+        unsigned int pgoffset;
+        unsigned int chunksz;
+        unsigned int chunk_skip;
+
+        if (dest_paddr == XENCOMM_INVALID) {
+            i++;
+            continue;
+        }
+
+        pgoffset = dest_paddr % PAGE_SIZE;
+        chunksz = PAGE_SIZE - pgoffset;
+
+        chunk_skip = min(chunksz, skip);
+        to_pos += chunk_skip;
+        chunksz -= chunk_skip;
+        skip -= chunk_skip;
+
+        if (skip == 0) {
+            unsigned long dest_maddr;
+            unsigned long source = (unsigned long)from + from_pos;
+            unsigned int bytes = min(chunksz, n - from_pos);
+
+            dest_maddr = paddr_to_maddr(dest_paddr + chunk_skip);
+            if (xencomm_debug > 1)
+                printk("%lx[%d] -> %lx\n", source, bytes, dest_maddr);
+            memcpy((void *)dest_maddr, (void *)source, bytes);
+            from_pos += bytes;
+            to_pos += bytes;
+        }
+
+        i++;
+    }
+
+    return n - from_pos;
+}
+
+/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely
+ * exhausted pages to XENCOMM_INVALID. */
+void *xencomm_add_offset(void *handle, unsigned int bytes)
+{
+    struct xencomm_desc *desc;
+    int i = 0;
+
+    if ((unsigned long)handle & XENCOMM_INLINE) {
+	    return (void *)((unsigned long)handle + bytes);
+    }
+
+    /* first we need to access the descriptor */
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)handle);
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+        return NULL;
+    }
+
+    /* iterate through the descriptor incrementing addresses */
+    while ((bytes > 0) && (i < desc->nr_addrs)) {
+        unsigned long dest_paddr = desc->address[i];
+        unsigned int pgoffset;
+        unsigned int chunksz;
+        unsigned int chunk_skip;
+
+        pgoffset = dest_paddr % PAGE_SIZE;
+        chunksz = PAGE_SIZE - pgoffset;
+
+        chunk_skip = min(chunksz, bytes);
+        if (chunk_skip == chunksz) {
+            /* exhausted this page */
+            desc->address[i] = XENCOMM_INVALID;
+        } else {
+            desc->address[i] += chunk_skip;
+        }
+        bytes -= chunk_skip;
+    }
+    return handle;
+}
+
+int xencomm_handle_is_null(void *ptr)
+{
+    struct xencomm_desc *desc;
+
+    if ((unsigned long)ptr & XENCOMM_INLINE)
+	    return (unsigned long)ptr == XENCOMM_INLINE;
+    else {
+	    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)ptr);
+	    return (desc->address[0] == XENCOMM_INVALID);
+    }
+}
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to