diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/Kconfig --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Fri Aug 18 14:26:09 2006 +0200 @@ -530,6 +530,9 @@ config XEN_REBOOT config XEN_SMPBOOT default n + +config XEN_XENCOMM + default y endif source "drivers/xen/Kconfig" diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Fri Aug 18 14:26:09 2006 +0200 @@ -433,6 +433,9 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_XEN if (is_running_on_xen()) { + extern unsigned long kernel_start_pa; + + kernel_start_pa = KERNEL_START - ia64_tpa (KERNEL_START); setup_xen_features(); /* Register a call for panic conditions. */ notifier_chain_register(&panic_notifier_list, &xen_panic_block); diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/Makefile --- a/linux-2.6-xen-sparse/arch/ia64/xen/Makefile Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/Makefile Fri Aug 18 14:26:09 2006 +0200 @@ -3,6 +3,6 @@ # obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \ - hypervisor.o pci-dma-xen.o util.o + hypervisor.o pci-dma-xen.o util.o hcall.o pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Fri Aug 18 14:26:09 2006 +0200 @@ -371,8 +371,6 @@ int int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) { - __u64 va1, va2, pa1, pa2; - if (cmd == GNTTABOP_map_grant_ref) { unsigned int i; for (i = 0; i < count; i++) { @@ -380,29 +378,7 @@ HYPERVISOR_grant_table_op(unsigned int c (struct gnttab_map_grant_ref*)uop + i); } } - va1 = (__u64)uop & PAGE_MASK; - pa1 = pa2 = 0; - if ((REGION_NUMBER(va1) == 5) && - ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) { - pa1 = ia64_tpa(va1); - if (cmd <= GNTTABOP_transfer) { - static uint32_t uop_size[GNTTABOP_transfer + 1] = { - sizeof(struct gnttab_map_grant_ref), - sizeof(struct gnttab_unmap_grant_ref), - sizeof(struct gnttab_setup_table), - sizeof(struct gnttab_dump_table), - sizeof(struct gnttab_transfer), - }; - va2 = (__u64)uop + (uop_size[cmd] * count) - 1; - va2 &= PAGE_MASK; - if (va1 != va2) { - /* maximum size of uop is 2pages */ - BUG_ON(va2 > va1 + PAGE_SIZE); - pa2 = ia64_tpa(va2); - } - } - } - return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2); + return ____HYPERVISOR_grant_table_op(cmd, uop, count); } EXPORT_SYMBOL(HYPERVISOR_grant_table_op); diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/Kconfig --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Fri Aug 18 14:26:09 2006 +0200 @@ -257,4 +257,7 @@ config XEN_SMPBOOT default y depends on SMP +config XEN_XENCOMM + bool + default n endif diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/core/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Fri Aug 18 14:26:09 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 diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Aug 18 14:26:09 2006 +0200 @@ -34,6 +34,8 @@ static struct proc_dir_entry *privcmd_intf; static struct proc_dir_entry *capabilities_intf; + +extern int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall); #define NR_HYPERCALLS 64 static DECLARE_BITMAP(hypercall_permission_map, NR_HYPERCALLS); @@ -92,18 +94,7 @@ static int privcmd_ioctl(struct inode *i : "r8", "r10", "memory" ); } #elif defined (__ia64__) - __asm__ __volatile__ ( - ";; mov r14=%2; mov r15=%3; " - "mov r16=%4; mov r17=%5; mov r18=%6;" - "mov r2=%1; break 0x1000;; mov %0=r8 ;;" - : "=r" (ret) - : "r" (hypercall.op), - "r" (hypercall.arg[0]), - "r" (hypercall.arg[1]), - "r" (hypercall.arg[2]), - "r" (hypercall.arg[3]), - "r" (hypercall.arg[4]) - : "r14","r15","r16","r17","r18","r2","r8","memory"); + ret = xencomm_privcmd_hypercall (&hypercall); #endif } break; diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Fri Aug 18 14:26:09 2006 +0200 @@ -157,19 +157,13 @@ (type)__res; \ }) -static inline int -HYPERVISOR_sched_op_compat( - int cmd, unsigned long arg) -{ - return _hypercall2(int, sched_op_compat, cmd, arg); -} - -static inline int -HYPERVISOR_sched_op( - int cmd, void *arg) -{ - return _hypercall2(int, sched_op, cmd, arg); -} +#if 0 +extern int +HYPERVISOR_sched_op_compat(int cmd, unsigned long arg); +#endif + +extern int +HYPERVISOR_sched_op(int cmd, void *arg); static inline long HYPERVISOR_set_timer_op( @@ -180,29 +174,16 @@ HYPERVISOR_set_timer_op( return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); } -static inline int -HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) -{ - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - return _hypercall1(int, dom0_op, dom0_op); -} - -static inline int -HYPERVISOR_multicall( - void *call_list, int nr_calls) -{ - return _hypercall2(int, multicall, call_list, nr_calls); -} +extern int +HYPERVISOR_dom0_op(dom0_op_t *dom0_op); + +extern int +HYPERVISOR_multicall(multicall_entry_t *call_list, int nr_calls); //XXX xen/ia64 copy_from_guest() is broken. // This is a temporal work around until it is fixed. -static inline int -____HYPERVISOR_memory_op( - unsigned int cmd, void *arg) -{ - return _hypercall2(int, memory_op, cmd, arg); -} +extern int +____HYPERVISOR_memory_op(unsigned int cmd, void *arg); #include int ia64_xenmem_reservation_op(unsigned long op, @@ -223,81 +204,33 @@ HYPERVISOR_memory_op( /* NOTREACHED */ } -static inline int -HYPERVISOR_event_channel_op( - int cmd, void *arg) -{ - int rc = _hypercall2(int, event_channel_op, cmd, arg); - if (unlikely(rc == -ENOSYS)) { - struct evtchn_op op; - op.cmd = cmd; - memcpy(&op.u, arg, sizeof(op.u)); - rc = _hypercall1(int, event_channel_op_compat, &op); - } - return rc; -} - -static inline int -HYPERVISOR_acm_op( - unsigned int cmd, void *arg) -{ - return _hypercall2(int, acm_op, cmd, arg); -} - -static inline int -HYPERVISOR_xen_version( - int cmd, void *arg) -{ - return _hypercall2(int, xen_version, cmd, arg); -} - -static inline int -HYPERVISOR_console_io( - int cmd, int count, char *str) -{ - return _hypercall3(int, console_io, cmd, count, str); -} - -static inline int -HYPERVISOR_physdev_op( - int cmd, void *arg) -{ - int rc = _hypercall2(int, physdev_op, cmd, arg); - if (unlikely(rc == -ENOSYS)) { - struct physdev_op op; - op.cmd = cmd; - memcpy(&op.u, arg, sizeof(op.u)); - rc = _hypercall1(int, physdev_op_compat, &op); - } - return rc; -} +extern int +HYPERVISOR_event_channel_op(int cmd, void *arg); + +extern int +HYPERVISOR_acm_op(unsigned int cmd, void *arg); + +extern int +HYPERVISOR_xen_version(int cmd, void *arg); + +extern int +HYPERVISOR_console_io(int cmd, int count, char *str); + +extern int +HYPERVISOR_physdev_op(int cmd, void *arg); //XXX __HYPERVISOR_grant_table_op is used for this hypercall constant. -static inline int -____HYPERVISOR_grant_table_op( - unsigned int cmd, void *uop, unsigned int count, - unsigned long pa1, unsigned long pa2) -{ - return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2); -} +extern int +____HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); +// unsigned long pa1, unsigned long pa2); int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); -static inline int -HYPERVISOR_vcpu_op( - int cmd, int vcpuid, void *extra_args) -{ - return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); -} +extern int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args); extern int HYPERVISOR_suspend(unsigned long srec); -static inline int -HYPERVISOR_callback_op( - int cmd, void *arg) -{ - return _hypercall2(int, callback_op, cmd, arg); -} +extern int HYPERVISOR_callback_op(int cmd, void *arg); extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); static inline void exit_idle(void) {} diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Wed Aug 16 14:28:57 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Fri Aug 18 14:26:09 2006 +0200 @@ -70,9 +70,6 @@ HYPERVISOR_yield( { int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL); - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); - return rc; } @@ -81,9 +78,6 @@ HYPERVISOR_block( void) { int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL); - - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0); return rc; } @@ -97,9 +91,6 @@ HYPERVISOR_shutdown( }; int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); - - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason); return rc; } @@ -117,8 +108,6 @@ HYPERVISOR_poll( set_xen_guest_handle(sched_poll.ports, ports); rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll); - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); return rc; } diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/hcall.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hcall.c Fri Aug 18 14:26:09 2006 +0200 @@ -0,0 +1,669 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __ia64__ +extern unsigned long xen_pa(void *ptr); +#endif + +#define xen_guest_handle(hnd) ((hnd).p) + +/* 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. + * + * 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 HYPERVISOR_console_io(int cmd, int count, char *str) +{ + struct xencomm_desc *desc; + int rc; + + desc = xencomm_create_inline (str, count); + + rc = _hypercall3(int, console_io, cmd, count, desc); + + return rc; +} +EXPORT_SYMBOL(HYPERVISOR_console_io); + +int HYPERVISOR_event_channel_op(int cmd, void *op) +{ + struct xencomm_desc *desc; + int rc; + + desc = xencomm_create_inline(op, sizeof(evtchn_op_t)); + + rc = _hypercall2(int, event_channel_op, cmd, desc); + + return rc; +} +EXPORT_SYMBOL(HYPERVISOR_event_channel_op); + +int HYPERVISOR_xen_version(int cmd, void *arg) +{ + struct xencomm_desc *desc; + int argsize; + int rc; + + switch (cmd) { + case XENVER_version: + /* do not actually pass an argument */ + return _hypercall2(int, 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); + + rc = _hypercall2(int, xen_version, cmd, desc); + + return rc; +} +EXPORT_SYMBOL(HYPERVISOR_xen_version); + +int HYPERVISOR_physdev_op(int cmd, void *op) +{ + struct xencomm_desc *desc; + int rc; + + desc = xencomm_create_inline(op, sizeof(physdev_op_t)); + + rc = _hypercall2(int, physdev_op, cmd, desc); + + return rc; +} +EXPORT_SYMBOL(HYPERVISOR_physdev_op); + +int ____HYPERVISOR_grant_table_op(unsigned int cmd, void *op, + unsigned int count) +{ + struct xencomm_desc *desc; + struct xencomm_desc *frame_list; + long rc; + 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); + + rc = _hypercall3(int, grant_table_op, cmd, desc, count); + + return rc; +} +/*EXPORT_SYMBOL(HYPERVISOR_grant_table_op);*/ + +int HYPERVISOR_sched_op(int cmd, void *arg) +{ + int rc; + struct xencomm_desc *desc; + ulong argsize; + + switch (cmd) { + case SCHEDOP_yield: + case SCHEDOP_block: + return _hypercall2(int, 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); + + rc = _hypercall2(int, sched_op, cmd, desc); + + return rc; +} +EXPORT_SYMBOL(HYPERVISOR_sched_op); + +int HYPERVISOR_multicall(multicall_entry_t *call_list, int nr_calls) +{ + int i; + multicall_entry_t *mce; + struct xencomm_desc *desc; + + for (i = 0; i < nr_calls; i++) { + mce = 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 from %p\n", + __func__, mce->op, __builtin_return_address (0)); + return -ENOSYS; + } + } + + desc = xencomm_create_inline + (call_list, nr_calls * sizeof(multicall_entry_t)); + + return _hypercall2(int, multicall, desc, nr_calls); +} +EXPORT_SYMBOL(HYPERVISOR_multicall); + +int +HYPERVISOR_callback_op( + int cmd, void *arg) +{ + int rc; + struct xencomm_desc *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; + } + + rc = _hypercall2(int, callback_op, cmd, desc); + + return rc; +} + +static void xencommize_memory_reservation (xen_memory_reservation_t *mop) +{ + if (xen_guest_handle(mop->extent_start)) { + struct xencomm_desc *desc; + void * addr; + + addr = xen_guest_handle(mop->extent_start); + desc = xencomm_create_inline + (addr, + mop->nr_extents * + sizeof(*xen_guest_handle(mop->extent_start))); + set_xen_guest_handle(mop->extent_start, (void *)desc); + } +} + +int ____HYPERVISOR_memory_op(unsigned int cmd, void *arg) +{ + int ret; + + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + { + struct xencomm_desc *desc; + + desc = xencomm_create_inline + (arg, sizeof(xen_memory_reservation_t)); + + xencommize_memory_reservation + ((xen_memory_reservation_t *)arg); + + ret = _hypercall2(int, memory_op, cmd, desc); + } + break; + + case XENMEM_maximum_ram_page: + /* arg is NULL so we can call thru here */ + ret = _hypercall2(int, memory_op, cmd, NULL); + + break; + + case XENMEM_exchange: + { + struct xencomm_desc *desc; + + 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); + + ret = _hypercall2(int, memory_op, cmd, desc); + } + break; + + default: + printk("%s: unknown memory op %d\n", __func__, cmd); + ret = -ENOSYS; + } + return ret; + +} +/* EXPORT_SYMBOL(HYPERVISOR_memory_op);*/ + +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_desc *op_desc; + struct xencomm_desc *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 + 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 *)xen_pa(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 *)xen_pa(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 *)xen_pa(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 *)xen_pa(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 *)xen_pa(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 *)xen_pa(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 *)xen_pa(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 *)xen_pa(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 = _hypercall1(int, 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; +} + +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_desc *op_desc; + struct xencomm_desc *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 *)xen_pa(desc)); + + ret = _hypercall1(int, acm_op, 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_desc *desc = NULL; + struct xencomm_desc *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 *)xen_pa (desc)); + } + + ret = _hypercall2(int, 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_version(privcmd_hypercall_t *hypercall) +{ + int cmd = hypercall->arg[0]; + void __user *arg = (void __user *)hypercall->arg[1]; + struct xencomm_desc *desc; + size_t argsize; + int rc; + + switch (cmd) { + case XENVER_version: + /* do not actually pass an argument */ + return _hypercall2(int, 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 = _hypercall2(int, xen_version, cmd, xen_pa (desc)); + + xencomm_free(desc); + + return rc; +} + +static int xencomm_privcmd_event_channel_op(privcmd_hypercall_t *hypercall) +{ + int cmd = hypercall->arg[0]; + struct xencomm_desc *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 = _hypercall2(int, event_channel_op, cmd, xen_pa (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_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; + /* fallthru */ + /* below are the hcalls we know will fail and its ok */ + } +} + diff -r 8c6bb45901e7 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 Fri Aug 18 14:26:09 2006 +0200 @@ -0,0 +1,222 @@ +/* + * 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 + +int xencomm_debug; + +#ifdef __ia64__ +unsigned long kernel_start_pa; + +unsigned long xen_pa(void *ptr) +{ + unsigned long addr = (unsigned long)ptr; + + if (addr >= KERNEL_START + && addr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) + return addr - kernel_start_pa; + else + return __pa(addr); +} +#else +#define xen_pa(addr) __pa(addr) +#endif + +/* translate virtual address to physical address */ +static unsigned long __vaddr_to_paddr(unsigned long vaddr) +{ + struct page *page; + struct vm_area_struct *vma; + + if (vaddr > TASK_SIZE) { + /* kernel address */ + return xen_pa((void *)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); +} + +/* for use with kernel buffers before __vaddr_to_paddr works (e.g. boot + * console) */ +static unsigned long __kern_paddr(unsigned long vaddr) +{ + return xen_pa((void *)vaddr); +} + +static int __xencomm_init(struct xencomm_desc *desc, void *buffer, + unsigned long bytes, unsigned long (*to_phys)(unsigned long)) +{ + 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 = to_phys(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? */ + desc = (struct xencomm_desc *)__get_free_page(gfp_mask); + if (desc == NULL) + return NULL; + desc->nr_addrs = (PAGE_SIZE - sizeof(struct xencomm_desc)) / + sizeof(*desc->address); + + return desc; +} + +void xencomm_free(struct xencomm_desc *desc) +{ + if (desc) + free_page((unsigned long)desc); +} + +int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask) +{ + struct xencomm_desc *desc; + int rc; + + if (xencomm_debug) { + if ((!buffer) || (bytes == 0)) { + printk(KERN_ERR "%s: NULL buffer\n", __func__); + return 0; + } + printk("%s: %p[%ld]\n", __func__, buffer, bytes); + } + + if (buffer == NULL || bytes == 0) { + *ret = NULL; + return 0; + } + + desc = xencomm_alloc(gfp_mask); + if (!desc) { + printk("%s failure from %p\n", "xencomm_alloc", + __builtin_return_address (0)); + return -ENOMEM; + } + + rc = __xencomm_init(desc, buffer, bytes, __vaddr_to_paddr); + if (rc) { + printk("%s failure: %d\n", "__xencomm_init", rc); + xencomm_free(desc); + return rc; + } + + *ret = desc; + 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_desc **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, __kern_paddr); + if (rc) + return rc; + + *ret = desc; + return 0; +} + +struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long bytes) +{ + return (struct xencomm_desc *) + (__kern_paddr((unsigned long)buffer) | XENCOMM_INLINE); +} diff -r 8c6bb45901e7 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 Fri Aug 18 14:26:09 2006 +0200 @@ -0,0 +1,38 @@ +/* + * 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 + +#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) + +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 int xencomm_create_mini(void *area, int arealen, void *buffer, + unsigned long bytes, struct xencomm_desc **ret); +struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long bytes); + +#endif /* _LINUX_XENCOMM_H_ */