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