Hi,
taking into account Hollis comments I now submit this patch.
IA64 specific stuff will be posted to xen-ia64-unstable after merge.
Tristan.
# HG changeset patch
# User [EMAIL PROTECTED]
# Node ID ba96f5f81464dc3db80af0454fb05c73de620637
# Parent cc7a78171c811b9caa5587a0141d8c8477d10ce8
Xencomm support in linux kernel:
* descriptor creation and destruction
* transformation of kernels hypercalls
* transformation of privcmd issued hypercalls.
It must be enabled by architecture config.
Signed-off-by: Tristan Gingold <[EMAIL PROTECTED]>
Signed-off-by: Hollis Blanchard <[EMAIL PROTECTED]>
diff -r cc7a78171c81 -r ba96f5f81464 linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Wed Aug 23 12:23:05 2006 +0200
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Wed Aug 23 12:28:12 2006 +0200
@@ -257,4 +257,7 @@ config XEN_SMPBOOT
default y
depends on SMP
+config XEN_XENCOMM
+ bool
+ default n
endif
diff -r cc7a78171c81 -r ba96f5f81464 linux-2.6-xen-sparse/drivers/xen/core/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Wed Aug 23 12:23:05 2006 +0200
+++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Wed Aug 23 12:28:12 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 cc7a78171c81 -r ba96f5f81464 linux-2.6-xen-sparse/drivers/xen/privcmd/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/Makefile Wed Aug 23 12:23:05 2006 +0200
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/Makefile Wed Aug 23 12:28:12 2006 +0200
@@ -1,1 +1,3 @@ obj-y := privcmd.o
obj-y := privcmd.o
+
+obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
diff -r cc7a78171c81 -r ba96f5f81464 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 Wed Aug 23 12:28:12 2006 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <[EMAIL PROTECTED]>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <xen/xencomm.h>
+#include <xen/interface/xen.h>
+#include <asm/xen/xencomm.h>
+
+static int xencomm_debug;
+
+/* translate virtual address to physical address.
+ This is the generic version. Architectures must declare
+ xen_vaddr_to_paddr in asm/xen/xencomm.h, which may be a macro.
+*/
+static unsigned long xen_generic_vaddr_to_paddr(unsigned long vaddr)
+{
+ struct page *page;
+ struct vm_area_struct *vma;
+
+ 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);
+}
+
+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;
+}
+
+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask)
+{
+ struct xencomm_desc *desc;
+
+ /* XXX could we call this from irq context? */
+ desc = (struct xencomm_desc *)__get_free_page(gfp_mask);
+ if (desc == NULL) {
+ 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;
+}
+
+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 *)(paddr | XENCOMM_INLINE_FLAG);
+}
diff -r cc7a78171c81 -r ba96f5f81464 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 Wed Aug 23 12:28:12 2006 +0200
@@ -0,0 +1,281 @@
+#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:
+ * 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)
+{
+ struct xencomm_handle *desc;
+
+ desc = xencomm_create_inline(str, count);
+
+ return xencomm_arch_hypercall_console_io(cmd, count, desc);
+}
+
+int xencomm_hypercall_event_channel_op(int cmd, void *op)
+{
+ struct xencomm_handle *desc;
+
+ desc = xencomm_create_inline(op, sizeof(evtchn_op_t));
+
+ return xencomm_arch_hypercall_event_channel_op(cmd, desc);
+}
+
+int xencomm_hypercall_xen_version(int cmd, void *arg)
+{
+ struct xencomm_handle *desc;
+ int argsize;
+
+ 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 cmd %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_create_inline(arg, argsize);
+
+ return xencomm_arch_hypercall_xen_version(cmd, desc);
+}
+
+int xencomm_hypercall_physdev_op(int cmd, void *op)
+{
+ struct xencomm_handle *desc;
+
+ desc = xencomm_create_inline(op, sizeof(physdev_op_t));
+
+ return xencomm_arch_hypercall_physdev_op(cmd, desc);
+}
+
+int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
+ unsigned int count)
+{
+ struct xencomm_handle *desc;
+ struct xencomm_handle *frame_list;
+ int argsize;
+
+ switch (cmd) {
+ case GNTTABOP_map_grant_ref:
+ argsize = sizeof(struct gnttab_map_grant_ref);
+ break;
+ case GNTTABOP_unmap_grant_ref:
+ argsize = sizeof(struct gnttab_unmap_grant_ref);
+ break;
+ case GNTTABOP_setup_table:
+ {
+ struct gnttab_setup_table *setup = op;
+ argsize = sizeof(struct gnttab_setup_table);
+
+ frame_list = xencomm_create_inline
+ (xen_guest_handle(setup->frame_list),
+ setup->nr_frames
+ * sizeof(*xen_guest_handle(setup->frame_list)));
+
+ set_xen_guest_handle(setup->frame_list, (void *)frame_list);
+ break;
+ }
+ case GNTTABOP_dump_table:
+ argsize = sizeof(struct gnttab_dump_table);
+ break;
+ case GNTTABOP_transfer:
+ argsize = sizeof(struct gnttab_transfer);
+ break;
+ default:
+ printk("%s: unknown grant table op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_create_inline(op, count * argsize);
+
+ return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
+}
+
+int xencomm_hypercall_sched_op(int cmd, void *arg)
+{
+ int rc;
+ struct xencomm_handle *desc;
+ ulong argsize;
+
+ switch (cmd) {
+ case SCHEDOP_yield:
+ case SCHEDOP_block:
+ return xencomm_arch_hypercall_sched_op (cmd, 0);
+ break;
+
+ case SCHEDOP_shutdown:
+ argsize = sizeof(sched_shutdown_t);
+ break;
+ case SCHEDOP_poll:
+ argsize = sizeof(sched_poll_t);
+ break;
+ case SCHEDOP_remote_shutdown:
+ argsize = sizeof(sched_remote_shutdown_t);
+ break;
+ default:
+ printk("%s: unknown sched op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_create_inline(arg, argsize);
+
+ return xencomm_arch_hypercall_sched_op(cmd, desc);
+}
+
+int xencomm_hypercall_multicall(void *call_list, int nr_calls)
+{
+ int i;
+ multicall_entry_t *mce;
+ struct xencomm_handle *desc;
+
+ 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_memory_op:
+ default:
+ printk("%s: unhandled multicall op entry op %lu\n",
+ __func__, mce->op);
+ return -ENOSYS;
+ }
+ }
+
+ desc = xencomm_create_inline
+ (call_list, nr_calls * sizeof(multicall_entry_t));
+
+ return xencomm_arch_hypercall_multicall(desc, nr_calls);
+}
+
+int xencomm_hypercall_callback_op(int cmd, void *arg)
+{
+ struct xencomm_handle *desc;
+
+ switch (cmd)
+ {
+ case CALLBACKOP_register:
+ desc = xencomm_create_inline
+ (arg, sizeof(callback_register_t));
+ break;
+ case CALLBACKOP_unregister:
+ desc = xencomm_create_inline
+ (arg, sizeof(callback_unregister_t));
+ break;
+ default:
+ printk("%s: unknown callback op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_callback_op(cmd, desc);
+}
+
+static void xencommize_memory_reservation (xen_memory_reservation_t *mop)
+{
+ struct xencomm_handle *desc;
+
+ if (xen_guest_handle(mop->extent_start) == NULL)
+ return;
+
+ desc = xencomm_create_inline
+ (xen_guest_handle(mop->extent_start),
+ mop->nr_extents *
+ sizeof(*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)
+{
+ struct xencomm_handle *desc;
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ desc = xencomm_create_inline
+ (arg, sizeof(xen_memory_reservation_t));
+
+ xencommize_memory_reservation
+ ((xen_memory_reservation_t *)arg);
+ break;
+
+ case XENMEM_maximum_ram_page:
+ /* arg is NULL so we can call thru here */
+ desc = NULL;
+ break;
+
+ case XENMEM_exchange:
+ desc = xencomm_create_inline
+ (arg, sizeof (xen_memory_exchange_t));
+
+ xencommize_memory_reservation
+ (&((xen_memory_exchange_t *)arg)->in);
+ xencommize_memory_reservation
+ (&((xen_memory_exchange_t *)arg)->out);
+ break;
+
+ default:
+ printk("%s: unknown memory op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_memory_op(cmd, desc);
+}
+
diff -r cc7a78171c81 -r ba96f5f81464 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 Wed Aug 23 12:28:12 2006 +0200
@@ -0,0 +1,359 @@
+#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__
+ /* 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 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) {
+ /* 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_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 cc7a78171c81 -r ba96f5f81464 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 Wed Aug 23 12:28:12 2006 +0200
@@ -0,0 +1,26 @@
+#ifndef _ASM_IA64_XEN_XENCOMM_H
+#define _ASM_IA64_XEN_XENCOMM_H
+
+/* Written by Tristan Gingold <[EMAIL PROTECTED]>
+ Define xen_vaddr_to_paddr.
+ This file is included only by drivers/xen/core/xencomm.c
+*/
+
+extern unsigned long kernel_start_pa;
+
+static unsigned long xen_generic_vaddr_to_paddr(unsigned long vaddr);
+
+static unsigned long xen_vaddr_to_paddr(unsigned long vaddr)
+{
+ /* 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)) {
+ return vaddr - kernel_start_pa;
+ }
+ return xen_generic_vaddr_to_paddr(vaddr);
+}
+
+#endif /* _ASM_IA64_XEN_XENCOMM_H */
diff -r cc7a78171c81 -r ba96f5f81464 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 Wed Aug 23 12:28:12 2006 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <[EMAIL PROTECTED]>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_XENCOMM_H_
+#define _LINUX_XENCOMM_H_
+
+#include <xen/interface/xencomm.h>
+
+/* 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);
+struct xencomm_handle *xencomm_create_inline (void *buffer,
+ unsigned long bytes);
+
+#define xen_guest_handle(hnd) ((hnd).p)
+
+#endif /* _LINUX_XENCOMM_H_ */
diff -r cc7a78171c81 -r ba96f5f81464 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 Wed Aug 23 12:28:12 2006 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006 Tristan Gingold <[EMAIL PROTECTED]>, 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);
+
+#endif /* _LINUX_XENCOMM_HCALL_H_ */
_______________________________________________
Xen-ppc-devel mailing list
[email protected]
http://lists.xensource.com/xen-ppc-devel