# HG changeset patch
# User [EMAIL PROTECTED]
# Date 1188280422 -32400
# Node ID ec6538af0ce5c0cee25d7a063c1d33df0f80a8d9
# Parent  fa5615e8bf84df1d5b4f9d87e95359692a65dbcb
[xen, xencomm] xencomm multiple page support
Current implementation doesn't allow struct xencomm_desc::address array
to be more than single page. On IA64 it causes 64GB+ domain creation
failure. This patch generalizes xencomm to allow multipage
xencomm_desc::address array.
PATCHNAME: xencomm_multiple_page

Signed-off-by: Isaku Yamahata <[EMAIL PROTECTED]>

diff -r fa5615e8bf84 -r ec6538af0ce5 xen/common/xencomm.c
--- a/xen/common/xencomm.c      Tue Aug 28 14:43:33 2007 +0900
+++ b/xen/common/xencomm.c      Tue Aug 28 14:53:42 2007 +0900
@@ -17,6 +17,7 @@
  *
  * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
  *          Tristan Gingold <[EMAIL PROTECTED]>
+ *          Isaku Yamahata <[EMAIL PROTECTED]> multiple page support
  */
 
 #include <xen/config.h>
@@ -82,10 +83,11 @@ xencomm_desc_cross_page_boundary(unsigne
 }
 
 struct xencomm_ctxt {
-    struct xencomm_desc *desc;
-
+    struct xencomm_desc __user *desc_in_paddr;
     uint32_t nr_addrs;
+
     struct page_info *page;
+    unsigned long *address;
 };
 
 static uint32_t
@@ -95,21 +97,9 @@ xencomm_ctxt_nr_addrs(const struct xenco
 }
 
 static unsigned long*
-xencomm_ctxt_address(struct xencomm_ctxt *ctxt, int i)
-{
-    return &ctxt->desc->address[i];
-}
-
-/* check if struct xencomm_desc and address array cross page boundary */
-static int
-xencomm_ctxt_cross_page_boundary(struct xencomm_ctxt *ctxt)
-{
-    unsigned long saddr = (unsigned long)ctxt->desc;
-    unsigned long eaddr =
-        (unsigned long)&ctxt->desc->address[ctxt->nr_addrs] - 1;
-    if ( (saddr >> PAGE_SHIFT) != (eaddr >> PAGE_SHIFT) )
-        return 1;
-    return 0;
+xencomm_ctxt_address(struct xencomm_ctxt *ctxt)
+{
+    return ctxt->address;
 }
 
 static int
@@ -138,16 +128,40 @@ xencomm_ctxt_init(const void* handle, st
         return -EINVAL;
     }
 
-    ctxt->desc = desc;
     ctxt->nr_addrs = desc->nr_addrs; /* copy before use.
                                       * It is possible for a guest domain to
                                       * modify concurrently.
                                       */
+    ctxt->desc_in_paddr = (struct xencomm_desc*)handle;
     ctxt->page = page;
-    if ( xencomm_ctxt_cross_page_boundary(ctxt) )
-    {
-        put_page(page);
-        return -EINVAL;
+    ctxt->address = &desc->address[0];
+    return 0;
+}
+
+static int
+xencomm_ctxt_next(struct xencomm_ctxt *ctxt, int i)
+{
+    BUG_ON(i >= ctxt->nr_addrs);
+    /* in i == 0 case, we already calculated in xecomm_addr_init() */
+    if ( i != 0 )
+        ctxt->address++;
+    
+    /* When crossing page boundary, machine address must be calculated. */
+    if ( ((unsigned long)ctxt->address & ~PAGE_MASK) == 0 )
+    {
+        unsigned long paddr =
+            (unsigned long)&(ctxt->desc_in_paddr->address[i]);
+        struct page_info *page;
+        int ret;
+
+        ret = xencomm_get_page(paddr, &page);
+        if ( ret == 0 )
+        {
+            put_page(ctxt->page);
+            ctxt->page = page;
+            ctxt->address = xencomm_vaddr(paddr, page);
+        }
+        return ret;
     }
     return 0;
 }
@@ -238,9 +252,12 @@ xencomm_copy_from_guest(
     /* Iterate through the descriptor, copying up to a page at a time */
     while ( (to_pos < n) && (i < xencomm_ctxt_nr_addrs(&ctxt)) )
     {
-        unsigned long src_paddr = *xencomm_ctxt_address(&ctxt, i);
+        unsigned long src_paddr;
         unsigned int pgoffset, chunksz, chunk_skip;
 
+        if ( xencomm_ctxt_next(&ctxt, i) )
+            goto out;
+        src_paddr = *xencomm_ctxt_address(&ctxt);
         if ( src_paddr == XENCOMM_INVALID )
         {
             i++;
@@ -354,9 +371,12 @@ xencomm_copy_to_guest(
     /* Iterate through the descriptor, copying up to a page at a time */
     while ( (from_pos < n) && (i < xencomm_ctxt_nr_addrs(&ctxt)) )
     {
-        unsigned long dest_paddr = *xencomm_ctxt_address(&ctxt, i);
+        unsigned long dest_paddr;
         unsigned int pgoffset, chunksz, chunk_skip;
 
+        if ( xencomm_ctxt_next(&ctxt, i) )
+            goto out;
+        dest_paddr = *xencomm_ctxt_address(&ctxt);
         if ( dest_paddr == XENCOMM_INVALID )
         {
             i++;
@@ -402,22 +422,27 @@ int xencomm_add_offset(void **handle, un
 {
     struct xencomm_ctxt ctxt;
     int i = 0;
+    int res = 0;
 
     if ( xencomm_is_inline(*handle) )
         return xencomm_inline_add_offset(handle, bytes);
 
-    if ( xencomm_ctxt_init(handle, &ctxt) )
-        return -1;
+    res = xencomm_ctxt_init(handle, &ctxt);
+    if ( res != 0 )
+        return res;
 
     /* Iterate through the descriptor incrementing addresses */
     while ( (bytes > 0) && (i < xencomm_ctxt_nr_addrs(&ctxt)) )
     {
-        unsigned long *address = xencomm_ctxt_address(&ctxt, i);
-        unsigned long dest_paddr = *address;
-        unsigned int pgoffset;
-        unsigned int chunksz;
-        unsigned int chunk_skip;
-
+        unsigned long *address;
+        unsigned long dest_paddr;
+        unsigned int pgoffset, chunksz, chunk_skip;
+
+        res = xencomm_ctxt_next(&ctxt, i);
+        if ( res )
+            goto out;
+        address = xencomm_ctxt_address(&ctxt);
+        dest_paddr = *address;
         if ( dest_paddr == XENCOMM_INVALID )
         {
             i++;
@@ -436,8 +461,10 @@ int xencomm_add_offset(void **handle, un
 
         i++;
     }
+
+out:
     xencomm_ctxt_done(&ctxt);
-    return 0;
+    return res;
 }
 
 int xencomm_handle_is_null(void *handle)
@@ -454,7 +481,9 @@ int xencomm_handle_is_null(void *handle)
 
     for ( i = 0; i < xencomm_ctxt_nr_addrs(&ctxt); i++ )
     {
-        if ( *xencomm_ctxt_address(&ctxt, i) != XENCOMM_INVALID )
+        if ( xencomm_ctxt_next(&ctxt, i) )
+            goto out;
+        if ( *xencomm_ctxt_address(&ctxt) != XENCOMM_INVALID )
         {
             res = 0;
             goto out;
# HG changeset patch
# User [EMAIL PROTECTED]
# Date 1188280422 -32400
# Node ID ec6538af0ce5c0cee25d7a063c1d33df0f80a8d9
# Parent  fa5615e8bf84df1d5b4f9d87e95359692a65dbcb
[xen, xencomm] xencomm multiple page support
Current implementation doesn't allow struct xencomm_desc::address array
to be more than single page. On IA64 it causes 64GB+ domain creation
failure. This patch generalizes xencomm to allow multipage
xencomm_desc::address array.
PATCHNAME: xencomm_multiple_page

Signed-off-by: Isaku Yamahata <[EMAIL PROTECTED]>

diff -r fa5615e8bf84 -r ec6538af0ce5 xen/common/xencomm.c
--- a/xen/common/xencomm.c	Tue Aug 28 14:43:33 2007 +0900
+++ b/xen/common/xencomm.c	Tue Aug 28 14:53:42 2007 +0900
@@ -17,6 +17,7 @@
  *
  * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
  *          Tristan Gingold <[EMAIL PROTECTED]>
+ *          Isaku Yamahata <[EMAIL PROTECTED]> multiple page support
  */
 
 #include <xen/config.h>
@@ -82,10 +83,11 @@ xencomm_desc_cross_page_boundary(unsigne
 }
 
 struct xencomm_ctxt {
-    struct xencomm_desc *desc;
-
+    struct xencomm_desc __user *desc_in_paddr;
     uint32_t nr_addrs;
+
     struct page_info *page;
+    unsigned long *address;
 };
 
 static uint32_t
@@ -95,21 +97,9 @@ xencomm_ctxt_nr_addrs(const struct xenco
 }
 
 static unsigned long*
-xencomm_ctxt_address(struct xencomm_ctxt *ctxt, int i)
-{
-    return &ctxt->desc->address[i];
-}
-
-/* check if struct xencomm_desc and address array cross page boundary */
-static int
-xencomm_ctxt_cross_page_boundary(struct xencomm_ctxt *ctxt)
-{
-    unsigned long saddr = (unsigned long)ctxt->desc;
-    unsigned long eaddr =
-        (unsigned long)&ctxt->desc->address[ctxt->nr_addrs] - 1;
-    if ( (saddr >> PAGE_SHIFT) != (eaddr >> PAGE_SHIFT) )
-        return 1;
-    return 0;
+xencomm_ctxt_address(struct xencomm_ctxt *ctxt)
+{
+    return ctxt->address;
 }
 
 static int
@@ -138,16 +128,40 @@ xencomm_ctxt_init(const void* handle, st
         return -EINVAL;
     }
 
-    ctxt->desc = desc;
     ctxt->nr_addrs = desc->nr_addrs; /* copy before use.
                                       * It is possible for a guest domain to
                                       * modify concurrently.
                                       */
+    ctxt->desc_in_paddr = (struct xencomm_desc*)handle;
     ctxt->page = page;
-    if ( xencomm_ctxt_cross_page_boundary(ctxt) )
-    {
-        put_page(page);
-        return -EINVAL;
+    ctxt->address = &desc->address[0];
+    return 0;
+}
+
+static int
+xencomm_ctxt_next(struct xencomm_ctxt *ctxt, int i)
+{
+    BUG_ON(i >= ctxt->nr_addrs);
+    /* in i == 0 case, we already calculated in xecomm_addr_init() */
+    if ( i != 0 )
+        ctxt->address++;
+    
+    /* When crossing page boundary, machine address must be calculated. */
+    if ( ((unsigned long)ctxt->address & ~PAGE_MASK) == 0 )
+    {
+        unsigned long paddr =
+            (unsigned long)&(ctxt->desc_in_paddr->address[i]);
+        struct page_info *page;
+        int ret;
+
+        ret = xencomm_get_page(paddr, &page);
+        if ( ret == 0 )
+        {
+            put_page(ctxt->page);
+            ctxt->page = page;
+            ctxt->address = xencomm_vaddr(paddr, page);
+        }
+        return ret;
     }
     return 0;
 }
@@ -238,9 +252,12 @@ xencomm_copy_from_guest(
     /* Iterate through the descriptor, copying up to a page at a time */
     while ( (to_pos < n) && (i < xencomm_ctxt_nr_addrs(&ctxt)) )
     {
-        unsigned long src_paddr = *xencomm_ctxt_address(&ctxt, i);
+        unsigned long src_paddr;
         unsigned int pgoffset, chunksz, chunk_skip;
 
+        if ( xencomm_ctxt_next(&ctxt, i) )
+            goto out;
+        src_paddr = *xencomm_ctxt_address(&ctxt);
         if ( src_paddr == XENCOMM_INVALID )
         {
             i++;
@@ -354,9 +371,12 @@ xencomm_copy_to_guest(
     /* Iterate through the descriptor, copying up to a page at a time */
     while ( (from_pos < n) && (i < xencomm_ctxt_nr_addrs(&ctxt)) )
     {
-        unsigned long dest_paddr = *xencomm_ctxt_address(&ctxt, i);
+        unsigned long dest_paddr;
         unsigned int pgoffset, chunksz, chunk_skip;
 
+        if ( xencomm_ctxt_next(&ctxt, i) )
+            goto out;
+        dest_paddr = *xencomm_ctxt_address(&ctxt);
         if ( dest_paddr == XENCOMM_INVALID )
         {
             i++;
@@ -402,22 +422,27 @@ int xencomm_add_offset(void **handle, un
 {
     struct xencomm_ctxt ctxt;
     int i = 0;
+    int res = 0;
 
     if ( xencomm_is_inline(*handle) )
         return xencomm_inline_add_offset(handle, bytes);
 
-    if ( xencomm_ctxt_init(handle, &ctxt) )
-        return -1;
+    res = xencomm_ctxt_init(handle, &ctxt);
+    if ( res != 0 )
+        return res;
 
     /* Iterate through the descriptor incrementing addresses */
     while ( (bytes > 0) && (i < xencomm_ctxt_nr_addrs(&ctxt)) )
     {
-        unsigned long *address = xencomm_ctxt_address(&ctxt, i);
-        unsigned long dest_paddr = *address;
-        unsigned int pgoffset;
-        unsigned int chunksz;
-        unsigned int chunk_skip;
-
+        unsigned long *address;
+        unsigned long dest_paddr;
+        unsigned int pgoffset, chunksz, chunk_skip;
+
+        res = xencomm_ctxt_next(&ctxt, i);
+        if ( res )
+            goto out;
+        address = xencomm_ctxt_address(&ctxt);
+        dest_paddr = *address;
         if ( dest_paddr == XENCOMM_INVALID )
         {
             i++;
@@ -436,8 +461,10 @@ int xencomm_add_offset(void **handle, un
 
         i++;
     }
+
+out:
     xencomm_ctxt_done(&ctxt);
-    return 0;
+    return res;
 }
 
 int xencomm_handle_is_null(void *handle)
@@ -454,7 +481,9 @@ int xencomm_handle_is_null(void *handle)
 
     for ( i = 0; i < xencomm_ctxt_nr_addrs(&ctxt); i++ )
     {
-        if ( *xencomm_ctxt_address(&ctxt, i) != XENCOMM_INVALID )
+        if ( xencomm_ctxt_next(&ctxt, i) )
+            goto out;
+        if ( *xencomm_ctxt_address(&ctxt) != XENCOMM_INVALID )
         {
             res = 0;
             goto out;
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to