From mboxrd@z Thu Jan 1 00:00:00 1970 From: Hollis Blanchard Subject: [PATCH][XEN][POWERPC] xencomm common code Date: Fri, 08 Dec 2006 14:25:08 -0600 Message-ID: <1165609508.23364.14.camel@basalt> References: <1165344436.11779.27.camel@basalt> Reply-To: Hollis Blanchard Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1101626013==" Return-path: In-Reply-To: <1165344436.11779.27.camel@basalt> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Mime-version: 1.0 Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Keir Fraser Cc: xen-devel , xen-ppc-devel List-Id: xen-devel@lists.xenproject.org --===============1101626013== Content-Type: multipart/alternative; boundary="=-Tobgj89THXhXgUSHk2Wn" --=-Tobgj89THXhXgUSHk2Wn Content-Type: text/plain Content-Transfer-Encoding: 7bit Move xencomm code out of arch/powerpc so it can be shared with other architectures. Currently it is only built for PowerPC, leaving IA64's fork untouched. Signed-off-by: Hollis Blanchard diff -r 9d83185b4c37 xen/common/xencomm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/common/xencomm.c Wed Sep 13 10:04:10 2006 -0600 @@ -0,0 +1,316 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corp. 2006 + * + * Authors: Hollis Blanchard + * Tristan Gingold + */ + +#include +#include +#include +#include +#include +#include + + +#undef DEBUG +#ifdef DEBUG +static int xencomm_debug = 1; /* extremely verbose */ +#else +#define xencomm_debug 0 +#endif + +static unsigned long +xencomm_inline_from_guest(void *to, const void *from, unsigned int n, + unsigned int skip) +{ + unsigned long src_paddr = xencomm_inline_addr(from); + + src_paddr += skip; + + while (n > 0) { + unsigned int chunksz; + unsigned long src_maddr; + unsigned int bytes; + + chunksz = PAGE_SIZE - (src_paddr % PAGE_SIZE); + + bytes = min(chunksz, n); + + src_maddr = paddr_to_maddr(src_paddr); + if (xencomm_debug) + printk("%lx[%d] -> %lx\n", src_maddr, bytes, (unsigned long)to); + memcpy(to, (void *)src_maddr, bytes); + src_paddr += bytes; + to += bytes; + n -= bytes; + } + + /* Always successful. */ + return 0; +} + +/** + * xencomm_copy_from_guest: Copy a block of data from domain space. + * @to: Machine address. + * @from: Physical address to a xencomm buffer descriptor. + * @n: Number of bytes to copy. + * @skip: Number of bytes from the start to skip. + * + * Copy data from domain to hypervisor. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +unsigned long +xencomm_copy_from_guest(void *to, const void *from, unsigned int n, + unsigned int skip) +{ + struct xencomm_desc *desc; + unsigned int from_pos = 0; + unsigned int to_pos = 0; + unsigned int i = 0; + + if (xencomm_is_inline(from)) + return xencomm_inline_from_guest(to, from, n, skip); + + /* first we need to access the descriptor */ + desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)from); + if (desc == NULL) + return n; + + if (desc->magic != XENCOMM_MAGIC) { + printk("%s: error: %p magic was 0x%x\n", + __func__, desc, desc->magic); + return n; + } + + /* iterate through the descriptor, copying up to a page at a time */ + while ((to_pos < n) && (i < desc->nr_addrs)) { + unsigned long src_paddr = desc->address[i]; + unsigned int pgoffset; + unsigned int chunksz; + unsigned int chunk_skip; + + if (src_paddr == XENCOMM_INVALID) { + i++; + continue; + } + + pgoffset = src_paddr % PAGE_SIZE; + chunksz = PAGE_SIZE - pgoffset; + + chunk_skip = min(chunksz, skip); + from_pos += chunk_skip; + chunksz -= chunk_skip; + skip -= chunk_skip; + + if (skip == 0) { + unsigned long src_maddr; + unsigned long dest = (unsigned long)to + to_pos; + unsigned int bytes = min(chunksz, n - to_pos); + + src_maddr = paddr_to_maddr(src_paddr + chunk_skip); + if (src_maddr == 0) + return n - to_pos; + + if (xencomm_debug) + printk("%lx[%d] -> %lx\n", src_maddr, bytes, dest); + memcpy((void *)dest, (void *)src_maddr, bytes); + from_pos += bytes; + to_pos += bytes; + } + + i++; + } + + return n - to_pos; +} + +static unsigned long +xencomm_inline_to_guest(void *to, const void *from, unsigned int n, + unsigned int skip) +{ + unsigned long dest_paddr = xencomm_inline_addr(to); + + dest_paddr += skip; + + while (n > 0) { + unsigned int chunksz; + unsigned long dest_maddr; + unsigned int bytes; + + chunksz = PAGE_SIZE - (dest_paddr % PAGE_SIZE); + + bytes = min(chunksz, n); + + dest_maddr = paddr_to_maddr(dest_paddr); + if (xencomm_debug) + printk("%lx[%d] -> %lx\n", (unsigned long)from, bytes, dest_maddr); + memcpy((void *)dest_maddr, (void *)from, bytes); + dest_paddr += bytes; + from += bytes; + n -= bytes; + } + + /* Always successful. */ + return 0; +} + +/** + * xencomm_copy_to_guest: Copy a block of data to domain space. + * @to: Physical address to xencomm buffer descriptor. + * @from: Machine address. + * @n: Number of bytes to copy. + * @skip: Number of bytes from the start to skip. + * + * Copy data from hypervisor to domain. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +unsigned long +xencomm_copy_to_guest(void *to, const void *from, unsigned int n, + unsigned int skip) +{ + struct xencomm_desc *desc; + unsigned int from_pos = 0; + unsigned int to_pos = 0; + unsigned int i = 0; + + if (xencomm_is_inline(to)) + return xencomm_inline_to_guest(to, from, n, skip); + + /* first we need to access the descriptor */ + desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)to); + if (desc == NULL) + return n; + + if (desc->magic != XENCOMM_MAGIC) { + printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic); + return n; + } + + /* iterate through the descriptor, copying up to a page at a time */ + while ((from_pos < n) && (i < desc->nr_addrs)) { + unsigned long dest_paddr = desc->address[i]; + unsigned int pgoffset; + unsigned int chunksz; + unsigned int chunk_skip; + + if (dest_paddr == XENCOMM_INVALID) { + i++; + continue; + } + + pgoffset = dest_paddr % PAGE_SIZE; + chunksz = PAGE_SIZE - pgoffset; + + chunk_skip = min(chunksz, skip); + to_pos += chunk_skip; + chunksz -= chunk_skip; + skip -= chunk_skip; + + if (skip == 0) { + unsigned long dest_maddr; + unsigned long source = (unsigned long)from + from_pos; + unsigned int bytes = min(chunksz, n - from_pos); + + dest_maddr = paddr_to_maddr(dest_paddr + chunk_skip); + if (dest_maddr == 0) + return -1; + + if (xencomm_debug) + printk("%lx[%d] -> %lx\n", source, bytes, dest_maddr); + memcpy((void *)dest_maddr, (void *)source, bytes); + from_pos += bytes; + to_pos += bytes; + } + + i++; + } + + return n - from_pos; +} + +static int xencomm_inline_add_offset(void **handle, unsigned int bytes) +{ + *handle += bytes; + return 0; +} + +/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely + * exhausted pages to XENCOMM_INVALID. */ +int xencomm_add_offset(void **handle, unsigned int bytes) +{ + struct xencomm_desc *desc; + int i = 0; + + if (xencomm_is_inline(*handle)) + return xencomm_inline_add_offset(handle, bytes); + + /* first we need to access the descriptor */ + desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)*handle); + if (desc == NULL) + return -1; + + if (desc->magic != XENCOMM_MAGIC) { + printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic); + return -1; + } + + /* iterate through the descriptor incrementing addresses */ + while ((bytes > 0) && (i < desc->nr_addrs)) { + unsigned long dest_paddr = desc->address[i]; + unsigned int pgoffset; + unsigned int chunksz; + unsigned int chunk_skip; + + pgoffset = dest_paddr % PAGE_SIZE; + chunksz = PAGE_SIZE - pgoffset; + + chunk_skip = min(chunksz, bytes); + if (chunk_skip == chunksz) { + /* exhausted this page */ + desc->address[i] = XENCOMM_INVALID; + } else { + desc->address[i] += chunk_skip; + } + bytes -= chunk_skip; + } + return 0; +} + +int xencomm_handle_is_null(void *handle) +{ + struct xencomm_desc *desc; + int i; + + if (xencomm_is_inline(handle)) + return xencomm_inline_addr(handle) == 0; + + desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)handle); + if (desc == NULL) + return 1; + + for (i = 0; i < desc->nr_addrs; i++) + if (desc->address[i] != XENCOMM_INVALID) + return 0; + + return 1; +} + diff -r 9d83185b4c37 xen/include/xen/xencomm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/xen/xencomm.h Wed Sep 13 10:04:10 2006 -0600 @@ -0,0 +1,115 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corp. 2006 + * + * Authors: Hollis Blanchard + */ + +#ifndef __XENCOMM_H__ +#define __XENCOMM_H__ + +#include + +extern unsigned long xencomm_copy_to_guest(void *to, const void *from, + unsigned int len, unsigned int skip); +extern unsigned long xencomm_copy_from_guest(void *to, const void *from, + unsigned int len, unsigned int skip); +extern int xencomm_add_offset(void **handle, unsigned int bytes); +extern int xencomm_handle_is_null(void *ptr); + + +static inline int xencomm_is_inline(const void *handle) +{ + unsigned long addr = (unsigned long)handle; + return (addr & XENCOMM_INLINE_FLAG) == XENCOMM_INLINE_FLAG; +} + +static inline unsigned long xencomm_inline_addr(const void *handle) +{ + return (unsigned long)handle & ~XENCOMM_INLINE_FLAG; +} + +/* Is the guest handle a NULL reference? */ +#define guest_handle_is_null(hnd) \ + ((hnd).p == NULL || xencomm_handle_is_null((hnd).p)) + +/* Offset the given guest handle into the array it refers to. */ +#define guest_handle_add_offset(hnd, nr) ({ \ + const typeof((hnd).p) _ptr; \ + xencomm_add_offset((void **)&((hnd).p), nr * sizeof(*_ptr)); \ +}) + +/* Cast a guest handle to the specified type of handle. */ +#define guest_handle_cast(hnd, type) ({ \ + type *_x = (hnd).p; \ + XEN_GUEST_HANDLE(type) _y; \ + set_xen_guest_handle(_y, _x); \ + _y; \ +}) + +/* Since we run in real mode, we can safely access all addresses. That also + * means our __routines are identical to our "normal" routines. */ +#define guest_handle_okay(hnd, nr) 1 + +/* + * Copy an array of objects to guest context via a guest handle. + * Optionally specify an offset into the guest array. + */ +#define copy_to_guest_offset(hnd, idx, ptr, nr) \ + __copy_to_guest_offset(hnd, idx, ptr, nr) + +/* Copy sub-field of a structure to guest context via a guest handle. */ +#define copy_field_to_guest(hnd, ptr, field) \ + __copy_field_to_guest(hnd, ptr, field) + +/* + * Copy an array of objects from guest context via a guest handle. + * Optionally specify an offset into the guest array. + */ +#define copy_from_guest_offset(ptr, hnd, idx, nr) \ + __copy_from_guest_offset(ptr, hnd, idx, nr) + +/* Copy sub-field of a structure from guest context via a guest handle. */ +#define copy_field_from_guest(ptr, hnd, field) \ + __copy_field_from_guest(ptr, hnd, field) + +#define __copy_to_guest_offset(hnd, idx, ptr, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + xencomm_copy_to_guest(_x, _y, sizeof(*_x)*(nr), sizeof(*_x)*(idx)); \ +}) + +#define __copy_field_to_guest(hnd, ptr, field) ({ \ + const int _off = offsetof(typeof(*ptr), field); \ + const typeof(&(ptr)->field) _x = &(hnd).p->field; \ + const typeof(&(ptr)->field) _y = &(ptr)->field; \ + xencomm_copy_to_guest(_x, _y, sizeof(*_x), sizeof(*_x)*(_off)); \ +}) + +#define __copy_from_guest_offset(ptr, hnd, idx, nr) ({ \ + const typeof(ptr) _x = (hnd).p; \ + const typeof(ptr) _y = (ptr); \ + xencomm_copy_from_guest(_y, _x, sizeof(*_x)*(nr), sizeof(*_x)*(idx)); \ +}) + +#define __copy_field_from_guest(ptr, hnd, field) ({ \ + const int _off = offsetof(typeof(*ptr), field); \ + const typeof(&(ptr)->field) _x = &(hnd).p->field; \ + const typeof(&(ptr)->field) _y = &(ptr)->field; \ + xencomm_copy_to_guest(_y, _x, sizeof(*_x), sizeof(*_x)*(_off)); \ +}) + +#endif /* __XENCOMM_H__ */ diff -r 9d83185b4c37 xen/common/Makefile --- a/xen/common/Makefile Fri Dec 01 19:11:02 2006 -0500 +++ b/xen/common/Makefile Tue Dec 05 12:56:32 2006 -0600 @@ -31,5 +31,7 @@ obj-$(crash_debug) += gdbstub.o obj-$(crash_debug) += gdbstub.o obj-$(xenoprof) += xenoprof.o +obj-$(CONFIG_XENCOMM) += xencomm.o + # Object file contains changeset and compiler information. version.o: $(BASEDIR)/include/xen/compile.h diff -r 9d83185b4c37 config/powerpc64.mk --- a/config/powerpc64.mk Fri Dec 01 19:11:02 2006 -0500 +++ b/config/powerpc64.mk Tue Dec 05 12:56:11 2006 -0600 @@ -1,5 +1,7 @@ CONFIG_POWERPC := y CONFIG_POWERPC := y CONFIG_POWERPC_$(XEN_OS) := y +CONFIG_XENCOMM := y + CFLAGS += -DELFSIZE=64 LIBDIR := lib diff -r 9d83185b4c37 xen/arch/powerpc/usercopy.c --- a/xen/arch/powerpc/usercopy.c Fri Dec 01 19:11:02 2006 -0500 +++ b/xen/arch/powerpc/usercopy.c Fri Dec 01 17:18:45 2006 -0600 @@ -18,24 +18,14 @@ * Authors: Hollis Blanchard */ -#include -#include #include +#include #include -#include +#include #include -#include -#include - -#undef DEBUG -#ifdef DEBUG -static int xencomm_debug = 1; /* extremely verbose */ -#else -#define xencomm_debug 0 -#endif /* XXX need to return error, not panic, if domain passed a bad pointer */ -static unsigned long paddr_to_maddr(unsigned long paddr) +unsigned long paddr_to_maddr(unsigned long paddr) { struct vcpu *v = get_current(); struct domain *d = v->domain; @@ -58,208 +48,3 @@ static unsigned long paddr_to_maddr(unsi return pa; } - -/** - * xencomm_copy_from_guest: Copy a block of data from domain space. - * @to: Machine address. - * @from: Physical address to a xencomm buffer descriptor. - * @n: Number of bytes to copy. - * @skip: Number of bytes from the start to skip. - * - * Copy data from domain to hypervisor. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -unsigned long -xencomm_copy_from_guest(void *to, const void *from, unsigned int n, - unsigned int skip) -{ - struct xencomm_desc *desc; - unsigned int from_pos = 0; - unsigned int to_pos = 0; - unsigned int i = 0; - - /* first we need to access the descriptor */ - desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)from); - if (desc == NULL) - return n; - - if (desc->magic != XENCOMM_MAGIC) { - printk("%s: error: %p magic was 0x%x\n", - __func__, desc, desc->magic); - return n; - } - - /* iterate through the descriptor, copying up to a page at a time */ - while ((to_pos < n) && (i < desc->nr_addrs)) { - unsigned long src_paddr = desc->address[i]; - unsigned int pgoffset; - unsigned int chunksz; - unsigned int chunk_skip; - - if (src_paddr == XENCOMM_INVALID) { - i++; - continue; - } - - pgoffset = src_paddr % PAGE_SIZE; - chunksz = PAGE_SIZE - pgoffset; - - chunk_skip = min(chunksz, skip); - from_pos += chunk_skip; - chunksz -= chunk_skip; - skip -= chunk_skip; - - if (skip == 0) { - unsigned long src_maddr; - unsigned long dest = (unsigned long)to + to_pos; - unsigned int bytes = min(chunksz, n - to_pos); - - src_maddr = paddr_to_maddr(src_paddr + chunk_skip); - if (src_maddr == 0) - return n - to_pos; - - if (xencomm_debug) - printk("%lx[%d] -> %lx\n", src_maddr, bytes, dest); - memcpy((void *)dest, (void *)src_maddr, bytes); - from_pos += bytes; - to_pos += bytes; - } - - i++; - } - - return n - to_pos; -} - -/** - * xencomm_copy_to_guest: Copy a block of data to domain space. - * @to: Physical address to xencomm buffer descriptor. - * @from: Machine address. - * @n: Number of bytes to copy. - * @skip: Number of bytes from the start to skip. - * - * Copy data from hypervisor to domain. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -unsigned long -xencomm_copy_to_guest(void *to, const void *from, unsigned int n, - unsigned int skip) -{ - struct xencomm_desc *desc; - unsigned int from_pos = 0; - unsigned int to_pos = 0; - unsigned int i = 0; - - /* first we need to access the descriptor */ - desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)to); - if (desc == NULL) - return n; - - if (desc->magic != XENCOMM_MAGIC) { - printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic); - return n; - } - - /* iterate through the descriptor, copying up to a page at a time */ - while ((from_pos < n) && (i < desc->nr_addrs)) { - unsigned long dest_paddr = desc->address[i]; - unsigned int pgoffset; - unsigned int chunksz; - unsigned int chunk_skip; - - if (dest_paddr == XENCOMM_INVALID) { - i++; - continue; - } - - pgoffset = dest_paddr % PAGE_SIZE; - chunksz = PAGE_SIZE - pgoffset; - - chunk_skip = min(chunksz, skip); - to_pos += chunk_skip; - chunksz -= chunk_skip; - skip -= chunk_skip; - - if (skip == 0) { - unsigned long dest_maddr; - unsigned long source = (unsigned long)from + from_pos; - unsigned int bytes = min(chunksz, n - from_pos); - - dest_maddr = paddr_to_maddr(dest_paddr + chunk_skip); - if (dest_maddr == 0) - return -1; - - if (xencomm_debug) - printk("%lx[%d] -> %lx\n", source, bytes, dest_maddr); - memcpy((void *)dest_maddr, (void *)source, bytes); - from_pos += bytes; - to_pos += bytes; - } - - i++; - } - - return n - from_pos; -} - -/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely - * exhausted pages to XENCOMM_INVALID. */ -int xencomm_add_offset(void *handle, unsigned int bytes) -{ - struct xencomm_desc *desc; - int i = 0; - - /* first we need to access the descriptor */ - desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)handle); - if (desc == NULL) - return -1; - - if (desc->magic != XENCOMM_MAGIC) { - printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic); - return -1; - } - - /* iterate through the descriptor incrementing addresses */ - while ((bytes > 0) && (i < desc->nr_addrs)) { - unsigned long dest_paddr = desc->address[i]; - unsigned int pgoffset; - unsigned int chunksz; - unsigned int chunk_skip; - - if (dest_paddr == XENCOMM_INVALID) { - i++; - continue; - } - - pgoffset = dest_paddr % PAGE_SIZE; - chunksz = PAGE_SIZE - pgoffset; - - chunk_skip = min(chunksz, bytes); - if (chunk_skip == chunksz) { - /* exhausted this page */ - desc->address[i] = XENCOMM_INVALID; - } else { - desc->address[i] += chunk_skip; - } - bytes -= chunk_skip; - - i++; - } - return 0; -} - -int xencomm_handle_is_null(void *ptr) -{ - struct xencomm_desc *desc; - - desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)ptr); - if (desc == NULL) - return 1; - - return (desc->nr_addrs == 0); -} - -- Hollis Blanchard IBM Linux Technology Center --=-Tobgj89THXhXgUSHk2Wn Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 7bit Move xencomm code out of arch/powerpc so it can be shared with other architectures. Currently it is only built for PowerPC, leaving IA64's fork untouched.

Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>

diff -r 9d83185b4c37 xen/common/xencomm.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/xencomm.c	Wed Sep 13 10:04:10 2006 -0600
@@ -0,0 +1,316 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *          Tristan Gingold <tristan.gingold@bull.net>
+ */
+
+#include <xen/config.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <xen/xencomm.h>
+#include <public/xen.h>
+#include <public/xencomm.h>
+
+
+#undef DEBUG
+#ifdef DEBUG
+static int xencomm_debug = 1; /* extremely verbose */
+#else
+#define xencomm_debug 0
+#endif
+
+static unsigned long
+xencomm_inline_from_guest(void *to, const void *from, unsigned int n,
+        unsigned int skip)
+{
+    unsigned long src_paddr = xencomm_inline_addr(from);
+
+    src_paddr += skip;
+
+    while (n > 0) {
+        unsigned int chunksz;
+        unsigned long src_maddr;
+        unsigned int bytes;
+
+        chunksz = PAGE_SIZE - (src_paddr % PAGE_SIZE);
+
+        bytes = min(chunksz, n);
+
+        src_maddr = paddr_to_maddr(src_paddr);
+        if (xencomm_debug)
+            printk("%lx[%d] -> %lx\n", src_maddr, bytes, (unsigned long)to);
+        memcpy(to, (void *)src_maddr, bytes);
+        src_paddr += bytes;
+        to += bytes;
+        n -= bytes;
+    }
+
+    /* Always successful. */
+    return 0;
+}
+
+/**
+ * xencomm_copy_from_guest: Copy a block of data from domain space.
+ * @to:   Machine address.
+ * @from: Physical address to a xencomm buffer descriptor.
+ * @n:    Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from domain to hypervisor.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_from_guest(void *to, const void *from, unsigned int n,
+        unsigned int skip)
+{
+    struct xencomm_desc *desc;
+    unsigned int from_pos = 0;
+    unsigned int to_pos = 0;
+    unsigned int i = 0;
+
+    if (xencomm_is_inline(from))
+        return xencomm_inline_from_guest(to, from, n, skip);
+
+    /* first we need to access the descriptor */
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)from);
+    if (desc == NULL)
+        return n;
+
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s: error: %p magic was 0x%x\n",
+               __func__, desc, desc->magic);
+        return n;
+    }
+
+    /* iterate through the descriptor, copying up to a page at a time */
+    while ((to_pos < n) && (i < desc->nr_addrs)) {
+        unsigned long src_paddr = desc->address[i];
+        unsigned int pgoffset;
+        unsigned int chunksz;
+        unsigned int chunk_skip;
+
+        if (src_paddr == XENCOMM_INVALID) {
+            i++;
+            continue;
+        }
+
+        pgoffset = src_paddr % PAGE_SIZE;
+        chunksz = PAGE_SIZE - pgoffset;
+
+        chunk_skip = min(chunksz, skip);
+        from_pos += chunk_skip;
+        chunksz -= chunk_skip;
+        skip -= chunk_skip;
+
+        if (skip == 0) {
+            unsigned long src_maddr;
+            unsigned long dest = (unsigned long)to + to_pos;
+            unsigned int bytes = min(chunksz, n - to_pos);
+
+            src_maddr = paddr_to_maddr(src_paddr + chunk_skip);
+            if (src_maddr == 0)
+                return n - to_pos;
+
+            if (xencomm_debug)
+                printk("%lx[%d] -> %lx\n", src_maddr, bytes, dest);
+            memcpy((void *)dest, (void *)src_maddr, bytes);
+            from_pos += bytes;
+            to_pos += bytes;
+        }
+
+        i++;
+    }
+
+    return n - to_pos;
+}
+
+static unsigned long
+xencomm_inline_to_guest(void *to, const void *from, unsigned int n,
+        unsigned int skip)
+{
+    unsigned long dest_paddr = xencomm_inline_addr(to);
+
+    dest_paddr += skip;
+
+    while (n > 0) {
+        unsigned int chunksz;
+        unsigned long dest_maddr;
+        unsigned int bytes;
+
+        chunksz = PAGE_SIZE - (dest_paddr % PAGE_SIZE);
+
+        bytes = min(chunksz, n);
+
+        dest_maddr = paddr_to_maddr(dest_paddr);
+        if (xencomm_debug)
+            printk("%lx[%d] -> %lx\n", (unsigned long)from, bytes, dest_maddr);
+        memcpy((void *)dest_maddr, (void *)from, bytes);
+        dest_paddr += bytes;
+        from += bytes;
+        n -= bytes;
+    }
+
+    /* Always successful.  */
+    return 0;
+}
+
+/**
+ * xencomm_copy_to_guest: Copy a block of data to domain space.
+ * @to:     Physical address to xencomm buffer descriptor.
+ * @from:   Machine address.
+ * @n:      Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from hypervisor to domain.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_to_guest(void *to, const void *from, unsigned int n,
+        unsigned int skip)
+{
+    struct xencomm_desc *desc;
+    unsigned int from_pos = 0;
+    unsigned int to_pos = 0;
+    unsigned int i = 0;
+
+    if (xencomm_is_inline(to))
+        return xencomm_inline_to_guest(to, from, n, skip);
+
+    /* first we need to access the descriptor */
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)to);
+    if (desc == NULL)
+        return n;
+
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+        return n;
+    }
+
+    /* iterate through the descriptor, copying up to a page at a time */
+    while ((from_pos < n) && (i < desc->nr_addrs)) {
+        unsigned long dest_paddr = desc->address[i];
+        unsigned int pgoffset;
+        unsigned int chunksz;
+        unsigned int chunk_skip;
+
+        if (dest_paddr == XENCOMM_INVALID) {
+            i++;
+            continue;
+        }
+
+        pgoffset = dest_paddr % PAGE_SIZE;
+        chunksz = PAGE_SIZE - pgoffset;
+
+        chunk_skip = min(chunksz, skip);
+        to_pos += chunk_skip;
+        chunksz -= chunk_skip;
+        skip -= chunk_skip;
+
+        if (skip == 0) {
+            unsigned long dest_maddr;
+            unsigned long source = (unsigned long)from + from_pos;
+            unsigned int bytes = min(chunksz, n - from_pos);
+
+            dest_maddr = paddr_to_maddr(dest_paddr + chunk_skip);
+            if (dest_maddr == 0)
+                return -1;
+
+            if (xencomm_debug)
+                printk("%lx[%d] -> %lx\n", source, bytes, dest_maddr);
+            memcpy((void *)dest_maddr, (void *)source, bytes);
+            from_pos += bytes;
+            to_pos += bytes;
+        }
+
+        i++;
+    }
+
+    return n - from_pos;
+}
+
+static int xencomm_inline_add_offset(void **handle, unsigned int bytes)
+{
+    *handle += bytes;
+    return 0;
+}
+
+/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely
+ * exhausted pages to XENCOMM_INVALID. */
+int xencomm_add_offset(void **handle, unsigned int bytes)
+{
+    struct xencomm_desc *desc;
+    int i = 0;
+
+    if (xencomm_is_inline(*handle))
+        return xencomm_inline_add_offset(handle, bytes);
+
+    /* first we need to access the descriptor */
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)*handle);
+    if (desc == NULL)
+        return -1;
+
+    if (desc->magic != XENCOMM_MAGIC) {
+        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+        return -1;
+    }
+
+    /* iterate through the descriptor incrementing addresses */
+    while ((bytes > 0) && (i < desc->nr_addrs)) {
+        unsigned long dest_paddr = desc->address[i];
+        unsigned int pgoffset;
+        unsigned int chunksz;
+        unsigned int chunk_skip;
+
+        pgoffset = dest_paddr % PAGE_SIZE;
+        chunksz = PAGE_SIZE - pgoffset;
+
+        chunk_skip = min(chunksz, bytes);
+        if (chunk_skip == chunksz) {
+            /* exhausted this page */
+            desc->address[i] = XENCOMM_INVALID;
+        } else {
+            desc->address[i] += chunk_skip;
+        }
+        bytes -= chunk_skip;
+    }
+    return 0;
+}
+
+int xencomm_handle_is_null(void *handle)
+{
+    struct xencomm_desc *desc;
+    int i;
+
+    if (xencomm_is_inline(handle))
+        return xencomm_inline_addr(handle) == 0;
+
+    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)handle);
+    if (desc == NULL)
+        return 1;
+
+    for (i = 0; i < desc->nr_addrs; i++)
+        if (desc->address[i] != XENCOMM_INVALID)
+            return 0;
+
+    return 1;
+}
+
diff -r 9d83185b4c37 xen/include/xen/xencomm.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/xencomm.h	Wed Sep 13 10:04:10 2006 -0600
@@ -0,0 +1,115 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __XENCOMM_H__
+#define __XENCOMM_H__
+
+#include <public/xen.h>
+
+extern unsigned long xencomm_copy_to_guest(void *to, const void *from,
+        unsigned int len, unsigned int skip); 
+extern unsigned long xencomm_copy_from_guest(void *to, const void *from,
+        unsigned int len, unsigned int skip); 
+extern int xencomm_add_offset(void **handle, unsigned int bytes);
+extern int xencomm_handle_is_null(void *ptr);
+
+
+static inline int xencomm_is_inline(const void *handle)
+{
+    unsigned long addr = (unsigned long)handle;
+    return (addr & XENCOMM_INLINE_FLAG) == XENCOMM_INLINE_FLAG;
+}
+
+static inline unsigned long xencomm_inline_addr(const void *handle)
+{
+	return (unsigned long)handle & ~XENCOMM_INLINE_FLAG;
+}
+
+/* Is the guest handle a NULL reference? */
+#define guest_handle_is_null(hnd) \
+    ((hnd).p == NULL || xencomm_handle_is_null((hnd).p))
+
+/* Offset the given guest handle into the array it refers to. */
+#define guest_handle_add_offset(hnd, nr) ({         \
+    const typeof((hnd).p) _ptr;                     \
+    xencomm_add_offset((void **)&((hnd).p), nr * sizeof(*_ptr));   \
+})
+
+/* Cast a guest handle to the specified type of handle. */
+#define guest_handle_cast(hnd, type) ({         \
+    type *_x = (hnd).p;                         \
+    XEN_GUEST_HANDLE(type) _y; \
+    set_xen_guest_handle(_y, _x); \
+    _y; \
+})
+
+/* Since we run in real mode, we can safely access all addresses. That also
+ * means our __routines are identical to our "normal" routines. */
+#define guest_handle_okay(hnd, nr) 1
+
+/*
+ * Copy an array of objects to guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
+ */
+#define copy_to_guest_offset(hnd, idx, ptr, nr) \
+    __copy_to_guest_offset(hnd, idx, ptr, nr)
+
+/* Copy sub-field of a structure to guest context via a guest handle. */
+#define copy_field_to_guest(hnd, ptr, field) \
+    __copy_field_to_guest(hnd, ptr, field)
+
+/*
+ * Copy an array of objects from guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
+ */
+#define copy_from_guest_offset(ptr, hnd, idx, nr) \
+    __copy_from_guest_offset(ptr, hnd, idx, nr)
+
+/* Copy sub-field of a structure from guest context via a guest handle. */
+#define copy_field_from_guest(ptr, hnd, field) \
+    __copy_field_from_guest(ptr, hnd, field)
+
+#define __copy_to_guest_offset(hnd, idx, ptr, nr) ({                \
+    const typeof(ptr) _x = (hnd).p;                                 \
+    const typeof(ptr) _y = (ptr);                                   \
+    xencomm_copy_to_guest(_x, _y, sizeof(*_x)*(nr), sizeof(*_x)*(idx)); \
+})
+
+#define __copy_field_to_guest(hnd, ptr, field) ({                   \
+    const int _off = offsetof(typeof(*ptr), field);                  \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;               \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;                 \
+    xencomm_copy_to_guest(_x, _y, sizeof(*_x), sizeof(*_x)*(_off)); \
+})
+
+#define __copy_from_guest_offset(ptr, hnd, idx, nr) ({              \
+    const typeof(ptr) _x = (hnd).p;                                 \
+    const typeof(ptr) _y = (ptr);                                   \
+    xencomm_copy_from_guest(_y, _x, sizeof(*_x)*(nr), sizeof(*_x)*(idx));  \
+})
+
+#define __copy_field_from_guest(ptr, hnd, field) ({                 \
+    const int _off = offsetof(typeof(*ptr), field);                 \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;               \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;                 \
+    xencomm_copy_to_guest(_y, _x, sizeof(*_x), sizeof(*_x)*(_off)); \
+})
+
+#endif /* __XENCOMM_H__ */
diff -r 9d83185b4c37 xen/common/Makefile
--- a/xen/common/Makefile	Fri Dec 01 19:11:02 2006 -0500
+++ b/xen/common/Makefile	Tue Dec 05 12:56:32 2006 -0600
@@ -31,5 +31,7 @@ obj-$(crash_debug) += gdbstub.o
 obj-$(crash_debug) += gdbstub.o
 obj-$(xenoprof)    += xenoprof.o
 
+obj-$(CONFIG_XENCOMM) += xencomm.o
+
 # Object file contains changeset and compiler information.
 version.o: $(BASEDIR)/include/xen/compile.h
diff -r 9d83185b4c37 config/powerpc64.mk
--- a/config/powerpc64.mk	Fri Dec 01 19:11:02 2006 -0500
+++ b/config/powerpc64.mk	Tue Dec 05 12:56:11 2006 -0600
@@ -1,5 +1,7 @@ CONFIG_POWERPC := y
 CONFIG_POWERPC := y
 CONFIG_POWERPC_$(XEN_OS) := y
 
+CONFIG_XENCOMM := y
+
 CFLAGS += -DELFSIZE=64
 LIBDIR := lib
diff -r 9d83185b4c37 xen/arch/powerpc/usercopy.c
--- a/xen/arch/powerpc/usercopy.c	Fri Dec 01 19:11:02 2006 -0500
+++ b/xen/arch/powerpc/usercopy.c	Fri Dec 01 17:18:45 2006 -0600
@@ -18,24 +18,14 @@
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
 
-#include <xen/config.h>
-#include <xen/mm.h>
 #include <xen/sched.h>
+#include <xen/lib.h>
 #include <asm/current.h>
-#include <asm/uaccess.h>
+#include <asm/page.h>
 #include <asm/debugger.h>
-#include <public/xen.h>
-#include <public/xencomm.h>
-
-#undef DEBUG
-#ifdef DEBUG
-static int xencomm_debug = 1; /* extremely verbose */
-#else
-#define xencomm_debug 0
-#endif
 
 /* XXX need to return error, not panic, if domain passed a bad pointer */
-static unsigned long paddr_to_maddr(unsigned long paddr)
+unsigned long paddr_to_maddr(unsigned long paddr)
 {
     struct vcpu *v = get_current();
     struct domain *d = v->domain;
@@ -58,208 +48,3 @@ static unsigned long paddr_to_maddr(unsi
 
     return pa;
 }
-
-/**
- * xencomm_copy_from_guest: Copy a block of data from domain space.
- * @to:   Machine address.
- * @from: Physical address to a xencomm buffer descriptor.
- * @n:    Number of bytes to copy.
- * @skip: Number of bytes from the start to skip.
- *
- * Copy data from domain to hypervisor.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
-unsigned long
-xencomm_copy_from_guest(void *to, const void *from, unsigned int n,
-        unsigned int skip)
-{
-    struct xencomm_desc *desc;
-    unsigned int from_pos = 0;
-    unsigned int to_pos = 0;
-    unsigned int i = 0;
-
-    /* first we need to access the descriptor */
-    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)from);
-    if (desc == NULL)
-        return n;
-
-    if (desc->magic != XENCOMM_MAGIC) {
-        printk("%s: error: %p magic was 0x%x\n",
-               __func__, desc, desc->magic);
-        return n;
-    }
-
-    /* iterate through the descriptor, copying up to a page at a time */
-    while ((to_pos < n) && (i < desc->nr_addrs)) {
-        unsigned long src_paddr = desc->address[i];
-        unsigned int pgoffset;
-        unsigned int chunksz;
-        unsigned int chunk_skip;
-
-        if (src_paddr == XENCOMM_INVALID) {
-            i++;
-            continue;
-        }
-
-        pgoffset = src_paddr % PAGE_SIZE;
-        chunksz = PAGE_SIZE - pgoffset;
-
-        chunk_skip = min(chunksz, skip);
-        from_pos += chunk_skip;
-        chunksz -= chunk_skip;
-        skip -= chunk_skip;
-
-        if (skip == 0) {
-            unsigned long src_maddr;
-            unsigned long dest = (unsigned long)to + to_pos;
-            unsigned int bytes = min(chunksz, n - to_pos);
-
-            src_maddr = paddr_to_maddr(src_paddr + chunk_skip);
-            if (src_maddr == 0)
-                return n - to_pos;
-
-            if (xencomm_debug)
-                printk("%lx[%d] -> %lx\n", src_maddr, bytes, dest);
-            memcpy((void *)dest, (void *)src_maddr, bytes);
-            from_pos += bytes;
-            to_pos += bytes;
-        }
-
-        i++;
-    }
-
-    return n - to_pos;
-}
-
-/**
- * xencomm_copy_to_guest: Copy a block of data to domain space.
- * @to:     Physical address to xencomm buffer descriptor.
- * @from:   Machine address.
- * @n:      Number of bytes to copy.
- * @skip: Number of bytes from the start to skip.
- *
- * Copy data from hypervisor to domain.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
-unsigned long
-xencomm_copy_to_guest(void *to, const void *from, unsigned int n,
-        unsigned int skip)
-{
-    struct xencomm_desc *desc;
-    unsigned int from_pos = 0;
-    unsigned int to_pos = 0;
-    unsigned int i = 0;
-
-    /* first we need to access the descriptor */
-    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)to);
-    if (desc == NULL)
-        return n;
-
-    if (desc->magic != XENCOMM_MAGIC) {
-        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
-        return n;
-    }
-
-    /* iterate through the descriptor, copying up to a page at a time */
-    while ((from_pos < n) && (i < desc->nr_addrs)) {
-        unsigned long dest_paddr = desc->address[i];
-        unsigned int pgoffset;
-        unsigned int chunksz;
-        unsigned int chunk_skip;
-
-        if (dest_paddr == XENCOMM_INVALID) {
-            i++;
-            continue;
-        }
-
-        pgoffset = dest_paddr % PAGE_SIZE;
-        chunksz = PAGE_SIZE - pgoffset;
-
-        chunk_skip = min(chunksz, skip);
-        to_pos += chunk_skip;
-        chunksz -= chunk_skip;
-        skip -= chunk_skip;
-
-        if (skip == 0) {
-            unsigned long dest_maddr;
-            unsigned long source = (unsigned long)from + from_pos;
-            unsigned int bytes = min(chunksz, n - from_pos);
-
-            dest_maddr = paddr_to_maddr(dest_paddr + chunk_skip);
-            if (dest_maddr == 0)
-                return -1;
-
-            if (xencomm_debug)
-                printk("%lx[%d] -> %lx\n", source, bytes, dest_maddr);
-            memcpy((void *)dest_maddr, (void *)source, bytes);
-            from_pos += bytes;
-            to_pos += bytes;
-        }
-
-        i++;
-    }
-
-    return n - from_pos;
-}
-
-/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely
- * exhausted pages to XENCOMM_INVALID. */
-int xencomm_add_offset(void *handle, unsigned int bytes)
-{
-    struct xencomm_desc *desc;
-    int i = 0;
-
-    /* first we need to access the descriptor */
-    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)handle);
-    if (desc == NULL)
-        return -1;
-
-    if (desc->magic != XENCOMM_MAGIC) {
-        printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
-        return -1;
-    }
-
-    /* iterate through the descriptor incrementing addresses */
-    while ((bytes > 0) && (i < desc->nr_addrs)) {
-        unsigned long dest_paddr = desc->address[i];
-        unsigned int pgoffset;
-        unsigned int chunksz;
-        unsigned int chunk_skip;
-
-        if (dest_paddr == XENCOMM_INVALID) {
-            i++;
-            continue;
-        }
-
-        pgoffset = dest_paddr % PAGE_SIZE;
-        chunksz = PAGE_SIZE - pgoffset;
-
-        chunk_skip = min(chunksz, bytes);
-        if (chunk_skip == chunksz) {
-            /* exhausted this page */
-            desc->address[i] = XENCOMM_INVALID;
-        } else {
-            desc->address[i] += chunk_skip;
-        }
-        bytes -= chunk_skip;
-
-	i++;
-    }
-    return 0;
-}
-
-int xencomm_handle_is_null(void *ptr)
-{
-    struct xencomm_desc *desc;
-
-    desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)ptr);
-    if (desc == NULL)
-        return 1;
-
-    return (desc->nr_addrs == 0);
-}
-


-- 
Hollis Blanchard
IBM Linux Technology Center
--=-Tobgj89THXhXgUSHk2Wn-- --===============1101626013== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --===============1101626013==--