# HG changeset patch # User gingold@virtu10 # 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 Signed-off-by: Hollis Blanchard 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 , 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 +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + 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 , 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 + +/* 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 , 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_ */