# HG changeset patch
# User Jimi Xenidis <[EMAIL PROTECTED]>
# Node ID 5eca8383a521939f0d74e68eaddb049c5057742a
# Parent  ab3b5849331da89e578ae0813021376d66b7f333
[XEN] xencomm fixes for various runtime situations

This patch makes xencomm safe for all allocations scenarios including:
 - too early to use allocator
 - in IRQ
 - Recognize when inline can be used
 - vmalloc()
 - Automatic use of the xencomm_mini when the number of pages is small.

Signed-off-by: Jerone Young <[EMAIL PROTECTED]>
Signed-off-by: Jimi Xenidis <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/xen/gnttab.c |   21 ++
 arch/powerpc/platforms/xen/hcall.c  |  283 ++++++++++++++++++++++--------------
 arch/powerpc/platforms/xen/setup.c  |    2 
 drivers/xen/core/xencomm.c          |   73 ++++++++-
 include/xen/xencomm.h               |   20 ++
 5 files changed, 280 insertions(+), 119 deletions(-)

diff -r ab3b5849331d -r 5eca8383a521 arch/powerpc/platforms/xen/gnttab.c
--- a/arch/powerpc/platforms/xen/gnttab.c       Sun Jan 21 08:36:53 2007 -0500
+++ b/arch/powerpc/platforms/xen/gnttab.c       Tue Feb 06 16:21:30 2007 -0500
@@ -244,8 +244,8 @@ static void gnttab_post_map_grant_ref(
 
 int HYPERVISOR_grant_table_op(unsigned int cmd, void *op, unsigned int count)
 {
-       void *desc;
-       void *frame_list;
+       void *desc = NULL;
+       void *frame_list = NULL;
        int argsize;
        int ret;
 
@@ -263,8 +263,13 @@ int HYPERVISOR_grant_table_op(unsigned i
                memcpy(&setup, op, sizeof(setup));
                argsize = sizeof(setup);
 
-               frame_list = xencomm_create_inline(
-                       xen_guest_handle(setup.frame_list));
+               frame_list = xencomm_map(
+                       xen_guest_handle(setup.frame_list),
+                       (sizeof(*xen_guest_handle(setup.frame_list)) 
+                       * setup.nr_frames));
+
+               if (frame_list == NULL)
+                       return -ENOMEM;
 
                set_xen_guest_handle(setup.frame_list, frame_list);
                memcpy(op, &setup, sizeof(setup));
@@ -286,12 +291,18 @@ int HYPERVISOR_grant_table_op(unsigned i
                return -ENOSYS;
        }
 
-       desc = xencomm_create_inline(op);
+       desc = xencomm_map_no_alloc(op, argsize);
+
+       if (desc == NULL)
+               return -ENOSPC;
 
        ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_grant_table_op), cmd,
                                 desc, count);
        if (cmd == GNTTABOP_map_grant_ref)
                gnttab_post_map_grant_ref(op, count);
+
+       xencomm_free(frame_list);
+       xencomm_free(desc);
 
        return ret;
 }
diff -r ab3b5849331d -r 5eca8383a521 arch/powerpc/platforms/xen/hcall.c
--- a/arch/powerpc/platforms/xen/hcall.c        Sun Jan 21 08:36:53 2007 -0500
+++ b/arch/powerpc/platforms/xen/hcall.c        Tue Feb 06 16:21:30 2007 -0500
@@ -54,25 +54,43 @@
 
 int HYPERVISOR_console_io(int cmd, int count, char *str)
 {
-       void *desc = xencomm_create_inline(str);
-
-       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_console_io),
+       int rc;
+
+       void *desc = xencomm_map_no_alloc(str, count); 
+
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_console_io),
                                  cmd, count, desc);
+
+       xencomm_free(desc);
+
+       return rc;
 }
 EXPORT_SYMBOL(HYPERVISOR_console_io);
 
 int HYPERVISOR_event_channel_op(int cmd, void *op)
 {
-       void *desc = xencomm_create_inline(op);
-
-       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_event_channel_op),
+       int rc;
+
+       void *desc = xencomm_map_no_alloc(op, sizeof(evtchn_op_t));
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_event_channel_op),
                                cmd, desc);
+
+       xencomm_free(desc);
+       
+       return rc;
+
 }
 EXPORT_SYMBOL(HYPERVISOR_event_channel_op);
 
-int HYPERVISOR_xen_version_userspace(int cmd, void *arg)
-{
-       struct xencomm_desc *desc;
+int HYPERVISOR_xen_version(int cmd, void *arg)
+{
+       void *desc;
        const unsigned long hcall = __HYPERVISOR_xen_version;
        int argsize;
        int rc;
@@ -97,7 +115,10 @@ int HYPERVISOR_xen_version_userspace(int
                argsize = sizeof(xen_platform_parameters_t);
                break;
        case XENVER_pagesize:
-               argsize = (arg == NULL) ? 0 : sizeof(void *);
+               if (arg == NULL)
+                       argsize = 0;
+               else
+                       argsize = sizeof(void *);
                break;
        case XENVER_get_features:
                argsize = sizeof(xen_feature_info_t);
@@ -107,38 +128,41 @@ int HYPERVISOR_xen_version_userspace(int
                return -ENOSYS;
        }
 
-       rc = xencomm_create(arg, argsize, &desc, GFP_KERNEL);
-       if (rc)
-               return rc;
-
-       rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, xencomm_pa(desc));
-
-       xencomm_free(desc);
+       /* desc could be NULL in the case of XENVER_pagesize with NULL arg */
+       desc = xencomm_map(arg, argsize);
+
+       rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, desc);
+
+       xencomm_free(desc);     
+
        return rc;
 }
 EXPORT_SYMBOL(HYPERVISOR_xen_version);
 
-int HYPERVISOR_xen_version(int cmd, void *arg)
-{
-       if (is_kernel_addr((unsigned long)arg)) {
-               void *desc = xencomm_create_inline(arg);
-               return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_xen_version), 
cmd, desc);
-       }
-       return HYPERVISOR_xen_version_userspace(cmd, arg);
-}
 
 int HYPERVISOR_physdev_op(int cmd, void *op)
 {
-       void *desc = xencomm_create_inline(op);
-
-       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_physdev_op),
+       void *desc = xencomm_map_no_alloc(op, sizeof(physdev_op_t)); 
+       int rc;
+
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_physdev_op),
                                cmd, desc);
+
+       xencomm_free(desc);
+
+       return rc;
 }
 EXPORT_SYMBOL(HYPERVISOR_physdev_op);
 
 int HYPERVISOR_sched_op(int cmd, void *arg)
 {
-       struct xencomm_desc *desc;
+       int argsize = 0;
+       int rc;
+       void *desc;
+       evtchn_port_t *ports = NULL;
 
        switch (cmd) {
        case SCHEDOP_yield:
@@ -148,30 +172,46 @@ int HYPERVISOR_sched_op(int cmd, void *a
                break;
 
        case SCHEDOP_poll: {
-               evtchn_port_t *ports;
                struct sched_poll sched_poll;
 
+               argsize = sizeof(struct sched_poll);
+
                memcpy(&sched_poll, arg, sizeof(sched_poll));
 
-               ports = xencomm_create_inline(
-                       xen_guest_handle(sched_poll.ports));
+               ports = xencomm_map(
+                               xen_guest_handle(sched_poll.ports),
+                               (sizeof(evtchn_port_t) * sched_poll.nr_ports));
+
+               if (ports == NULL)
+                       return -ENOMEM;
+
                set_xen_guest_handle(sched_poll.ports, ports);
                memcpy(arg, &sched_poll, sizeof(sched_poll));
                
        }
                break;
        case SCHEDOP_shutdown:
+               argsize = sizeof(struct sched_shutdown);
+               break;
        case SCHEDOP_remote_shutdown:
+               argsize = sizeof(struct sched_remote_shutdown);
                break;
        default:
                printk(KERN_ERR "%s: unknown sched op %d\n", __func__, cmd);
                return -ENOSYS;
        }
 
-       desc = xencomm_create_inline(arg);
-
-       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
+       desc = xencomm_map_no_alloc(arg, argsize); 
+
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
                                cmd, desc);
+
+       xencomm_free(ports);
+
+       return rc;
 }
 EXPORT_SYMBOL(HYPERVISOR_sched_op);
 
@@ -233,8 +273,8 @@ static int xenppc_privcmd_domctl(privcmd
 {
        xen_domctl_t kern_op;
        xen_domctl_t __user *user_op = (xen_domctl_t __user *)hypercall->arg[0];
-       struct xencomm_desc *op_desc;
-       struct xencomm_desc *desc = NULL;
+       void *op_desc;
+       void *desc = NULL;
        int ret = 0;
 
        if (copy_from_user(&kern_op, user_op, sizeof(xen_domctl_t)))
@@ -246,9 +286,9 @@ static int xenppc_privcmd_domctl(privcmd
                return -EACCES;
        }
 
-       ret = xencomm_create(&kern_op, sizeof(xen_domctl_t), &op_desc, 
GFP_KERNEL);
-       if (ret)
-               return ret;
+       op_desc = xencomm_map(&kern_op, sizeof(xen_domctl_t));
+       if (op_desc == NULL)
+               return -ENOMEM;
 
        switch (kern_op.cmd) {
        case XEN_DOMCTL_createdomain:
@@ -258,52 +298,71 @@ static int xenppc_privcmd_domctl(privcmd
        case XEN_DOMCTL_getdomaininfo:
                break;
        case XEN_DOMCTL_getmemlist:
-               ret = xencomm_create(
+               desc = xencomm_map(
                        xen_guest_handle(kern_op.u.getmemlist.buffer),
-                       kern_op.u.getmemlist.max_pfns * sizeof(unsigned long),
-                       &desc, GFP_KERNEL);
+                       kern_op.u.getmemlist.max_pfns * sizeof(unsigned long));
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
                set_xen_guest_handle(kern_op.u.getmemlist.buffer,
-                                    xencomm_pa(desc));
+                                    desc);
                break;
        case XEN_DOMCTL_getpageframeinfo:
                break;
        case XEN_DOMCTL_getpageframeinfo2:
-               ret = xencomm_create(
+               desc = xencomm_map(
                        xen_guest_handle(kern_op.u.getpageframeinfo2.array),
-                       kern_op.u.getpageframeinfo2.num,
-                       &desc, GFP_KERNEL);
+                       kern_op.u.getpageframeinfo2.num);
+               
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
                set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
-                                    xencomm_pa(desc));
+                                    desc);
                break;
        case XEN_DOMCTL_shadow_op:
-               ret = xencomm_create(
-                       xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap),
-                       kern_op.u.shadow_op.pages * sizeof(unsigned long),
-                       &desc, GFP_KERNEL);
-               set_xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap,
-                                    xencomm_pa(desc));
+
+               if (xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap))
+               {
+                       desc = xencomm_map(
+                               
xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap),
+                               kern_op.u.shadow_op.pages * sizeof(unsigned 
long));
+       
+                       if (desc == NULL)
+                               ret = -ENOMEM;
+
+                       set_xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap,
+                                        desc);
+               }
                break;
        case XEN_DOMCTL_max_mem:
                break;
        case XEN_DOMCTL_setvcpucontext:
        case XEN_DOMCTL_getvcpucontext:
-               ret = xencomm_create(
+               desc = xencomm_map(
                        xen_guest_handle(kern_op.u.vcpucontext.ctxt),
-                       sizeof(vcpu_guest_context_t),
-                       &desc, GFP_KERNEL);
+                       sizeof(vcpu_guest_context_t));
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
                set_xen_guest_handle(kern_op.u.vcpucontext.ctxt,
-                                    xencomm_pa(desc));
+                                    desc);
                break;
        case XEN_DOMCTL_getvcpuinfo:
                break;
        case XEN_DOMCTL_setvcpuaffinity:
        case XEN_DOMCTL_getvcpuaffinity:
-               ret = xencomm_create(
+               desc = xencomm_map(
                        xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap),
-                       (kern_op.u.vcpuaffinity.cpumap.nr_cpus + 7) / 8,
-                       &desc, GFP_KERNEL);
+                       (kern_op.u.vcpuaffinity.cpumap.nr_cpus + 7) / 8);
+               
+               if (desc == NULL)
+                       ret = -ENOMEM;
+               
                set_xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap,
-                                    xencomm_pa(desc));
+                                    desc);
                break;
        case XEN_DOMCTL_max_vcpus:
        case XEN_DOMCTL_scheduler_op:
@@ -325,7 +384,7 @@ static int xenppc_privcmd_domctl(privcmd
        if (ret)
                goto out; /* error mapping the nested pointer */
 
-       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), xencomm_pa(op_desc));
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op),op_desc);
 
        if (copy_to_user(user_op, &kern_op, sizeof(xen_domctl_t)))
                ret = -EFAULT;
@@ -341,7 +400,7 @@ static int xenppc_privcmd_sysctl(privcmd
        xen_sysctl_t kern_op;
        xen_sysctl_t __user *user_op = (xen_sysctl_t __user *)hypercall->arg[0];
        struct xencomm_desc *op_desc;
-       struct xencomm_desc *desc = NULL;
+       void *desc = NULL;
        int ret = 0;
 
        if (copy_from_user(&kern_op, user_op, sizeof(xen_sysctl_t)))
@@ -353,18 +412,22 @@ static int xenppc_privcmd_sysctl(privcmd
                return -EACCES;
        }
 
-       ret = xencomm_create(&kern_op, sizeof(xen_sysctl_t), &op_desc, 
GFP_KERNEL);
-       if (ret)
-               return ret;
+       op_desc = xencomm_map(&kern_op, sizeof(xen_sysctl_t));
+
+       if (op_desc == NULL)
+               return -ENOMEM;
 
        switch (kern_op.cmd) {
        case XEN_SYSCTL_readconsole:
-               ret = xencomm_create(
+               desc = xencomm_map(
                        xen_guest_handle(kern_op.u.readconsole.buffer),
-                       kern_op.u.readconsole.count,
-                       &desc, GFP_KERNEL);
+                       kern_op.u.readconsole.count);
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+       
                set_xen_guest_handle(kern_op.u.readconsole.buffer,
-                                    xencomm_pa(desc));
+                                    desc);
                break;
        case XEN_SYSCTL_tbuf_op:
        case XEN_SYSCTL_physinfo:
@@ -376,13 +439,16 @@ static int xenppc_privcmd_sysctl(privcmd
                printk(KERN_ERR "%s: unknown sysctl cmd %d\n", __func__, 
kern_op.cmd);
                return -ENOSYS;
        case XEN_SYSCTL_getdomaininfolist:
-               ret = xencomm_create(
+               desc = xencomm_map(
                        xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
                        kern_op.u.getdomaininfolist.max_domains *
-                                       sizeof(xen_domctl_getdomaininfo_t),
-                       &desc, GFP_KERNEL);
+                                       sizeof(xen_domctl_getdomaininfo_t));
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
                set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
-                                    xencomm_pa(desc));
+                                    desc);
                break;
        default:
                printk(KERN_ERR "%s: unknown sysctl cmd %d\n", __func__, 
kern_op.cmd);
@@ -392,7 +458,7 @@ static int xenppc_privcmd_sysctl(privcmd
        if (ret)
                goto out; /* error mapping the nested pointer */
 
-       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), xencomm_pa(op_desc));
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), op_desc);
 
        if (copy_to_user(user_op, &kern_op, sizeof(xen_sysctl_t)))
                ret = -EFAULT;
@@ -408,8 +474,8 @@ static int xenppc_privcmd_platform_op(pr
        xen_platform_op_t kern_op;
        xen_platform_op_t __user *user_op =
                        (xen_platform_op_t __user *)hypercall->arg[0];
-       struct xencomm_desc *op_desc;
-       struct xencomm_desc *desc = NULL;
+       void *op_desc;
+       void *desc = NULL;
        int ret = 0;
 
        if (copy_from_user(&kern_op, user_op, sizeof(xen_platform_op_t)))
@@ -421,10 +487,10 @@ static int xenppc_privcmd_platform_op(pr
                return -EACCES;
        }
 
-       ret = xencomm_create(&kern_op, sizeof(xen_platform_op_t), &op_desc,
-                       GFP_KERNEL);
-       if (ret)
-               return ret;
+       op_desc = xencomm_map(&kern_op, sizeof(xen_platform_op_t));
+
+       if (op_desc == NULL)
+               return -ENOMEM;
 
        switch (kern_op.cmd) {
        case XENPF_settime:
@@ -443,7 +509,7 @@ static int xenppc_privcmd_platform_op(pr
        if (ret)
                goto out; /* error mapping the nested pointer */
 
-       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), xencomm_pa(op_desc));
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), op_desc);
 
        if (copy_to_user(user_op, &kern_op, sizeof(xen_platform_op_t)))
                ret = -EFAULT;
@@ -457,37 +523,38 @@ int HYPERVISOR_memory_op(unsigned int cm
 int HYPERVISOR_memory_op(unsigned int cmd, void *arg)
 {
        int ret;
-       struct xencomm_desc *op_desc;
+       void *op_desc;
        xen_memory_reservation_t *mop;
 
 
        mop = (xen_memory_reservation_t *)arg;
-       ret = xencomm_create(mop, sizeof(xen_memory_reservation_t),
-                            &op_desc, GFP_KERNEL);
-       if (ret)
-               return ret;
+
+       op_desc = xencomm_map(mop, sizeof(xen_memory_reservation_t));
+
+       if (op_desc == NULL)
+               return -ENOMEM;
 
        switch (cmd) {
        case XENMEM_increase_reservation:
        case XENMEM_decrease_reservation:
        {
-               struct xencomm_desc *desc = NULL;
+               void *desc = NULL;
 
                if (xen_guest_handle(mop->extent_start)) {
-                       ret = xencomm_create(
+                       desc = xencomm_map(
                                xen_guest_handle(mop->extent_start),
                                mop->nr_extents *
-                               sizeof(*xen_guest_handle(mop->extent_start)),
-                               &desc, GFP_KERNEL);
-                       if (ret)
-                               return ret;
+                               sizeof(*xen_guest_handle(mop->extent_start)));
+
+                       if (desc == NULL)
+                               return -ENOMEM;
 
                        set_xen_guest_handle(mop->extent_start,
-                                            xencomm_pa(desc));
+                                            desc);
                }
 
                ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_memory_op),
-                                        cmd, xencomm_pa(op_desc));
+                                       cmd, op_desc);
 
                xencomm_free(desc);
        }
@@ -556,12 +623,13 @@ static int xenppc_privcmd_event_channel_
                return -EINVAL;
        }
 
-       ret = xencomm_create((void *)hypercall->arg[1], argsize, &desc, 
GFP_KERNEL);
-       if (ret)
-               return ret;
+       desc = xencomm_map((void *)hypercall->arg[1], argsize);
+
+       if (desc == NULL)
+               return -ENOMEM;
 
        ret = plpar_hcall_norets(XEN_MARK(hypercall->op), hypercall->arg[0],
-                       xencomm_pa(desc));
+                               desc);
 
        xencomm_free(desc);
        return ret;
@@ -604,6 +672,7 @@ int HYPERVISOR_vcpu_op(int cmd, int vcpu
        int argsize;
        const unsigned long hcall = __HYPERVISOR_vcpu_op;
        void *desc;
+       int rc;
 
        switch (cmd) {
        case  VCPUOP_initialise:
@@ -622,8 +691,14 @@ int HYPERVISOR_vcpu_op(int cmd, int vcpu
                return -ENOSYS;
        }
 
-       desc = xencomm_create_inline(extra_args);
-       (void)argsize;
-       return plpar_hcall_norets(XEN_MARK(hcall), cmd, vcpuid, desc);
-}
+       desc = xencomm_map_no_alloc(extra_args, argsize);
        
+       if (desc == NULL)
+               return -EINVAL;
+       
+       rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, vcpuid, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+}
diff -r ab3b5849331d -r 5eca8383a521 arch/powerpc/platforms/xen/setup.c
--- a/arch/powerpc/platforms/xen/setup.c        Sun Jan 21 08:36:53 2007 -0500
+++ b/arch/powerpc/platforms/xen/setup.c        Tue Feb 06 16:21:30 2007 -0500
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(HYPERVISOR_shared_info);
 
 /* Raw start-of-day parameters from the hypervisor. */
 start_info_t *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);
 
 extern struct machdep_calls mach_maple_md;
 extern void maple_pci_init(void);
@@ -150,6 +151,7 @@ int is_running_on_xen(void)
 {
        return running_on_xen;
 }
+EXPORT_SYMBOL(is_running_on_xen);
 
 static void xen_power_save(void)
 {
diff -r ab3b5849331d -r 5eca8383a521 drivers/xen/core/xencomm.c
--- a/drivers/xen/core/xencomm.c        Sun Jan 21 08:36:53 2007 -0500
+++ b/drivers/xen/core/xencomm.c        Tue Feb 06 16:21:30 2007 -0500
@@ -80,13 +80,13 @@ static struct xencomm_desc *xencomm_allo
        return desc;
 }
 
-void xencomm_free(struct xencomm_desc *desc)
+void xencomm_free(void *desc)
 {
-       if (desc)
-               free_page((unsigned long)desc);
+       if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG))
+               free_page((unsigned long)__va(desc));
 }
 
-int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc 
**ret, gfp_t gfp_mask)
+static int xencomm_create(void *buffer, unsigned long bytes, struct 
xencomm_desc **ret, gfp_t gfp_mask)
 {
        struct xencomm_desc *desc;
        int rc;
@@ -119,13 +119,74 @@ int xencomm_create(void *buffer, unsigne
        return 0;
 }
 
-void *xencomm_create_inline(void *ptr)
+/* check if memory address is within VMALLOC region  */
+static int is_phys_contiguous(unsigned long addr)
+{
+       if (!is_kernel_addr(addr))
+               return 0;
+
+       return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
+}
+
+static void *xencomm_create_inline(void *ptr)
 {
        unsigned long paddr;
 
-       BUG_ON(!is_kernel_addr((unsigned long)ptr));
+       BUG_ON(!is_phys_contiguous((unsigned long)ptr));
 
        paddr = (unsigned long)xencomm_pa(ptr);
        BUG_ON(paddr & XENCOMM_INLINE_FLAG);
        return (void *)(paddr | XENCOMM_INLINE_FLAG);
 }
+
+/* "mini" routine, for stack-based communications: */
+static int xencomm_create_mini(void *buffer,
+       unsigned long bytes, struct xencomm_mini *xc_desc,
+       struct xencomm_desc **ret)
+{
+       int rc = 0;
+       struct xencomm_desc *desc;
+
+       desc = (void *)xc_desc; 
+
+       desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+       if (!(rc = xencomm_init(desc, buffer, bytes)))
+               *ret = desc;
+
+       return rc;
+}
+
+void *xencomm_map(void *ptr, unsigned long bytes)
+{
+       int rc;
+       struct xencomm_desc *desc;
+
+       if (is_phys_contiguous((unsigned long)ptr))
+               return xencomm_create_inline(ptr);
+
+       rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
+
+       if (rc || desc == NULL)
+               return NULL;
+
+       return (void *)__pa(desc);
+}
+
+void *__xencomm_map_no_alloc(void *ptr, unsigned long bytes, 
+                       struct xencomm_mini *xc_desc)
+{
+       int rc;
+       struct xencomm_desc *desc = NULL;
+
+       if (is_phys_contiguous((unsigned long)ptr))
+               return xencomm_create_inline(ptr);
+
+       rc = xencomm_create_mini(ptr, bytes, xc_desc,
+                               &desc);
+
+       if (rc)
+               return NULL;
+ 
+       return (void *)__pa(desc);
+}
diff -r ab3b5849331d -r 5eca8383a521 include/xen/xencomm.h
--- a/include/xen/xencomm.h     Sun Jan 21 08:36:53 2007 -0500
+++ b/include/xen/xencomm.h     Tue Feb 06 16:21:30 2007 -0500
@@ -16,6 +16,7 @@
  * Copyright (C) IBM Corp. 2006
  *
  * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
+ *          Jerone Young <[EMAIL PROTECTED]>
  */
 
 #ifndef _LINUX_XENCOMM_H_
@@ -23,10 +24,21 @@
 
 #include <xen/interface/xencomm.h>
 
-extern int xencomm_create(void *buffer, unsigned long bytes,
-                         struct xencomm_desc **desc, gfp_t type);
-extern void xencomm_free(struct xencomm_desc *desc);
-extern void *xencomm_create_inline(void *ptr);
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+       struct xencomm_desc _desc;
+       uint64_t address[XENCOMM_MINI_ADDRS];
+};
+
+extern void xencomm_free(void *desc);
+extern void *xencomm_map(void *ptr, unsigned long bytes);
+extern void *__xencomm_map_no_alloc(void *ptr, unsigned long bytes, 
+                               struct xencomm_mini *xc_area);
+
+#define xencomm_map_no_alloc(ptr, bytes) \
+       ({struct xencomm_mini xc_desc\
+               __attribute__((__aligned__(sizeof(struct xencomm_mini))));\
+               __xencomm_map_no_alloc(ptr, bytes, &xc_desc);})
 
 /* provided by architecture code: */
 extern unsigned long xencomm_vtop(unsigned long vaddr);

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to