WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [IA64] Use xencomm for hypercalls.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 26 Oct 2006 12:10:31 +0000
Delivery-date: Thu, 26 Oct 2006 05:12:27 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [IA64] Use xencomm for hypercalls., Xen patchbot-unstable <=