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

[Xen-devel] Re: [XenPPC] RFC: xencomm - linux side



I apologize for my mailer line-wrapping the patch as I quote it below.

On Mon, 2006-08-21 at 17:18 +0200, Tristan Gingold wrote:
> diff -r b7db009d622c linux-2.6-xen-sparse/drivers/xen/Kconfig
> --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig  Mon Aug 21 09:41:24
> 2006 +0200
> +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig  Mon Aug 21 15:04:32
> 2006 +0200
> @@ -257,4 +257,7 @@ config XEN_SMPBOOT
>         default y
>         depends on SMP
>  
> +config XEN_XENCOMM
> +       bool
> +       default n
>  endif

Shouldn't IA64 "select XEN_XENCOMM"? Or is your kernel in a separate
tree?

> diff -r b7db009d622c linux-2.6-xen-sparse/drivers/xen/Makefile
> --- a/linux-2.6-xen-sparse/drivers/xen/Makefile Mon Aug 21 09:41:24
> 2006 +0200
> +++ b/linux-2.6-xen-sparse/drivers/xen/Makefile Mon Aug 21 15:04:32
> 2006 +0200
> @@ -1,10 +1,10 @@ obj-y += core/
>  obj-y  += core/
>  obj-y  += console/
>  obj-y  += evtchn/
> -obj-y  += privcmd/
>  obj-y  += xenbus/
>  
>  obj-$(CONFIG_XEN_UTIL)                 += util.o
> +obj-$(CONFIG_XEN_PRIVCMD)              += privcmd/
>  obj-$(CONFIG_XEN_BALLOON)              += balloon/
>  obj-$(CONFIG_XEN_DEVMEM)               += char/
>  obj-$(CONFIG_XEN_BLKDEV_BACKEND)       += blkback/

Not really part of this patch.

> diff -r b7db009d622c linux-2.6-xen-sparse/drivers/xen/core/Makefile
> --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile    Mon Aug 21
> 09:41:24 2006 +0200
> +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile    Mon Aug 21
> 15:04:32 2006 +0200
> @@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SKBUFF)      += skbuff.o
>  obj-$(CONFIG_XEN_SKBUFF)       += skbuff.o
>  obj-$(CONFIG_XEN_REBOOT)       += reboot.o
>  obj-$(CONFIG_XEN_SMPBOOT)      += smpboot.o
> +obj-$(CONFIG_XEN_XENCOMM)      += xencomm.o xencomm_hcall.o
> diff -r b7db009d622c linux-2.6-xen-sparse/drivers/xen/privcmd/Makefile
> --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/Makefile Mon Aug 21
> 09:41:24 2006 +0200
> +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/Makefile Mon Aug 21
> 15:04:32 2006 +0200
> @@ -1,2 +1,3 @@
> +obj-y                          := privcmd.o
>  
> -obj-$(CONFIG_XEN_PRIVCMD)      := privcmd.o
> +obj-$(CONFIG_XEN_XENCOMM)      += xencomm.o

I agree with the CONFIG_XEN_PRIVCMD stuff, but I think that should be a
separate patch.

> diff -r b7db009d622c
> linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
> --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Mon
> Aug 21 09:41:24 2006 +0200
> +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Mon
> Aug 21 15:04:32 2006 +0200
> @@ -34,6 +34,10 @@
>  
>  static struct proc_dir_entry *privcmd_intf;
>  static struct proc_dir_entry *capabilities_intf;
> +
> +#ifdef CONFIG_XEN_XENCOMM
> +extern int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall);
> +#endif
>  
>  #define NR_HYPERCALLS 64
>  static DECLARE_BITMAP(hypercall_permission_map, NR_HYPERCALLS);
> @@ -91,19 +95,8 @@ static int privcmd_ioctl(struct inode *i
>                                 "g" ((unsigned long)hypercall.arg[4])
>                                 : "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");
> +#elif defined (CONFIG_XEN_XENCOMM)
> +               ret = xencomm_privcmd_hypercall (&hypercall);
>  #endif
>         }
>         break;

Move all the #ifdef stuff into appropriate header files, then have every
arch unconditionally call arch_privcmd_hypercall().

> diff -r b7db009d622c linux-2.6-xen-sparse/drivers/xen/core/xencomm.c
> --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/drivers/xen/core/xencomm.c   Mon Aug 21
> 15:04:32 2006 +0200
> @@ -0,0 +1,213 @@
> +/*
> + * 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 <xen/xencomm.h>
> +#include <xen/interface/xen.h>
> +
> +int xencomm_debug;
> +
> +/* translate virtual address to physical address */
> +static unsigned long xen_vaddr_to_paddr(unsigned long vaddr)
> +{
> +       struct page *page;
> +       struct vm_area_struct *vma;
> +
> +#ifdef __ia64__
> +       /* On ia64, TASK_SIZE refers to current.  It is not
> initialized
> +          during boot.
> +          Furthermore the kernel is relocatable and __pa() doesn't
> work on
> +          kernel addresses.  */
> +       if (vaddr >= KERNEL_START
> +           && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) {
> +               extern unsigned long kernel_start_pa;
> +               return vaddr - kernel_start_pa;
> +       }
> +#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;
> +
> +       page = follow_page(vma, vaddr, 0);
> +       if (!page)
> +               return ~0UL;
> +
> +       return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr &
> ~PAGE_MASK);
> +}

If there really is no way to implement xen_vaddr_to_paddr() in an
arch-neutral way (and I'm willing to believe that's true), just make the
whole function arch-specific. It wouldn't be too much duplicated code.

> +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 = xen_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;
> +}
> +
> +/* XXX use slab allocator */
> +static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask)
> +{
> +       struct xencomm_desc *desc;
> +
> +       /* XXX could we call this from irq context? */

You can remove this comment. It's historical, and we're passing in
gfp_mask now.

> +       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(void *area, int arealen)
> +{
> +       unsigned long base = (unsigned long)area;
> +       unsigned int pageoffset;
> +
> +       pageoffset = base % PAGE_SIZE;
> +
> +       /* we probably fit right at the front of area */
> +       if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini)) {
> +               return area;
> +       }
> +
> +       /* if not, see if area is big enough to advance to the next
> page */
> +       if ((arealen - pageoffset) >= sizeof(struct xencomm_mini))
> +               return (void *)(base + pageoffset);
> +
> +       /* area was too small */
> +       return NULL;
> +}
> +
> +int xencomm_create_mini(void *area, int arealen, void *buffer,
> +                       unsigned long bytes, struct xencomm_handle
> **ret)
> +{
> +       struct xencomm_desc *desc;
> +       int rc;
> +
> +       desc = xencomm_alloc_mini(area, arealen);
> +       if (!desc)
> +               return -ENOMEM;
> +       desc->nr_addrs = XENCOMM_MINI_ADDRS;
> +
> +       rc = xencomm_init(desc, buffer, bytes);
> +       if (rc)
> +               return rc;
> +
> +       *ret = (struct xencomm_handle *)__pa(desc);
> +       return 0;
> +}

*_mini are unused and should be removed entirely.

> +struct xencomm_handle *xencomm_create_inline (void *buffer,
> +                                             unsigned long bytes)
> +{
> +       unsigned long paddr;
> +
> +       paddr = xen_vaddr_to_paddr((unsigned long)buffer);
> +       return (struct xencomm_handle *)XENCOMM_INLINE_CREATE(paddr);
> +}

XENCOMM_INLINE_CREATE in undefined in this patch. I liked your old patch
just fine:
+struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long
bytes)
+{
+       return (struct xencomm_desc *)
+               (__kern_paddr((unsigned long)buffer) | XENCOMM_INLINE);
+}

> diff -r b7db009d622c
> linux-2.6-xen-sparse/drivers/xen/core/xencomm_hcall.c
> --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/drivers/xen/core/xencomm_hcall.c     Mon
> Aug 21 15:04:32 2006 +0200
> @@ -0,0 +1,311 @@
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/gfp.h>
> +#include <linux/module.h>
> +#include <xen/interface/xen.h>
> +#include <xen/interface/dom0_ops.h>
> +#include <xen/interface/memory.h>
> +#include <xen/interface/xencomm.h>
> +#include <xen/interface/version.h>
> +#include <xen/interface/sched.h>
> +#include <xen/interface/event_channel.h>
> +#include <xen/interface/physdev.h>
> +#include <xen/interface/grant_table.h>
> +#include <xen/interface/callback.h>
> +#include <xen/interface/acm_ops.h>
> +#include <xen/public/privcmd.h>
> +#include <asm/hypercall.h>
> +#include <asm/page.h>
> +#include <asm/uaccess.h>
> +#include <xen/xencomm.h>
> +
> +/* Xencomm notes:
> + *
> + * Some hypercalls are made before the memory subsystem is up, so
> instead of
> + * calling xencomm_create(), we allocate XENCOMM_MINI_AREA bytes from
> the stack
> + * to hold the xencomm descriptor.

Remove above comment.

> + * In general, we need a xencomm descriptor to cover the top-level
> data
> + * structure (e.g. the dom0 op), plus another for every embedded
> pointer to
> + * another data structure (i.e. for every GUEST_HANDLE).
> + */
> +
> +int xencomm_hypercall_console_io(int cmd, int count, char *str)
> +{
> +       struct xencomm_handle *desc;
> +       int rc;
> +
> +       desc = xencomm_create_inline (str, count);
> +
> +       rc = xencomm_arch_hypercall_console_io (cmd, count, desc);
> +
> +       return rc;
> +}

I don't understand the point of all these routines if they just call
arch_foo anyways.


> diff -r b7db009d622c
> linux-2.6-xen-sparse/drivers/xen/privcmd/xencomm.c
> --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/xencomm.c        Mon
> Aug 21 15:04:32 2006 +0200
> @@ -0,0 +1,358 @@
> +#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/version.h>
> +#include <xen/interface/event_channel.h>
> +#include <xen/interface/acm_ops.h>
> +#include <xen/public/privcmd.h>
> +#include <asm/hypercall.h>
> +#include <asm/page.h>
> +#include <asm/uaccess.h>
> +#include <xen/xencomm.h>
> +
> +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, sizeof(dom0_op_t));
> +
> +       switch (kern_op.cmd) {
> +       case DOM0_GETMEMLIST:
> +       {
> +               unsigned long nr_pages =
> kern_op.u.getmemlist.max_pfns;
> +#ifdef __ia64__
> +               /* Xen/ia64 pass first_page and nr_pages in max_pfns!
> */
> +               nr_pages &= 0xffffffff;
> +#endif

I'm willing to put up with this only if you guys promise to fix this
silly API incompatibility, at which point it will be removed.

> +               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 DOM0_SETVCPUCONTEXT:
> +               ret = xencomm_create(
> +                       xen_guest_handle(kern_op.u.setvcpucontext.ctxt),
> +                       sizeof(vcpu_guest_context_t),
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.setvcpucontext.ctxt,
> +                                    (void *)desc);
> +               break;
> +       case DOM0_READCONSOLE:
> +               ret = xencomm_create(
> +                       xen_guest_handle(kern_op.u.readconsole.buffer),
> +                       kern_op.u.readconsole.count,
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.readconsole.buffer,
> +                                    (void *)desc);
> +               break;
> +       case DOM0_GETPAGEFRAMEINFO2:
> +               ret = xencomm_create(
> +                       xen_guest_handle(kern_op.u.getpageframeinfo2.array),
> +                       kern_op.u.getpageframeinfo2.num,
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
> +                                    (void *)desc);
> +               break;
> +       case DOM0_PERFCCONTROL:
> +               ret = xencomm_create(
> +                       xen_guest_handle(kern_op.u.perfccontrol.desc),
> +                       kern_op.u.perfccontrol.nr_counters *
> +                       sizeof(dom0_perfc_desc_t),
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.perfccontrol.desc,
> +                                    (void *)desc);
> +               break;
> +       case DOM0_GETVCPUCONTEXT:
> +               ret = xencomm_create(
> +                       xen_guest_handle(kern_op.u.getvcpucontext.ctxt),
> +                       sizeof(vcpu_guest_context_t),
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.getvcpucontext.ctxt,
> +                                    (void *)desc);
> +               break;
> +       case DOM0_GETDOMAININFOLIST:
> +               ret = xencomm_create(
> +                       xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
> +                       kern_op.u.getdomaininfolist.num_domains *
> +                       sizeof(dom0_getdomaininfo_t),
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
> +                                    (void *)desc);
> +               break;
> +       case DOM0_PHYSICAL_MEMORY_MAP:
> +               ret = xencomm_create(
> +                       
> xen_guest_handle(kern_op.u.physical_memory_map.memory_map),
> +                       kern_op.u.physical_memory_map.nr_map_entries *
> +                       sizeof(struct dom0_memory_map_entry),
> +                       &desc, GFP_KERNEL);
> +               set_xen_guest_handle(kern_op.u.physical_memory_map.memory_map,
> +                                    (void *)desc);
> +               break;
> +
> +       case DOM0_SCHEDCTL:
> +       case DOM0_ADJUSTDOM:
> +       case DOM0_CREATEDOMAIN:
> +       case DOM0_DESTROYDOMAIN:
> +       case DOM0_PAUSEDOMAIN:
> +       case DOM0_UNPAUSEDOMAIN:
> +       case DOM0_GETDOMAININFO:
> +       case DOM0_MSR:
> +       case DOM0_SETTIME:
> +       case DOM0_GETPAGEFRAMEINFO:
> +       case DOM0_SETVCPUAFFINITY:
> +       case DOM0_TBUFCONTROL:
> +       case DOM0_PHYSINFO:
> +       case DOM0_SCHED_ID:
> +       case DOM0_SETDOMAINMAXMEM:
> +       case DOM0_ADD_MEMTYPE:
> +       case DOM0_DEL_MEMTYPE:
> +       case DOM0_READ_MEMTYPE:
> +       case DOM0_IOPORT_PERMISSION:
> +       case DOM0_GETVCPUINFO:
> +       case DOM0_PLATFORM_QUIRK:
> +       case DOM0_MAX_VCPUS:
> +       case DOM0_SETDOMAINHANDLE:
> +       case DOM0_SETDEBUGGING:
> +       case DOM0_DOMAIN_SETUP:
> +               /* no munging needed */
> +               break;
> +
> +       default:
> +               printk("%s: unknown dom0 cmd %d\n", __func__,
> kern_op.cmd);
> +               return -ENOSYS;
> +       }
> +
> +       if (ret)
> +               goto out; /* error mapping the nested pointer */
> +
> +       ret = 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);
> +out:
> +       return ret;
> +}

You misplaced the out label; it needs to go before xencomm_free(desc);

That's a good question about the copy_to_user(). I thought we never
exposed the modified handles back to the user, but I guess I was wrong.

Also please check whitespace throughout. In particular you seem to be
doing this:
        function (args);
and not even Keir's shall-we-say-unique style does that. ;)

> +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,
> sizeof(kern_arg));
> +
> +               ret =
> xencomm_create(xen_guest_handle(kern_arg.ssidbuf),
> +                                    kern_arg.ssidbuf_size,
> +                                    &desc, GFP_KERNEL);
> +               if (ret)
> +                       return ret;
> +
> +               set_xen_guest_handle(kern_arg.ssidbuf, (void *)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:
> +       {
> +               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, sizeof
> (kern_op));
> +
> +               if (xen_guest_handle(kern_op.extent_start)) {
> +                       void * addr;
> +
> +                       addr = xen_guest_handle(kern_op.extent_start);
> +                       ret = xencomm_create
> +                               (addr,
> +                                kern_op.nr_extents *
> +                                sizeof(*xen_guest_handle
> +                                       (kern_op.extent_start)),
> +                                &desc, GFP_KERNEL);
> +                       if (ret)
> +                               return ret;
> +                       set_xen_guest_handle(kern_op.extent_start,
> +                                            (void *)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;
> +       }
> +       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;
> +}
> +
> +int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall)
> +{
> +       switch (hypercall->op) {
> +       case __HYPERVISOR_dom0_op:
> +               return xencomm_privcmd_dom0_op(hypercall);
> +        case __HYPERVISOR_acm_op:
> +               return xencomm_privcmd_acm_op(hypercall);
> +       case __HYPERVISOR_xen_version:
> +               return xencomm_privcmd_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);
> +       default:
> +               printk("%s: unknown hcall (%ld)\n", __func__,
> hypercall->op);
> +               return -ENOSYS;
> +       }
> +}
> +
> diff -r b7db009d622c linux-2.6-xen-sparse/include/xen/xencomm.h
> --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/include/xen/xencomm.h        Mon Aug 21
> 15:04:32 2006 +0200
> @@ -0,0 +1,45 @@
> +/*
> + * 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];
> +};
> +#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2)

Remove above.

> +/* To avoid additionnal virt to phys convertion, the user only sees
> handle
> +   which are opaque structures.  */
> +struct xencomm_handle;

Typos in the comment.

> +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(void *area, int arealen, void *buffer,
> +            unsigned long bytes, struct xencomm_handle **ret);

Remove above.

> +struct xencomm_handle *xencomm_create_inline (void *buffer,
> +                                             unsigned long bytes);
> +
> +#define xen_guest_handle(hnd)  ((hnd).p)
> +
> +#endif /* _LINUX_XENCOMM_H_ */
> diff -r b7db009d622c linux-2.6-xen-sparse/include/xen/xencomm_hcall.h
> --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux-2.6-xen-sparse/include/xen/xencomm_hcall.h  Mon Aug 21
> 15:04:32 2006 +0200
> @@ -0,0 +1,45 @@
> +/*
> + * 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 correspondig xencomm_arch_hypercall_X.
> +   Architectures should defines HYPERVISOR_xxx as
> xencomm_hypercall_xxx unless
> +   they want to use their own wrapper.  */

"corresponding"

And I'm not clear on the reason for all the xencomm_arch_*, especially
because I haven't seen IA64's. If you're worried about the structure
size conversion I mentioned earlier, I think PowerPC will need to fix
that *before* the xencomm stuff is called anyways. So unless IA64 needs
something funny in xencomm_arch_*, they should all be removed.

-- 
Hollis Blanchard
IBM Linux Technology Center


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


 


Rackspace

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