[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] Use xencomm for hypercalls.



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 5c97ef4c71471999167a946bbbadacbf51c642d8
# Parent  2bfd19fc1b79c6a6712c99f875f1fbf883af3f35
[IA64] Use xencomm for hypercalls.

With xencomm metaphysical addresses are passed to the hypervisor instead
of virtual addresses.
This patch breaks compatibility.

Signed-off-by: Tristan Gingold <tristan.gingold@xxxxxxxx>
---
 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c          |    3 
 linux-2.6-xen-sparse/arch/ia64/xen/Makefile            |    3 
 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c        |   80 --
 linux-2.6-xen-sparse/arch/ia64/xen/util.c              |    2 
 linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c        |  468 +++++++++++++
 linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c      |  573 +++++++++++++++++
 linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c           |  244 +++++++
 linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S          |   14 
 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c     |   13 
 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h      |  262 +++----
 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h     |   11 
 linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h |   74 ++
 linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h    |   57 +
 tools/libxc/ia64/xc_ia64_linux_restore.c               |    3 
 tools/libxc/ia64/xc_ia64_linux_save.c                  |    3 
 xen/arch/ia64/xen/Makefile                             |    1 
 xen/arch/ia64/xen/domain.c                             |    1 
 xen/arch/ia64/xen/faults.c                             |    6 
 xen/arch/ia64/xen/fw_emul.c                            |    2 
 xen/arch/ia64/xen/hypercall.c                          |   42 -
 xen/arch/ia64/xen/mm.c                                 |   16 
 xen/arch/ia64/xen/xencomm.c                            |  380 +++++++++++
 xen/include/asm-ia64/guest_access.h                    |  152 ++--
 xen/include/public/arch-ia64.h                         |    8 
 24 files changed, 2055 insertions(+), 363 deletions(-)

diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c     Sun Oct 01 19:10:18 
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c     Mon Oct 02 14:03:42 
2006 -0600
@@ -76,6 +76,8 @@ EXPORT_SYMBOL(__per_cpu_offset);
 #endif
 
 #ifdef CONFIG_XEN
+unsigned long kernel_start_pa;
+
 static int
 xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
@@ -433,6 +435,7 @@ setup_arch (char **cmdline_p)
 
 #ifdef CONFIG_XEN
        if (is_running_on_xen()) {
+               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 2bfd19fc1b79 -r 5c97ef4c7147 linux-2.6-xen-sparse/arch/ia64/xen/Makefile
--- a/linux-2.6-xen-sparse/arch/ia64/xen/Makefile       Sun Oct 01 19:10:18 
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/Makefile       Mon Oct 02 14:03:42 
2006 -0600
@@ -3,6 +3,7 @@
 #
 
 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 xencomm.o xcom_hcall.o \
+        xcom_privcmd.o
 
 pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Sun Oct 01 19:10:18 
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Mon Oct 02 14:03:42 
2006 -0600
@@ -39,60 +39,6 @@ EXPORT_SYMBOL(xen_start_info);
 
 int running_on_xen;
 EXPORT_SYMBOL(running_on_xen);
-
-//XXX xen/ia64 copy_from_guest() is broken.
-//    This is a temporal work around until it is fixed.
-//    used by balloon.c netfront.c
-
-// get_xen_guest_handle is defined only when __XEN_TOOLS__ is defined
-// if the definition in arch-ia64.h is changed, this must be updated.
-#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
-
-int
-ia64_xenmem_reservation_op(unsigned long op,
-                          struct xen_memory_reservation* reservation__)
-{
-       struct xen_memory_reservation reservation = *reservation__;
-       unsigned long* frame_list;
-       unsigned long nr_extents = reservation__->nr_extents;
-       int ret = 0;
-       get_xen_guest_handle(frame_list, reservation__->extent_start);
-
-       BUG_ON(op != XENMEM_increase_reservation &&
-              op != XENMEM_decrease_reservation &&
-              op != XENMEM_populate_physmap);
-
-       while (nr_extents > 0) {
-               int tmp_ret;
-               volatile unsigned long dummy;
-
-               set_xen_guest_handle(reservation.extent_start, frame_list);
-               reservation.nr_extents = nr_extents;
-
-               dummy = frame_list[0];// re-install tlb entry before hypercall
-               tmp_ret = ____HYPERVISOR_memory_op(op, &reservation);
-               if (tmp_ret < 0) {
-                       if (ret == 0) {
-                               ret = tmp_ret;
-                       }
-                       break;
-               }
-               if (tmp_ret == 0) {
-                       //XXX dirty work around for skbuff_ctor()
-                       //    of a non-privileged domain, 
-                       if ((op == XENMEM_increase_reservation ||
-                            op == XENMEM_populate_physmap) &&
-                           !is_initial_xendomain() &&
-                           reservation.extent_order > 0)
-                               return ret;
-               }
-               frame_list += tmp_ret;
-               nr_extents -= tmp_ret;
-               ret += tmp_ret;
-       }
-       return ret;
-}
-EXPORT_SYMBOL(ia64_xenmem_reservation_op);
 
 //XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear()
 // move those to lib/contiguous_bitmap?
@@ -371,8 +317,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 +324,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 xencomm_mini_hypercall_grant_table_op(cmd, uop, count);
 }
 EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
 
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 linux-2.6-xen-sparse/arch/ia64/xen/util.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/util.c Sun Oct 01 19:10:18 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/util.c Mon Oct 02 14:03:42 2006 -0600
@@ -28,6 +28,8 @@
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include <xen/driver_util.h>
+#include <xen/interface/memory.h>
+#include <asm/hypercall.h>
 
 struct vm_struct *alloc_vm_area(unsigned long size)
 {
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S     Sun Oct 01 19:10:18 
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S     Mon Oct 02 14:03:42 
2006 -0600
@@ -37,18 +37,18 @@ END(early_xen_setup)
 
 /* Stub for suspend.
    Just force the stacked registers to be written in memory.  */       
-GLOBAL_ENTRY(HYPERVISOR_suspend)
+GLOBAL_ENTRY(xencomm_arch_hypercall_suspend)
+       mov r15=r32
+       ;; 
        alloc r20=ar.pfs,0,0,0,0
-       mov r14=2
-       mov r15=r12
-       ;;
+       mov r2=__HYPERVISOR_sched_op
+       ;; 
        /* We don't want to deal with RSE.  */
        flushrs
-       mov r2=__HYPERVISOR_sched_op
-       st4 [r12]=r14
+       mov r14=2 // SCHEDOP_shutdown
        ;;
        break 0x1000
        ;; 
        mov ar.pfs=r20
        br.ret.sptk.many b0
-END(HYPERVISOR_suspend)
+END(xencomm_arch_hypercall_suspend)
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Sun Oct 01 
19:10:18 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Mon Oct 02 
14:03:42 2006 -0600
@@ -83,18 +83,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 = privcmd_hypercall(&hypercall);
 #endif
        }
        break;
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Sun Oct 01 19:10:18 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Mon Oct 02 14:03:42 
2006 -0600
@@ -33,11 +33,12 @@
 #ifndef __HYPERCALL_H__
 #define __HYPERCALL_H__
 
-#include <linux/string.h> /* memcpy() */
-
 #ifndef __HYPERVISOR_H__
 # error "please don't include this file directly"
 #endif
+
+#include <asm/xen/xcom_hcall.h>
+struct xencomm_handle;
 
 /*
  * Assembler stubs for hyper-calls.
@@ -157,157 +158,105 @@
        (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)
+
+static inline int
+xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg)
 {
        return _hypercall2(int, sched_op, cmd, arg);
 }
 
 static inline long
-HYPERVISOR_set_timer_op(
-    u64 timeout)
-{
-    unsigned long timeout_hi = (unsigned long)(timeout>>32);
-    unsigned long timeout_lo = (unsigned long)timeout;
-    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);
-}
-
-//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);
-}
-
-#include <xen/interface/memory.h>
-#ifdef CONFIG_VMX_GUEST
-# define ia64_xenmem_reservation_op(op, xmr) (0)
-#else
-int ia64_xenmem_reservation_op(unsigned long op,
-                  struct xen_memory_reservation* reservation__);
-#endif
-static inline int
-HYPERVISOR_memory_op(
-    unsigned int cmd, void *arg)
-{
-    switch (cmd) {
-    case XENMEM_increase_reservation:
-    case XENMEM_decrease_reservation:
-    case XENMEM_populate_physmap:
-        return ia64_xenmem_reservation_op(cmd, 
-                                          (struct xen_memory_reservation*)arg);
-    default:
-        return ____HYPERVISOR_memory_op(cmd, arg);
-    }
-    /* 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;
-}
-
-//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);
+HYPERVISOR_set_timer_op(u64 timeout)
+{
+       unsigned long timeout_hi = (unsigned long)(timeout >> 32);
+       unsigned long timeout_lo = (unsigned long)timeout;
+       return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+}
+
+static inline int
+xencomm_arch_hypercall_dom0_op(struct xencomm_handle *op)
+{
+       return _hypercall1(int, dom0_op, op);
+}
+
+static inline int
+xencomm_arch_hypercall_sysctl(struct xencomm_handle *op)
+{
+       return _hypercall1(int, sysctl, op);
+}
+
+static inline int
+xencomm_arch_hypercall_domctl(struct xencomm_handle *op)
+{
+       return _hypercall1(int, domctl, op);
+}
+
+static inline int
+xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list,
+                                int nr_calls)
+{
+       return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int
+xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, event_channel_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_acm_op(unsigned int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, acm_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_console_io(int cmd, int count,
+                                  struct xencomm_handle *str)
+{
+       return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, physdev_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_grant_table_op(unsigned int cmd,
+                                      struct xencomm_handle *uop,
+                                      unsigned int count)
+{
+       return _hypercall3(int, grant_table_op, cmd, uop, count);
 }
 
 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_suspend(unsigned long srec);
-
-static inline unsigned long
-HYPERVISOR_hvm_op(
-       int cmd, void *arg)
+extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg);
+
+static inline int
+xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg)
+{
+       return _hypercall2(int, callback_op, cmd, arg);
+}
+
+static inline unsigned long
+xencomm_arch_hypercall_hvm_op(int cmd, void *arg)
 {
        return _hypercall2(unsigned long, hvm_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_callback_op(
-       int cmd, void *arg)
-{
-       return _hypercall2(int, callback_op, cmd, arg);
 }
 
 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
@@ -420,4 +369,33 @@ HYPERVISOR_add_physmap(unsigned long gpf
 // for balloon driver
 #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
 
+/* Use xencomm to do hypercalls.  */
+#ifdef MODULE
+#define HYPERVISOR_sched_op xencomm_mini_hypercall_sched_op
+#define HYPERVISOR_event_channel_op xencomm_mini_hypercall_event_channel_op
+#define HYPERVISOR_callback_op xencomm_mini_hypercall_callback_op
+#define HYPERVISOR_multicall xencomm_mini_hypercall_multicall
+#define HYPERVISOR_xen_version xencomm_mini_hypercall_xen_version
+#define HYPERVISOR_console_io xencomm_mini_hypercall_console_io
+#define HYPERVISOR_physdev_op xencomm_mini_hypercall_physdev_op
+#define HYPERVISOR_hvm_op xencomm_mini_hypercall_hvm_op
+#ifdef CONFIG_VMX_GUEST
+#define HYPERVISOR_memory_op 0
+#else
+#define HYPERVISOR_memory_op xencomm_mini_hypercall_memory_op
+#endif
+#else
+#define HYPERVISOR_sched_op xencomm_hypercall_sched_op
+#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op
+#define HYPERVISOR_callback_op xencomm_hypercall_callback_op
+#define HYPERVISOR_multicall xencomm_hypercall_multicall
+#define HYPERVISOR_xen_version xencomm_hypercall_xen_version
+#define HYPERVISOR_console_io xencomm_hypercall_console_io
+#define HYPERVISOR_physdev_op xencomm_hypercall_physdev_op
+#define HYPERVISOR_hvm_op xencomm_hypercall_hvm_op
+#define HYPERVISOR_memory_op xencomm_hypercall_memory_op
+#endif
+
+#define HYPERVISOR_suspend xencomm_hypercall_suspend
+
 #endif /* __HYPERCALL_H__ */
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Sun Oct 01 
19:10:18 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Mon Oct 02 
14:03:42 2006 -0600
@@ -75,9 +75,6 @@ HYPERVISOR_yield(
 {
        int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
 
-       if (rc == -ENOSYS)
-               rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
-
        return rc;
 }
 
@@ -86,9 +83,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;
 }
@@ -102,9 +96,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;
 }
@@ -122,8 +113,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 2bfd19fc1b79 -r 5c97ef4c7147 tools/libxc/ia64/xc_ia64_linux_restore.c
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c  Sun Oct 01 19:10:18 2006 -0600
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c  Mon Oct 02 14:03:42 2006 -0600
@@ -224,6 +224,9 @@ xc_linux_restore(int xc_handle, int io_f
         ERR("Error when reading ctxt");
         goto out;
     }
+
+    fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt.user_regs.cr_iip,
+            ctxt.user_regs.b0);
 
     /* First to initialize.  */
     domctl.cmd = XEN_DOMCTL_setvcpucontext;
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 tools/libxc/ia64/xc_ia64_linux_save.c
--- a/tools/libxc/ia64/xc_ia64_linux_save.c     Sun Oct 01 19:10:18 2006 -0600
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c     Mon Oct 02 14:03:42 2006 -0600
@@ -458,6 +458,9 @@ xc_linux_save(int xc_handle, int io_fd, 
         goto out;
     }
 
+    fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt.user_regs.cr_iip,
+            ctxt.user_regs.b0);
+
     mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                PROT_READ|PROT_WRITE, ctxt.privregs_pfn);
     if (mem == NULL) {
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/Makefile
--- a/xen/arch/ia64/xen/Makefile        Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/arch/ia64/xen/Makefile        Mon Oct 02 14:03:42 2006 -0600
@@ -26,5 +26,6 @@ obj-y += flushd.o
 obj-y += flushd.o
 obj-y += privop_stat.o
 obj-y += xenpatch.o
+obj-y += xencomm.o
 
 obj-$(crash_debug) += gdbstub.o
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/arch/ia64/xen/domain.c        Mon Oct 02 14:03:42 2006 -0600
@@ -46,6 +46,7 @@
 #include <asm/regionreg.h>
 #include <asm/dom_fw.h>
 #include <asm/shadow.h>
+#include <xen/guest_access.h>
 
 unsigned long dom0_size = 512*1024*1024;
 unsigned long dom0_align = 64*1024*1024;
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/faults.c
--- a/xen/arch/ia64/xen/faults.c        Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/arch/ia64/xen/faults.c        Mon Oct 02 14:03:42 2006 -0600
@@ -228,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 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/fw_emul.c
--- a/xen/arch/ia64/xen/fw_emul.c       Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/arch/ia64/xen/fw_emul.c       Mon Oct 02 14:03:42 2006 -0600
@@ -16,7 +16,6 @@
  *
  */
 #include <xen/config.h>
-#include <xen/console.h>
 #include <asm/system.h>
 #include <asm/pgalloc.h>
 
@@ -29,6 +28,7 @@
 #include <asm/vcpu.h>
 #include <asm/dom_fw.h>
 #include <asm/uaccess.h>
+#include <xen/console.h>
 
 extern unsigned long running_on_sim;
 
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c     Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/arch/ia64/xen/hypercall.c     Mon Oct 02 14:03:42 2006 -0600
@@ -32,7 +32,6 @@
 #include <xen/event.h>
 #include <xen/perfc.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);
 
@@ -54,10 +53,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 */
@@ -108,19 +107,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);
@@ -133,7 +119,7 @@ xen_hypercall (struct pt_regs *regs)
                        regs->r19);
        } else
                regs->r8 = -ENOSYS;
-
+       
        return IA64_NO_FAULT;
 }
 
@@ -465,28 +451,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 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c    Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/arch/ia64/xen/mm.c    Mon Oct 02 14:03:42 2006 -0600
@@ -708,6 +708,22 @@ void *domain_mpa_to_imva(struct domain *
 }
 #endif
 
+unsigned long
+xencomm_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) {
+        printf("%s: called with bad memory address: 0x%lx - iip=%lx\n",
+               __func__, paddr, vcpu_regs(v)->cr_iip);
+        return 0;
+    }
+    return __va_ul((pa & _PFN_MASK) | (paddr & ~PAGE_MASK));
+}
+
 /* Allocate a new page for domain and map it to the specified metaphysical
    address.  */
 static struct page_info *
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 xen/include/asm-ia64/guest_access.h
--- a/xen/include/asm-ia64/guest_access.h       Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/include/asm-ia64/guest_access.h       Mon Oct 02 14:03:42 2006 -0600
@@ -1,91 +1,107 @@
-/******************************************************************************
- * 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 <hollisb@xxxxxxxxxx>
+ *          Tristan Gingold <tristan.gingold@xxxxxxxx>
  */
 
-#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 };                \
+#define guest_handle_cast(hnd, type) ({   \
+    type *_x = (hnd).p;                   \
+    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))
+/* Internal use only: returns 0 in case of bad address.  */
+extern unsigned long xencomm_paddr_to_maddr(unsigned long paddr);
 
-#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 2bfd19fc1b79 -r 5c97ef4c7147 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h    Sun Oct 01 19:10:18 2006 -0600
+++ b/xen/include/public/arch-ia64.h    Mon Oct 02 14:03:42 2006 -0600
@@ -431,6 +431,14 @@ struct xen_ia64_boot_param {
 #define HYPERPRIVOP_GET_PSR            0x19
 #define HYPERPRIVOP_MAX                        0x19
 
+/* Xencomm macros.  */
+#define XENCOMM_INLINE_MASK 0xf800000000000000UL
+#define XENCOMM_INLINE_FLAG 0x8000000000000000UL
+
+#define XENCOMM_IS_INLINE(addr) \
+  (((unsigned long)(addr) & XENCOMM_INLINE_MASK) == XENCOMM_INLINE_FLAG)
+#define XENCOMM_INLINE_ADDR(addr) \
+  ((unsigned long)(addr) & ~XENCOMM_INLINE_MASK)
 #endif /* __HYPERVISOR_IF_IA64_H__ */
 
 /*
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c   Mon Oct 02 14:03:42 
2006 -0600
@@ -0,0 +1,468 @@
+/*
+ * 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.
+ *
+ *          Tristan Gingold <tristan.gingold@xxxxxxxx>
+ */
+#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/interface/hvm/params.h>
+#include <xen/public/privcmd.h>
+#include <asm/hypercall.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/xen/xencomm.h>
+
+/* Xencomm notes:
+ * This file defines hypercalls to be used by xencomm.  The hypercalls simply
+ * create inlines descriptors for pointers and then call the raw arch hypercall
+ * xencomm_arch_hypercall_XXX
+ *
+ * If the arch wants to directly use these hypercalls, simply define macros
+ * in asm/hypercall.h, eg:
+ *  #define HYPERVISOR_sched_op xencomm_hypercall_sched_op
+ * 
+ * The arch may also define HYPERVISOR_xxx as a function and do more operations
+ * before/after doing the hypercall.
+ *
+ * Note: because only inline descriptors are created these functions must only
+ * be called with in kernel memory parameters.
+ */
+
+int
+xencomm_hypercall_console_io(int cmd, int count, char *str)
+{
+       return xencomm_arch_hypercall_console_io
+               (cmd, count, xencomm_create_inline(str));
+}
+
+int
+xencomm_hypercall_event_channel_op(int cmd, void *op)
+{
+       return xencomm_arch_hypercall_event_channel_op
+               (cmd, xencomm_create_inline(op));
+}
+
+int
+xencomm_hypercall_xen_version(int cmd, void *arg)
+{
+       switch (cmd) {
+       case XENVER_version:
+       case XENVER_extraversion:
+       case XENVER_compile_info:
+       case XENVER_capabilities:
+       case XENVER_changeset:
+       case XENVER_platform_parameters:
+       case XENVER_pagesize:
+       case XENVER_get_features:
+               break;
+       default:
+               printk("%s: unknown version cmd %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       return xencomm_arch_hypercall_xen_version
+               (cmd, xencomm_create_inline(arg));
+}
+
+int
+xencomm_hypercall_physdev_op(int cmd, void *op)
+{
+       return xencomm_arch_hypercall_physdev_op
+               (cmd, xencomm_create_inline(op));
+}
+
+static void *
+xencommize_grant_table_op(unsigned int cmd, void *op, unsigned int count)
+{
+       switch (cmd) {
+       case GNTTABOP_map_grant_ref:
+       case GNTTABOP_unmap_grant_ref:
+               break;
+       case GNTTABOP_setup_table:
+       {
+               struct gnttab_setup_table *setup = op;
+               struct xencomm_handle *frame_list;
+
+               frame_list = xencomm_create_inline
+                       (xen_guest_handle(setup->frame_list));
+
+               set_xen_guest_handle(setup->frame_list, (void *)frame_list);
+               break;
+       }
+       case GNTTABOP_dump_table:
+       case GNTTABOP_transfer:
+               break;
+       default:
+               printk("%s: unknown grant table op %d\n", __func__, cmd);
+               BUG();
+       }
+
+       return  xencomm_create_inline(op);
+}
+
+int
+xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, unsigned int 
count)
+{
+       void *desc = xencommize_grant_table_op (cmd, op, count);
+
+       return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
+}
+
+int
+xencomm_hypercall_sched_op(int cmd, void *arg)
+{
+       switch (cmd) {
+       case SCHEDOP_yield:
+       case SCHEDOP_block:
+       case SCHEDOP_shutdown:
+       case SCHEDOP_poll:
+       case SCHEDOP_remote_shutdown:
+               break;
+       default:
+               printk("%s: unknown sched op %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+       
+       return xencomm_arch_hypercall_sched_op(cmd, xencomm_create_inline(arg));
+}
+
+int
+xencomm_hypercall_multicall(void *call_list, int nr_calls)
+{
+       int i;
+       multicall_entry_t *mce;
+
+       for (i = 0; i < nr_calls; i++) {
+               mce = (multicall_entry_t *)call_list + i;
+
+               switch (mce->op) {
+               case __HYPERVISOR_update_va_mapping:
+               case __HYPERVISOR_mmu_update:
+                       /* No-op on ia64.  */
+                       break;
+               case __HYPERVISOR_grant_table_op:
+                       mce->args[1] = (unsigned long)xencommize_grant_table_op
+                               (mce->args[0], (void *)mce->args[1],
+                                mce->args[2]);
+                       break;
+               case __HYPERVISOR_memory_op:
+               default:
+                       printk("%s: unhandled multicall op entry op %lu\n",
+                              __func__, mce->op);
+                       return -ENOSYS;
+               }
+       }
+
+       return xencomm_arch_hypercall_multicall
+               (xencomm_create_inline(call_list), nr_calls);
+}
+
+int
+xencomm_hypercall_callback_op(int cmd, void *arg)
+{
+       switch (cmd)
+       {
+       case CALLBACKOP_register:
+       case CALLBACKOP_unregister:
+               break;
+       default:
+               printk("%s: unknown callback op %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       return xencomm_arch_hypercall_callback_op
+               (cmd, xencomm_create_inline(arg));
+}
+
+static void
+xencommize_memory_reservation (xen_memory_reservation_t *mop)
+{
+       struct xencomm_handle *desc;
+
+       desc = xencomm_create_inline(xen_guest_handle(mop->extent_start));
+       set_xen_guest_handle(mop->extent_start, (void *)desc);
+}
+
+int
+xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case XENMEM_increase_reservation:
+       case XENMEM_decrease_reservation:
+       case XENMEM_populate_physmap:
+               xencommize_memory_reservation((xen_memory_reservation_t *)arg);
+               break;
+               
+       case XENMEM_maximum_ram_page:
+               break;
+
+       case XENMEM_exchange:
+               xencommize_memory_reservation
+                       (&((xen_memory_exchange_t *)arg)->in);
+               xencommize_memory_reservation
+                       (&((xen_memory_exchange_t *)arg)->out);
+               break;
+
+       default:
+               printk("%s: unknown memory op %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       return xencomm_arch_hypercall_memory_op
+               (cmd, xencomm_create_inline(arg));
+}
+
+unsigned long
+xencomm_hypercall_hvm_op(int cmd, void *arg)
+{
+       switch (cmd) {
+       case HVMOP_set_param:
+       case HVMOP_get_param:
+               break;
+       default:
+               printk("%s: unknown hvm op %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       return xencomm_arch_hypercall_hvm_op(cmd, xencomm_create_inline(arg));
+}
+
+int
+xencomm_hypercall_suspend(unsigned long srec)
+{
+       struct sched_shutdown arg;
+
+       arg.reason = SHUTDOWN_suspend;
+
+       return xencomm_arch_hypercall_suspend(xencomm_create_inline(&arg));
+}
+
+int
+xencomm_mini_hypercall_event_channel_op(int cmd, void *op)
+{
+       struct xencomm_mini xc_area[2];
+       int nbr_area = 2;
+       struct xencomm_handle *desc;
+       int rc;
+
+       rc = xencomm_create_mini(xc_area, &nbr_area,
+                                op, sizeof(evtchn_op_t), &desc);
+       if (rc)
+               return rc;
+
+       return xencomm_arch_hypercall_event_channel_op(cmd, desc);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_event_channel_op);
+
+static int
+xencommize_mini_grant_table_op(struct xencomm_mini *xc_area, int *nbr_area,
+                               unsigned int cmd, void *op, unsigned int count,
+                               struct xencomm_handle **desc)
+{
+       struct xencomm_handle *desc1;
+       unsigned int argsize;
+       int rc;
+
+       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(*setup);
+
+               if (count != 1)
+                       return -EINVAL;
+               rc = xencomm_create_mini
+                       (xc_area, nbr_area,
+                        xen_guest_handle(setup->frame_list),
+                        setup->nr_frames 
+                        * sizeof(*xen_guest_handle(setup->frame_list)),
+                        &desc1);
+               if (rc)
+                       return rc;
+               set_xen_guest_handle(setup->frame_list, (void *)desc1);
+               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 mini grant table op %d\n", __func__, cmd);
+               BUG();
+       }
+
+       rc = xencomm_create_mini(xc_area, nbr_area, op, count * argsize, desc);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+int
+xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op,
+                                      unsigned int count)
+{
+       int rc;
+       struct xencomm_handle *desc;
+       int nbr_area = 2;
+       struct xencomm_mini xc_area[2];
+
+       rc = xencommize_mini_grant_table_op(xc_area, &nbr_area,
+                                           cmd, op, count, &desc);
+       if (rc)
+               return rc;
+
+       return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_grant_table_op);
+
+int
+xencomm_mini_hypercall_multicall(void *call_list, int nr_calls)
+{
+       int i;
+       multicall_entry_t *mce;
+       int nbr_area = 2 + nr_calls * 3;
+       struct xencomm_mini xc_area[nbr_area];
+       struct xencomm_handle *desc;
+       int rc;
+
+       for (i = 0; i < nr_calls; i++) {
+               mce = (multicall_entry_t *)call_list + i;
+
+               switch (mce->op) {
+               case __HYPERVISOR_update_va_mapping:
+               case __HYPERVISOR_mmu_update:
+                       /* No-op on ia64.  */
+                       break;
+               case __HYPERVISOR_grant_table_op:
+                       rc = xencommize_mini_grant_table_op
+                               (xc_area, &nbr_area,
+                                mce->args[0], (void *)mce->args[1],
+                                mce->args[2], &desc);
+                       if (rc)
+                               return rc;
+                       mce->args[1] = (unsigned long)desc;
+                       break;
+               case __HYPERVISOR_memory_op:
+               default:
+                       printk("%s: unhandled multicall op entry op %lu\n",
+                              __func__, mce->op);
+                       return -ENOSYS;
+               }
+       }
+
+       rc = xencomm_create_mini(xc_area, &nbr_area, call_list,
+                                nr_calls * sizeof(multicall_entry_t), &desc);
+       if (rc)
+               return rc;
+
+       return xencomm_arch_hypercall_multicall(desc, nr_calls);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_multicall);
+
+static int
+xencommize_mini_memory_reservation(struct xencomm_mini *area, int *nbr_area,
+                                   xen_memory_reservation_t *mop)
+{
+       struct xencomm_handle *desc;
+       int rc;
+
+       rc = xencomm_create_mini
+               (area, nbr_area,
+                xen_guest_handle(mop->extent_start),
+                mop->nr_extents 
+                * sizeof(*xen_guest_handle(mop->extent_start)),
+                &desc);
+       if (rc)
+               return rc;
+
+       set_xen_guest_handle(mop->extent_start, (void *)desc);
+
+       return 0;
+}
+
+int
+xencomm_mini_hypercall_memory_op(unsigned int cmd, void *arg)
+{
+       int nbr_area = 4;
+       struct xencomm_mini xc_area[4];
+       struct xencomm_handle *desc;
+       int rc;
+       unsigned int argsize;
+
+       switch (cmd) {
+       case XENMEM_increase_reservation:
+       case XENMEM_decrease_reservation:
+       case XENMEM_populate_physmap:
+               argsize = sizeof(xen_memory_reservation_t);
+               rc = xencommize_mini_memory_reservation
+                       (xc_area, &nbr_area, (xen_memory_reservation_t *)arg);
+               if (rc)
+                       return rc;
+               break;
+               
+       case XENMEM_maximum_ram_page:
+               argsize = 0;
+               break;
+
+       case XENMEM_exchange:
+               argsize = sizeof(xen_memory_exchange_t);
+               rc = xencommize_mini_memory_reservation
+                       (xc_area, &nbr_area,
+                        &((xen_memory_exchange_t *)arg)->in);
+               if (rc)
+                       return rc;
+               rc = xencommize_mini_memory_reservation
+                       (xc_area, &nbr_area,
+                        &((xen_memory_exchange_t *)arg)->out);
+               if (rc)
+                       return rc;
+               break;
+
+       default:
+               printk("%s: unknown mini memory op %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       rc = xencomm_create_mini(xc_area, &nbr_area, arg, argsize, &desc);
+       if (rc)
+               return rc;
+
+       return xencomm_arch_hypercall_memory_op(cmd, desc);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_memory_op);
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c Mon Oct 02 14:03:42 
2006 -0600
@@ -0,0 +1,573 @@
+/*
+ * 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.
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ *          Tristan Gingold <tristan.gingold@xxxxxxxx>
+ */
+#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>
+#define __XEN__
+#include <xen/interface/domctl.h>
+#include <xen/interface/sysctl.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/version.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/acm_ops.h>
+#include <xen/interface/hvm/params.h>
+#include <xen/public/privcmd.h>
+#include <asm/hypercall.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/xen/xencomm.h>
+
+#define ROUND_DIV(v,s) (((v) + (s) - 1) / (s))
+
+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_handle *op_desc;
+       struct xencomm_handle *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);
+
+       switch (kern_op.cmd) {
+       default:
+               printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
+               return -ENOSYS;
+       }
+
+       if (ret) {
+               /* error mapping the nested pointer */
+               return ret;
+       }
+
+       ret = xencomm_arch_hypercall_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);
+       return ret;
+}
+
+static int
+xencomm_privcmd_sysctl(privcmd_hypercall_t *hypercall)
+{
+       xen_sysctl_t kern_op;
+       xen_sysctl_t __user *user_op;
+       struct xencomm_handle *op_desc;
+       struct xencomm_handle *desc = NULL;
+       struct xencomm_handle *desc1 = NULL;
+       int ret = 0;
+
+       user_op = (xen_sysctl_t __user *)hypercall->arg[0];
+
+       if (copy_from_user(&kern_op, user_op, sizeof(xen_sysctl_t)))
+               return -EFAULT;
+
+       if (kern_op.interface_version != XEN_SYSCTL_INTERFACE_VERSION)
+               return -EACCES;
+
+       op_desc = xencomm_create_inline(&kern_op);
+
+       switch (kern_op.cmd) {
+       case XEN_SYSCTL_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 *)desc);
+               break;
+       case XEN_SYSCTL_tbuf_op:
+       case XEN_SYSCTL_physinfo:
+       case XEN_SYSCTL_sched_id:
+               break;
+       case XEN_SYSCTL_perfc_op:
+               ret = xencomm_create(
+                       xen_guest_handle(kern_op.u.perfc_op.desc),
+                       kern_op.u.perfc_op.nr_counters *
+                       sizeof(xen_sysctl_perfc_desc_t),
+                       &desc, GFP_KERNEL);
+               if (ret)
+                       return ret;
+               set_xen_guest_handle(kern_op.u.perfc_op.val,
+                                    (void *)desc);
+               ret = xencomm_create(
+                       xen_guest_handle(kern_op.u.perfc_op.val),
+                       kern_op.u.perfc_op.nr_vals *
+                       sizeof(xen_sysctl_perfc_desc_t),
+                       &desc1, GFP_KERNEL);
+               if (ret)
+                       xencomm_free(desc);
+               set_xen_guest_handle(kern_op.u.perfc_op.val,
+                                    (void *)desc1);
+               break;
+       case XEN_SYSCTL_getdomaininfolist:
+               ret = xencomm_create(
+                       xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
+                       kern_op.u.getdomaininfolist.max_domains *
+                       sizeof(xen_domctl_getdomaininfo_t),
+                       &desc, GFP_KERNEL);
+               set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
+                                    (void *)desc);
+               break;
+       default:
+               printk("%s: unknown sysctl cmd %d\n", __func__, kern_op.cmd);
+               return -ENOSYS;
+       }
+
+       if (ret) {
+               /* error mapping the nested pointer */
+               return ret;
+       }
+
+       ret = xencomm_arch_hypercall_sysctl(op_desc);
+
+       /* FIXME: should we restore the handle?  */
+       if (copy_to_user(user_op, &kern_op, sizeof(xen_sysctl_t)))
+               ret = -EFAULT;
+
+       if (desc)
+               xencomm_free(desc);
+       if (desc1)
+               xencomm_free(desc1);
+       return ret;
+}
+
+static int
+xencomm_privcmd_domctl(privcmd_hypercall_t *hypercall)
+{
+       xen_domctl_t kern_op;
+       xen_domctl_t __user *user_op;
+       struct xencomm_handle *op_desc;
+       struct xencomm_handle *desc = NULL;
+       int ret = 0;
+
+       user_op = (xen_domctl_t __user *)hypercall->arg[0];
+
+       if (copy_from_user(&kern_op, user_op, sizeof(xen_domctl_t)))
+               return -EFAULT;
+
+       if (kern_op.interface_version != XEN_DOMCTL_INTERFACE_VERSION)
+               return -EACCES;
+
+       op_desc = xencomm_create_inline(&kern_op);
+
+       switch (kern_op.cmd) {
+       case XEN_DOMCTL_createdomain:
+       case XEN_DOMCTL_destroydomain:
+       case XEN_DOMCTL_pausedomain:
+       case XEN_DOMCTL_unpausedomain:
+       case XEN_DOMCTL_getdomaininfo:
+               break;
+       case XEN_DOMCTL_getmemlist:
+       {
+               unsigned long nr_pages = kern_op.u.getmemlist.max_pfns;
+#ifdef __ia64__
+               /* FIXME: 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 *)desc);
+               break;
+       }
+       case XEN_DOMCTL_getpageframeinfo:
+               break;
+       case XEN_DOMCTL_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 *)desc);
+               break;
+       case XEN_DOMCTL_shadow_op:
+               ret = xencomm_create(
+                       xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap),
+                       ROUND_DIV(kern_op.u.shadow_op.pages, 8),
+                       &desc, GFP_KERNEL);
+               set_xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap,
+                                    (void *)desc);
+               break;
+       case XEN_DOMCTL_max_mem:
+               break;
+       case XEN_DOMCTL_setvcpucontext:
+       case XEN_DOMCTL_getvcpucontext:
+               ret = xencomm_create(
+                       xen_guest_handle(kern_op.u.vcpucontext.ctxt),
+                       sizeof(vcpu_guest_context_t),
+                       &desc, GFP_KERNEL);
+               set_xen_guest_handle(kern_op.u.vcpucontext.ctxt, (void *)desc);
+               break;
+       case XEN_DOMCTL_getvcpuinfo:
+               break;
+       case XEN_DOMCTL_setvcpuaffinity:
+       case XEN_DOMCTL_getvcpuaffinity:
+               ret = xencomm_create(
+                       xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap),
+                       ROUND_DIV(kern_op.u.vcpuaffinity.cpumap.nr_cpus, 8),
+                       &desc, GFP_KERNEL);
+               set_xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap,
+                                    (void *)desc);
+               break;
+       case XEN_DOMCTL_max_vcpus:
+       case XEN_DOMCTL_scheduler_op:
+       case XEN_DOMCTL_setdomainhandle:
+       case XEN_DOMCTL_setdebugging:
+       case XEN_DOMCTL_irq_permission:
+       case XEN_DOMCTL_iomem_permission:
+       case XEN_DOMCTL_ioport_permission:
+       case XEN_DOMCTL_hypercall_init:
+       case XEN_DOMCTL_arch_setup:
+       case XEN_DOMCTL_settimeoffset:
+               break;
+       default:
+               printk("%s: unknown domctl cmd %d\n", __func__, kern_op.cmd);
+               return -ENOSYS;
+       }
+
+       if (ret) {
+               /* error mapping the nested pointer */
+               return ret;
+       }
+
+       ret = xencomm_arch_hypercall_domctl (op_desc);
+
+       /* FIXME: should we restore the handle?  */
+       if (copy_to_user(user_op, &kern_op, sizeof(xen_domctl_t)))
+               ret = -EFAULT;
+
+       if (desc)
+               xencomm_free(desc);
+       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_handle *op_desc;
+       struct xencomm_handle *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);
+
+               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 *)desc);
+
+               ret = xencomm_arch_hypercall_acm_op(cmd, 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:
+       case XENMEM_populate_physmap:
+       {
+               xen_memory_reservation_t kern_op;
+               xen_memory_reservation_t __user *user_op;
+               struct xencomm_handle *desc = NULL;
+               struct xencomm_handle *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);
+
+               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 *)desc);
+               }
+
+               ret = xencomm_arch_hypercall_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;
+       }
+       case XENMEM_translate_gpfn_list:
+       {
+               xen_translate_gpfn_list_t kern_op;
+               xen_translate_gpfn_list_t __user *user_op;
+               struct xencomm_handle *desc_gpfn = NULL;
+               struct xencomm_handle *desc_mfn = NULL;
+               struct xencomm_handle *desc_op;
+               void *addr;
+
+               user_op = (xen_translate_gpfn_list_t __user *)
+                       hypercall->arg[1];
+               if (copy_from_user(&kern_op, user_op,
+                                  sizeof(xen_translate_gpfn_list_t)))
+                       return -EFAULT;
+               desc_op = xencomm_create_inline(&kern_op);
+
+               if (kern_op.nr_gpfns) {
+                       /* gpfn_list.  */
+                       addr = xen_guest_handle(kern_op.gpfn_list);
+
+                       ret = xencomm_create(addr, kern_op.nr_gpfns *
+                                            sizeof(*xen_guest_handle
+                                                   (kern_op.gpfn_list)),
+                                            &desc_gpfn, GFP_KERNEL);
+                       if (ret)
+                               return ret;
+                       set_xen_guest_handle(kern_op.gpfn_list,
+                                            (void *)desc_gpfn);
+
+                       /* mfn_list.  */
+                       addr = xen_guest_handle(kern_op.mfn_list);
+
+                       ret = xencomm_create(addr, kern_op.nr_gpfns *
+                                            sizeof(*xen_guest_handle
+                                                   (kern_op.mfn_list)),
+                                            &desc_mfn, GFP_KERNEL);
+                       if (ret)
+                               return ret;
+                       set_xen_guest_handle(kern_op.mfn_list,
+                                            (void *)desc_mfn);
+               }
+
+               ret = xencomm_arch_hypercall_memory_op(cmd, desc_op);
+
+               if (desc_gpfn)
+                       xencomm_free(desc_gpfn);
+
+               if (desc_mfn)
+                       xencomm_free(desc_mfn);
+
+               if (ret != 0)
+                       return ret;
+
+               return ret;
+       }
+       default:
+               printk("%s: unknown memory op %lu\n", __func__, cmd);
+               ret = -ENOSYS;
+       }
+       return ret;
+}
+
+static int
+xencomm_privcmd_xen_version(privcmd_hypercall_t *hypercall)
+{
+       int cmd = hypercall->arg[0];
+       void __user *arg = (void __user *)hypercall->arg[1];
+       struct xencomm_handle *desc;
+       size_t argsize;
+       int rc;
+
+       switch (cmd) {
+       case XENVER_version:
+               /* do not actually pass an argument */
+               return xencomm_arch_hypercall_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 = xencomm_arch_hypercall_xen_version(cmd, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+}
+
+static int
+xencomm_privcmd_event_channel_op(privcmd_hypercall_t *hypercall)
+{
+       int cmd = hypercall->arg[0];
+       struct xencomm_handle *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 = xencomm_arch_hypercall_event_channel_op(cmd, desc);
+
+       xencomm_free(desc);
+       return ret;
+}
+
+static int
+xencomm_privcmd_hvm_op(privcmd_hypercall_t *hypercall)
+{
+       int cmd = hypercall->arg[0];
+       struct xencomm_handle *desc;
+       unsigned int argsize;
+       int ret;
+
+       switch (cmd) {
+       case HVMOP_get_param:
+       case HVMOP_set_param:
+               argsize = sizeof(xen_hvm_param_t);
+               break;
+       default:
+               printk("%s: unknown HVMOP %d\n", __func__, cmd);
+               return -EINVAL;
+       }
+
+       ret = xencomm_create((void *)hypercall->arg[1], argsize,
+                            &desc, GFP_KERNEL);
+       if (ret)
+               return ret;
+
+       ret = xencomm_arch_hypercall_hvm_op(cmd, desc);
+
+       xencomm_free(desc);
+       return ret;
+}
+
+int
+privcmd_hypercall(privcmd_hypercall_t *hypercall)
+{
+       switch (hypercall->op) {
+       case __HYPERVISOR_dom0_op:
+               return xencomm_privcmd_dom0_op(hypercall);
+       case __HYPERVISOR_domctl:
+               return xencomm_privcmd_domctl(hypercall);
+       case __HYPERVISOR_sysctl:
+               return xencomm_privcmd_sysctl(hypercall);
+        case __HYPERVISOR_acm_op:
+               return xencomm_privcmd_acm_op(hypercall);
+       case __HYPERVISOR_xen_version:
+               return xencomm_privcmd_xen_version(hypercall);
+       case __HYPERVISOR_memory_op:
+               return xencomm_privcmd_memory_op(hypercall);
+       case __HYPERVISOR_event_channel_op:
+               return xencomm_privcmd_event_channel_op(hypercall);
+       case __HYPERVISOR_hvm_op:
+               return xencomm_privcmd_hvm_op(hypercall);
+       default:
+               printk("%s: unknown hcall (%ld)\n", __func__, hypercall->op);
+               return -ENOSYS;
+       }
+}
+
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c      Mon Oct 02 14:03:42 
2006 -0600
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <hollisb@xxxxxxxxxx>, 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 <asm/xen/xencomm.h>
+#include <xen/interface/xen.h>
+
+static int xencomm_debug = 0;
+
+/* Translate virtual address to physical address.  */
+unsigned long
+xencomm_vaddr_to_paddr(unsigned long vaddr)
+{
+       struct page *page;
+       struct vm_area_struct *vma;
+
+       if (vaddr == 0)
+               return 0;
+
+#ifdef __ia64__
+       if (REGION_NUMBER(vaddr) == 5) {
+               pgd_t *pgd;
+               pud_t *pud;
+               pmd_t *pmd;
+               pte_t *ptep;
+
+               /* On ia64, TASK_SIZE refers to current.  It is not initialized
+                  during boot.
+                  Furthermore the kernel is relocatable and __pa() doesn't
+                  work on  addresses.  */
+               if (vaddr >= KERNEL_START
+                   && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) {
+                       extern unsigned long kernel_start_pa;
+                       
+                       return vaddr - kernel_start_pa;
+               }
+
+               /* In kernel area -- virtually mapped.  */
+               pgd = pgd_offset_k(vaddr);
+               if (pgd_none(*pgd) || pgd_bad(*pgd))
+                       return ~0UL;
+
+               pud = pud_offset(pgd, vaddr);
+               if (pud_none(*pud) || pud_bad(*pud))
+                       return ~0UL;
+
+               pmd = pmd_offset(pud, vaddr);
+               if (pmd_none(*pmd) || pmd_bad(*pmd))
+                       return ~0UL;
+
+               ptep = pte_offset_kernel(pmd, vaddr);
+               if (!ptep)
+                       return ~0UL;
+
+               return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK);
+       }
+#endif
+
+       if (vaddr > TASK_SIZE) {
+               /* kernel address */
+               return __pa(vaddr);
+       }
+
+       /* XXX double-check (lack of) locking */
+       vma = find_extend_vma(current->mm, vaddr);
+       if (!vma)
+               return ~0UL;
+
+       /* We assume the page is modified.  */
+       page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH);
+       if (!page)
+               return ~0UL;
+
+       return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+}
+
+static int
+xencomm_init(struct xencomm_desc *desc, void *buffer, unsigned long bytes)
+{
+       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 = xencomm_vaddr_to_paddr(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;
+}
+
+static struct xencomm_desc *
+xencomm_alloc(gfp_t gfp_mask)
+{
+       struct xencomm_desc *desc;
+
+       desc = (struct xencomm_desc *)__get_free_page(gfp_mask);
+       if (desc == NULL)
+               panic("%s: page allocation failed\n", __func__);
+
+       desc->nr_addrs = (PAGE_SIZE - sizeof(struct xencomm_desc)) /
+                        sizeof(*desc->address);
+
+       return desc;
+}
+
+void
+xencomm_free(struct xencomm_handle *desc)
+{
+       if (desc)
+               free_page((unsigned long)__va(desc));
+}
+
+int
+xencomm_create(void *buffer, unsigned long bytes,
+               struct xencomm_handle **ret, gfp_t gfp_mask)
+{
+       struct xencomm_desc *desc;
+       struct xencomm_handle *handle;
+       int rc;
+
+       if (xencomm_debug)
+               printk("%s: %p[%ld]\n", __func__, buffer, bytes);
+
+       if (buffer == NULL || bytes == 0) {
+               *ret = (struct xencomm_handle *)NULL;
+               return 0;
+       }
+
+       desc = xencomm_alloc(gfp_mask);
+       if (!desc) {
+               printk("%s failure\n", "xencomm_alloc");
+               return -ENOMEM;
+       }
+       handle = (struct xencomm_handle *)__pa(desc);
+
+       rc = xencomm_init(desc, buffer, bytes);
+       if (rc) {
+               printk("%s failure: %d\n", "xencomm_init", rc);
+               xencomm_free(handle);
+               return rc;
+       }
+
+       *ret = handle;
+       return 0;
+}
+
+/* "mini" routines, for stack-based communications: */
+
+static void *
+xencomm_alloc_mini(struct xencomm_mini *area, int *nbr_area)
+{
+       unsigned long base;
+       unsigned int pageoffset;
+
+       while (*nbr_area >= 0) {
+               /* Allocate an area.  */
+               (*nbr_area)--;
+
+               base = (unsigned long)(area + *nbr_area);
+               pageoffset = base % PAGE_SIZE;
+
+               /* If the area does not cross a page, use it.  */
+               if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini))
+                       return &area[*nbr_area];
+       }
+       /* No more area.  */
+       return NULL;
+}
+
+int
+xencomm_create_mini(struct xencomm_mini *area, int *nbr_area,
+                    void *buffer, unsigned long bytes,
+                    struct xencomm_handle **ret)
+{
+       struct xencomm_desc *desc;
+       int rc;
+       unsigned long res;
+
+       desc = xencomm_alloc_mini(area, nbr_area);
+       if (!desc)
+               return -ENOMEM;
+       desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+       rc = xencomm_init(desc, buffer, bytes);
+       if (rc)
+               return rc;
+
+       res = xencomm_vaddr_to_paddr((unsigned long)desc);
+       if (res == ~0UL)
+               return -EINVAL;
+
+       *ret = (struct xencomm_handle*)res;
+       return 0;
+}
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h    Mon Oct 02 
14:03:42 2006 -0600
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2006 Tristan Gingold <tristan.gingold@xxxxxxxx>, Bull SAS
+ *
+ * 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_HCALL_H_
+#define _LINUX_XENCOMM_HCALL_H_
+
+/* These function creates inline descriptor for the parameters and
+   calls the corresponding xencomm_arch_hypercall_X.
+   Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless
+   they want to use their own wrapper.  */
+extern int xencomm_hypercall_console_io(int cmd, int count, char *str);
+
+extern int xencomm_hypercall_event_channel_op(int cmd, void *op);
+
+extern int xencomm_hypercall_xen_version(int cmd, void *arg);
+
+extern int xencomm_hypercall_physdev_op(int cmd, void *op);
+
+extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
+                                            unsigned int count);
+
+extern int xencomm_hypercall_sched_op(int cmd, void *arg);
+
+extern int xencomm_hypercall_multicall(void *call_list, int nr_calls);
+
+extern int xencomm_hypercall_callback_op(int cmd, void *arg);
+
+extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg);
+
+extern unsigned long xencomm_hypercall_hvm_op(int cmd, void *arg);
+
+extern int xencomm_hypercall_suspend(unsigned long srec);
+
+/* Using mini xencomm.  */
+extern int xencomm_mini_hypercall_console_io(int cmd, int count, char *str);
+
+extern int xencomm_mini_hypercall_event_channel_op(int cmd, void *op);
+
+extern int xencomm_mini_hypercall_xen_version(int cmd, void *arg);
+
+extern int xencomm_mini_hypercall_physdev_op(int cmd, void *op);
+
+extern int xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op,
+                                                 unsigned int count);
+
+extern int xencomm_mini_hypercall_sched_op(int cmd, void *arg);
+
+extern int xencomm_mini_hypercall_multicall(void *call_list, int nr_calls);
+
+extern int xencomm_mini_hypercall_callback_op(int cmd, void *arg);
+
+extern int xencomm_mini_hypercall_memory_op(unsigned int cmd, void *arg);
+
+/* For privcmd.  Locally declare argument type to avoid include storm.
+   Type coherency will be checked within privcmd.c  */
+struct privcmd_hypercall;
+extern int privcmd_hypercall(struct privcmd_hypercall *hypercall);
+
+#endif /* _LINUX_XENCOMM_HCALL_H_ */
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 
linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h       Mon Oct 02 
14:03:42 2006 -0600
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <hollisb@xxxxxxxxxx>, 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];
+};
+
+/* To avoid additionnal virt to phys conversion, an opaque structure is
+   presented.  */
+struct xencomm_handle;
+
+extern int xencomm_create(void *buffer, unsigned long bytes,
+                          struct xencomm_handle **desc, gfp_t type);
+extern void xencomm_free(struct xencomm_handle *desc);
+
+extern int xencomm_create_mini(struct xencomm_mini *area, int *nbr_area,
+                               void *buffer, unsigned long bytes,
+                               struct xencomm_handle **ret);
+
+/* Translate virtual address to physical address.  */
+extern unsigned long xencomm_vaddr_to_paddr(unsigned long vaddr);
+
+/* Inline version.  To be used only on linear space (kernel space).  */
+static inline struct xencomm_handle *
+xencomm_create_inline(void *buffer)
+{
+       unsigned long paddr;
+
+       paddr = xencomm_vaddr_to_paddr((unsigned long)buffer);
+       return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
+}
+
+#define xen_guest_handle(hnd)  ((hnd).p)
+
+#endif /* _LINUX_XENCOMM_H_ */
diff -r 2bfd19fc1b79 -r 5c97ef4c7147 xen/arch/ia64/xen/xencomm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/xencomm.c       Mon Oct 02 14:03:42 2006 -0600
@@ -0,0 +1,380 @@
+/*
+ * 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 <hollisb@xxxxxxxxxx>
+ *          Tristan Gingold <tristan.gingold@xxxxxxxx>
+ */
+
+#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>
+#include <xen/errno.h>
+
+#undef DEBUG
+#ifdef DEBUG
+static int xencomm_debug = 1; /* extremely verbose */
+#else
+#define xencomm_debug 0
+#endif
+
+static int
+xencomm_copy_chunk_from(
+    unsigned long to,
+    unsigned long paddr,
+    unsigned int  len)
+{
+    unsigned long maddr;
+    struct page_info *page;
+
+    while (1) {
+       maddr = xencomm_paddr_to_maddr(paddr);
+       if (xencomm_debug > 1)
+           printk("%lx[%d] -> %lx\n", maddr, len, to);
+       if (maddr == 0)
+           return -EFAULT;
+
+       page = virt_to_page(maddr);
+       if (get_page(page, current->domain) == 0) {
+           if (page_get_owner(page) != current->domain) {
+               /* This page might be a page granted by another domain  */
+               panic_domain(NULL, "copy_from_guest from foreign domain\n");
+           }
+           /* Try again.  */
+           continue;
+       }
+       memcpy((void *)to, (void *)maddr, len);
+       put_page(page);
+       return 0;
+    }
+}
+
+/**
+ * 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 long desc_addr;
+    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 (XENCOMM_IS_INLINE(from)) {
+        unsigned long src_paddr = XENCOMM_INLINE_ADDR(from);
+            
+        src_paddr += skip;
+
+        while (n > 0) {
+            unsigned int chunksz;
+            unsigned int bytes;
+           int res;
+            
+            chunksz = PAGE_SIZE - (src_paddr % PAGE_SIZE);
+            
+            bytes = min(chunksz, n);
+
+            res = xencomm_copy_chunk_from((unsigned long)to, src_paddr, bytes);
+           if (res != 0)
+               return -EFAULT;
+            src_paddr += bytes;
+            to += bytes;
+            n -= bytes;
+        }
+        
+        /* Always successful.  */
+        return 0;
+    }
+
+    /* first we need to access the descriptor */
+    desc_addr = xencomm_paddr_to_maddr((unsigned long)from);
+    if (desc_addr == 0)
+        return -EFAULT;
+
+    desc = (struct xencomm_desc *)desc_addr;
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s: error: %p magic was 0x%x\n",
+               __func__, desc, desc->magic);
+        return -EFAULT;
+    }
+
+    /* 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 int bytes = min(chunksz, n - to_pos);
+           int res;
+
+            if (xencomm_debug > 1)
+                printf ("src_paddr=%lx i=%d, skip=%d\n",
+                        src_paddr, i, chunk_skip);
+
+            res = xencomm_copy_chunk_from((unsigned long)to + to_pos,
+                                          src_paddr + chunk_skip, bytes);
+            if (res != 0)
+                return -EFAULT;
+
+            from_pos += bytes;
+            to_pos += bytes;
+        }
+
+        i++;
+    }
+
+    return n - to_pos;
+}
+
+static int
+xencomm_copy_chunk_to(
+    unsigned long paddr,
+    unsigned long from,
+    unsigned int  len)
+{
+    unsigned long maddr;
+    struct page_info *page;
+
+    while (1) {
+       maddr = xencomm_paddr_to_maddr(paddr);
+       if (xencomm_debug > 1)
+           printk("%lx[%d] -> %lx\n", from, len, maddr);
+       if (maddr == 0)
+           return -EFAULT;
+
+       page = virt_to_page(maddr);
+       if (get_page(page, current->domain) == 0) {
+           if (page_get_owner(page) != current->domain) {
+               /* This page might be a page granted by another domain  */
+               panic_domain(NULL, "copy_to_guest to foreign domain\n");
+           }
+           /* Try again.  */
+           continue;
+       }
+       memcpy((void *)maddr, (void *)from, len);
+       put_page(page);
+       return 0;
+    }
+}
+
+/**
+ * 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 long desc_addr;
+    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 (XENCOMM_IS_INLINE(to)) {
+        unsigned long dest_paddr = XENCOMM_INLINE_ADDR(to);
+            
+        dest_paddr += skip;
+
+        while (n > 0) {
+            unsigned int chunksz;
+            unsigned int bytes;
+            int res;
+
+            chunksz = PAGE_SIZE - (dest_paddr % PAGE_SIZE);
+            
+            bytes = min(chunksz, n);
+
+            res = xencomm_copy_chunk_to(dest_paddr, (unsigned long)from, 
bytes);
+            if (res != 0)
+                return res;
+
+            dest_paddr += bytes;
+            from += bytes;
+            n -= bytes;
+        }
+
+        /* Always successful.  */
+        return 0;
+    }
+
+    /* first we need to access the descriptor */
+    desc_addr = xencomm_paddr_to_maddr((unsigned long)to);
+    if (desc_addr == 0)
+        return -EFAULT;
+
+    desc = (struct xencomm_desc *)desc_addr;
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+        return -EFAULT;
+    }
+
+    /* 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;
+        dest_paddr += chunk_skip;
+
+        if (skip == 0) {
+            unsigned int bytes = min(chunksz, n - from_pos);
+            int res;
+
+            res = xencomm_copy_chunk_to(dest_paddr,
+                                        (unsigned long)from + from_pos, bytes);
+            if (res != 0)
+                return res;
+
+            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;
+    unsigned long desc_addr;
+    int i = 0;
+
+    if (XENCOMM_IS_INLINE(handle))
+        return (void *)((unsigned long)handle + bytes);
+
+    /* first we need to access the descriptor */
+    desc_addr = xencomm_paddr_to_maddr((unsigned long)handle);
+    if (desc_addr == 0)
+        return NULL;
+
+    desc = (struct xencomm_desc *)desc_addr;
+    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)
+{
+    if (XENCOMM_IS_INLINE(ptr))
+        return XENCOMM_INLINE_ADDR(ptr) == 0;
+    else {
+        struct xencomm_desc *desc;
+        unsigned long desc_addr;
+
+        desc_addr = xencomm_paddr_to_maddr((unsigned long)ptr);
+        if (desc_addr == 0)
+            return 1;
+
+        desc = (struct xencomm_desc *)desc_addr;
+        return (desc->address[0] == XENCOMM_INVALID);
+    }
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.