[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] [PPC] Add architecture-generic xencomm infrastructure.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1183726818 -3600 # Node ID 0dc0d418483e989dcbc6ef86a74b6f1f0172b1aa # Parent 3af06a6f06c2797e164d351e837ba01eb9f1b853 [PPC] Add architecture-generic xencomm infrastructure. Xencomm is the mechanism by which userspace can pass virtual addresses to Xen on architectures that cannot perform page table walks in software, including PowerPC and IA64. Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- drivers/xen/Kconfig | 3 drivers/xen/core/Makefile | 1 drivers/xen/core/xencomm.c | 192 +++++++++++++++++++++++++++++++++++++++++++++ include/xen/xencomm.h | 51 +++++++++++ 4 files changed, 247 insertions(+) diff -r 3af06a6f06c2 -r 0dc0d418483e drivers/xen/Kconfig --- a/drivers/xen/Kconfig Fri Jul 06 13:59:15 2007 +0100 +++ b/drivers/xen/Kconfig Fri Jul 06 14:00:18 2007 +0100 @@ -278,4 +278,7 @@ config XEN_BALLOON bool default y +config XEN_XENCOMM + bool + endif diff -r 3af06a6f06c2 -r 0dc0d418483e drivers/xen/core/Makefile --- a/drivers/xen/core/Makefile Fri Jul 06 13:59:15 2007 +0100 +++ b/drivers/xen/core/Makefile Fri Jul 06 14:00:18 2007 +0100 @@ -10,3 +10,4 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o obj-$(CONFIG_KEXEC) += machine_kexec.o +obj-$(CONFIG_XEN_XENCOMM) += xencomm.o diff -r 3af06a6f06c2 -r 0dc0d418483e drivers/xen/core/xencomm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/xen/core/xencomm.c Fri Jul 06 14:00:18 2007 +0100 @@ -0,0 +1,192 @@ +/* + * 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 + * + * Copyright (C) IBM Corp. 2006 + * + * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx> + */ + +#include <linux/gfp.h> +#include <linux/mm.h> +#include <asm/page.h> +#include <xen/xencomm.h> +#include <xen/interface/xen.h> + +static int xencomm_init(struct xencomm_desc *desc, + void *buffer, unsigned long bytes) +{ + unsigned long recorded = 0; + int i = 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 = xencomm_vtop(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; + + 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(void *desc) +{ + if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) + free_page((unsigned long)__va(desc)); +} + +static int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask) +{ + struct xencomm_desc *desc; + int rc; + + pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes); + + if (bytes == 0) { + /* don't create a descriptor; Xen recognizes NULL. */ + BUG_ON(buffer != NULL); + *ret = NULL; + return 0; + } + + BUG_ON(buffer == NULL); /* 'bytes' is non-zero */ + + desc = xencomm_alloc(gfp_mask); + if (!desc) { + printk("%s failure\n", "xencomm_alloc"); + return -ENOMEM; + } + + rc = xencomm_init(desc, buffer, bytes); + if (rc) { + printk("%s failure: %d\n", "xencomm_init", rc); + xencomm_free(desc); + return rc; + } + + *ret = desc; + return 0; +} + +/* check if memory address is within VMALLOC region */ +static int is_phys_contiguous(unsigned long addr) +{ + if (!is_kernel_addr(addr)) + return 0; + + return (addr < VMALLOC_START) || (addr >= VMALLOC_END); +} + +static void *xencomm_create_inline(void *ptr) +{ + unsigned long paddr; + + 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 || desc == NULL) + return NULL; + + return (void *)__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 3af06a6f06c2 -r 0dc0d418483e include/xen/xencomm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/xen/xencomm.h Fri Jul 06 14:00:18 2007 +0100 @@ -0,0 +1,51 @@ +/* + * 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 + * + * Copyright (C) IBM Corp. 2006 + * + * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx> + * Jerone Young <jyoung5@xxxxxxxxxx> + */ + +#ifndef _LINUX_XENCOMM_H_ +#define _LINUX_XENCOMM_H_ + +#include <xen/interface/xencomm.h> + +#define XENCOMM_MINI_ADDRS 3 +struct xencomm_mini { + struct xencomm_desc _desc; + uint64_t address[XENCOMM_MINI_ADDRS]; +}; + +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); + +static inline void *xencomm_pa(void *ptr) +{ + return (void *)xencomm_vtop((unsigned long)ptr); +} + +#endif /* _LINUX_XENCOMM_H_ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |