# HG changeset patch
# User Hollis Blanchard <hollisb@xxxxxxxxxx>
# Node ID b057b940f6ebeec7527c089b5656669025d9a640
# Parent a79b3252bbe46a13d91586081e7f6be278b07126
[XEN] Move xencomm into generic code and support "inline" handles.
- inline code based on code from Tristan Gingold <tristan.gingold@xxxxxxxx>
- make xencomm_handle_is_null() more thorough (check all addresses)
- delete unused asm-powerpc/uaccess.h
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
---
xen/include/asm-powerpc/uaccess.h | 38 ---
xen/arch/powerpc/usercopy.c | 214 ----------------------
xen/common/Makefile | 1
xen/common/xencomm.c | 316 +++++++++++++++++++++++++++++++++
xen/include/asm-powerpc/guest_access.h | 78 --------
xen/include/asm-powerpc/mm.h | 27 --
xen/include/asm-powerpc/page.h | 25 ++
xen/include/public/arch-powerpc.h | 2
xen/include/public/xencomm.h | 6
xen/include/xen/xencomm.h | 115 ++++++++++++
10 files changed, 471 insertions(+), 351 deletions(-)
diff -r a79b3252bbe4 -r b057b940f6eb xen/arch/powerpc/usercopy.c
--- a/xen/arch/powerpc/usercopy.c Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/arch/powerpc/usercopy.c Tue Sep 12 12:08:04 2006 -0500
@@ -18,23 +18,13 @@
* Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
*/
-#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 <public/xen.h>
-#include <public/xencomm.h>
-
-#undef DEBUG
-#ifdef DEBUG
-static int xencomm_debug = 1; /* extremely verbose */
-#else
-#define xencomm_debug 0
-#endif
+#include <asm/page.h>
/* 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;
@@ -77,201 +67,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;
-
- 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 *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);
-}
-
diff -r a79b3252bbe4 -r b057b940f6eb xen/common/Makefile
--- a/xen/common/Makefile Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/common/Makefile Tue Sep 12 12:08:04 2006 -0500
@@ -24,6 +24,7 @@ obj-y += timer.o
obj-y += timer.o
obj-y += version.o
obj-y += vsprintf.o
+obj-y += xencomm.o
obj-y += xmalloc.o
obj-$(perfc) += perfc.o
diff -r a79b3252bbe4 -r b057b940f6eb xen/include/asm-powerpc/guest_access.h
--- a/xen/include/asm-powerpc/guest_access.h Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/include/asm-powerpc/guest_access.h Tue Sep 12 12:08:04 2006 -0500
@@ -21,82 +21,6 @@
#ifndef __PPC_GUEST_ACCESS_H__
#define __PPC_GUEST_ACCESS_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);
-
-
-/* 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 = (hnd).p; \
- xencomm_add_offset(_ptr, 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)); \
-})
+#include <xen/xencomm.h>
#endif /* __PPC_GUEST_ACCESS_H__ */
diff -r a79b3252bbe4 -r b057b940f6eb xen/include/asm-powerpc/mm.h
--- a/xen/include/asm-powerpc/mm.h Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/include/asm-powerpc/mm.h Tue Sep 12 12:08:04 2006 -0500
@@ -28,7 +28,7 @@
#include <asm/misc.h>
#include <asm/system.h>
#include <asm/flushtlb.h>
-#include <asm/uaccess.h>
+#include <asm/page.h>
#define memguard_guard_range(_p,_l) ((void)0)
#define memguard_unguard_range(_p,_l) ((void)0)
@@ -234,29 +234,8 @@ extern int update_grant_va_mapping(unsig
struct domain *,
struct vcpu *);
-#define INVALID_MFN (~0UL)
-#define PFN_TYPE_NONE 0
-#define PFN_TYPE_RMA 1
-#define PFN_TYPE_LOGICAL 2
-#define PFN_TYPE_IO 3
-#define PFN_TYPE_REMOTE 4
-
-extern ulong pfn2mfn(struct domain *d, ulong pfn, int *type);
-
/* Arch-specific portion of memory_op hypercall. */
long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
-
-/* XXX implement me? */
-#define set_gpfn_from_mfn(mfn, pfn) do { } while (0)
-/* XXX only used for debug print right now... */
-#define get_gpfn_from_mfn(mfn) (mfn)
-
-static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gmfn)
-{
- return pfn2mfn(d, gmfn, NULL);
-}
-
-#define mfn_to_gmfn(_d, mfn) (mfn)
extern int allocate_rma(struct domain *d, unsigned int order_pages);
extern uint allocate_extents(struct domain *d, uint nrpages, uint rma_nrpages);
@@ -265,4 +244,8 @@ extern int steal_page(struct domain *d,
extern int steal_page(struct domain *d, struct page_info *page,
unsigned int memflags);
+/* XXX these just exist until we can stop #including x86 code */
+#define access_ok(addr,size) 1
+#define array_access_ok(addr,count,size) 1
+
#endif
diff -r a79b3252bbe4 -r b057b940f6eb xen/include/asm-powerpc/page.h
--- a/xen/include/asm-powerpc/page.h Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/include/asm-powerpc/page.h Tue Sep 12 12:08:04 2006 -0500
@@ -13,7 +13,7 @@
* 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. 2005
+ * Copyright (C) IBM Corp. 2005, 2006
*
* Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
*/
@@ -112,5 +112,28 @@ static inline int get_order_from_pages(u
#define _PAGE_PAT 0x080UL
#define _PAGE_PSE 0x080UL
#define _PAGE_GLOBAL 0x100UL
+
+#define INVALID_MFN (~0UL)
+#define PFN_TYPE_NONE 0
+#define PFN_TYPE_RMA 1
+#define PFN_TYPE_LOGICAL 2
+#define PFN_TYPE_IO 3
+#define PFN_TYPE_REMOTE 4
+
+extern ulong pfn2mfn(struct domain *d, ulong pfn, int *type);
+extern unsigned long paddr_to_maddr(unsigned long paddr);
+
+/* XXX implement me? */
+#define set_gpfn_from_mfn(mfn, pfn) do { } while (0)
+/* XXX only used for debug print right now... */
+#define get_gpfn_from_mfn(mfn) (mfn)
+
+static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gmfn)
+{
+ return pfn2mfn(d, gmfn, NULL);
+}
+
+#define mfn_to_gmfn(_d, mfn) (mfn)
+
#endif /* ! __ASSEMBLY__ */
#endif
diff -r a79b3252bbe4 -r b057b940f6eb xen/include/public/arch-powerpc.h
--- a/xen/include/public/arch-powerpc.h Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/include/public/arch-powerpc.h Tue Sep 12 12:08:04 2006 -0500
@@ -72,6 +72,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
#ifndef __ASSEMBLY__
+#define XENCOMM_INLINE_FLAG (1UL << 63)
+
typedef uint64_t xen_ulong_t;
/* User-accessible registers: need to be saved/restored for every nested Xen
diff -r a79b3252bbe4 -r b057b940f6eb xen/include/public/xencomm.h
--- a/xen/include/public/xencomm.h Fri Sep 08 12:37:27 2006 -0500
+++ b/xen/include/public/xencomm.h Tue Sep 12 12:08:04 2006 -0500
@@ -1,6 +1,4 @@
/*
- * Copyright (C) 2006 Hollis Blanchard <hollisb@xxxxxxxxxx>, 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
@@ -14,6 +12,10 @@
* 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>
*/
#ifndef _XEN_XENCOMM_H_
diff -r a79b3252bbe4 -r b057b940f6eb xen/common/xencomm.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/xencomm.c Tue Sep 12 12:08:04 2006 -0500
@@ -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@xxxxxxxxxx>
+ * Tristan Gingold <tristan.gingold@xxxxxxxx>
+ */
+
+#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 a79b3252bbe4 -r b057b940f6eb xen/include/xen/xencomm.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/xencomm.h Tue Sep 12 12:08:04 2006 -0500
@@ -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@xxxxxxxxxx>
+ */
+
+#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 a79b3252bbe4 -r b057b940f6eb xen/include/asm-powerpc/uaccess.h
--- a/xen/include/asm-powerpc/uaccess.h Fri Sep 08 12:37:27 2006 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * 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@xxxxxxxxxx>
- */
-
-#ifndef __PPC_UACCESS_H__
-#define __PPC_UACCESS_H__
-
-#include <xen/errno.h>
-#include <asm/page.h>
-#include <asm/guest_access.h>
-
-/* since we run in real mode, we can safely access all addresses.
- * XXX well, except IO. should we check for that here? */
-#define access_ok(addr,size) 1
-#define array_access_ok(addr,count,size) 1
-
-#define __copy_to_user copy_to_user
-#define __copy_from_user copy_from_user
-#define copy_to_user(to,from,len) xencomm_copy_to_guest(to,from,len,0)
-#define copy_from_user(to,from,len) xencomm_copy_from_guest(to,from,len,0)
-
-#endif /* __PPC_UACCESS_H__ */
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|