ia64/xen-unstable
changeset 15783:c93e2a822d6f
[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
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
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
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author | kfraser@localhost.localdomain |
---|---|
date | Tue Aug 28 15:32:27 2007 +0100 (2007-08-28) |
parents | b1c3b9df7d9a |
children | f4a0804d18f9 |
files | xen/common/xencomm.c |
line diff
1.1 --- a/xen/common/xencomm.c Tue Aug 28 15:31:56 2007 +0100 1.2 +++ b/xen/common/xencomm.c Tue Aug 28 15:32:27 2007 +0100 1.3 @@ -17,6 +17,7 @@ 1.4 * 1.5 * Authors: Hollis Blanchard <hollisb@us.ibm.com> 1.6 * Tristan Gingold <tristan.gingold@bull.net> 1.7 + * Isaku Yamahata <yamahata@valinux.co.jp> multiple page support 1.8 */ 1.9 1.10 #include <xen/config.h> 1.11 @@ -82,10 +83,11 @@ xencomm_desc_cross_page_boundary(unsigne 1.12 } 1.13 1.14 struct xencomm_ctxt { 1.15 - struct xencomm_desc *desc; 1.16 + struct xencomm_desc __user *desc_in_paddr; 1.17 + uint32_t nr_addrs; 1.18 1.19 - uint32_t nr_addrs; 1.20 struct page_info *page; 1.21 + unsigned long *address; 1.22 }; 1.23 1.24 static uint32_t 1.25 @@ -95,21 +97,9 @@ xencomm_ctxt_nr_addrs(const struct xenco 1.26 } 1.27 1.28 static unsigned long* 1.29 -xencomm_ctxt_address(struct xencomm_ctxt *ctxt, int i) 1.30 +xencomm_ctxt_address(struct xencomm_ctxt *ctxt) 1.31 { 1.32 - return &ctxt->desc->address[i]; 1.33 -} 1.34 - 1.35 -/* check if struct xencomm_desc and address array cross page boundary */ 1.36 -static int 1.37 -xencomm_ctxt_cross_page_boundary(struct xencomm_ctxt *ctxt) 1.38 -{ 1.39 - unsigned long saddr = (unsigned long)ctxt->desc; 1.40 - unsigned long eaddr = 1.41 - (unsigned long)&ctxt->desc->address[ctxt->nr_addrs] - 1; 1.42 - if ( (saddr >> PAGE_SHIFT) != (eaddr >> PAGE_SHIFT) ) 1.43 - return 1; 1.44 - return 0; 1.45 + return ctxt->address; 1.46 } 1.47 1.48 static int 1.49 @@ -138,16 +128,40 @@ xencomm_ctxt_init(const void* handle, st 1.50 return -EINVAL; 1.51 } 1.52 1.53 - ctxt->desc = desc; 1.54 ctxt->nr_addrs = desc->nr_addrs; /* copy before use. 1.55 * It is possible for a guest domain to 1.56 * modify concurrently. 1.57 */ 1.58 + ctxt->desc_in_paddr = (struct xencomm_desc*)handle; 1.59 ctxt->page = page; 1.60 - if ( xencomm_ctxt_cross_page_boundary(ctxt) ) 1.61 + ctxt->address = &desc->address[0]; 1.62 + return 0; 1.63 +} 1.64 + 1.65 +static int 1.66 +xencomm_ctxt_next(struct xencomm_ctxt *ctxt, int i) 1.67 +{ 1.68 + BUG_ON(i >= ctxt->nr_addrs); 1.69 + /* in i == 0 case, we already calculated in xecomm_addr_init() */ 1.70 + if ( i != 0 ) 1.71 + ctxt->address++; 1.72 + 1.73 + /* When crossing page boundary, machine address must be calculated. */ 1.74 + if ( ((unsigned long)ctxt->address & ~PAGE_MASK) == 0 ) 1.75 { 1.76 - put_page(page); 1.77 - return -EINVAL; 1.78 + unsigned long paddr = 1.79 + (unsigned long)&(ctxt->desc_in_paddr->address[i]); 1.80 + struct page_info *page; 1.81 + int ret; 1.82 + 1.83 + ret = xencomm_get_page(paddr, &page); 1.84 + if ( ret == 0 ) 1.85 + { 1.86 + put_page(ctxt->page); 1.87 + ctxt->page = page; 1.88 + ctxt->address = xencomm_vaddr(paddr, page); 1.89 + } 1.90 + return ret; 1.91 } 1.92 return 0; 1.93 } 1.94 @@ -238,9 +252,12 @@ xencomm_copy_from_guest( 1.95 /* Iterate through the descriptor, copying up to a page at a time */ 1.96 while ( (to_pos < n) && (i < xencomm_ctxt_nr_addrs(&ctxt)) ) 1.97 { 1.98 - unsigned long src_paddr = *xencomm_ctxt_address(&ctxt, i); 1.99 + unsigned long src_paddr; 1.100 unsigned int pgoffset, chunksz, chunk_skip; 1.101 1.102 + if ( xencomm_ctxt_next(&ctxt, i) ) 1.103 + goto out; 1.104 + src_paddr = *xencomm_ctxt_address(&ctxt); 1.105 if ( src_paddr == XENCOMM_INVALID ) 1.106 { 1.107 i++; 1.108 @@ -354,9 +371,12 @@ xencomm_copy_to_guest( 1.109 /* Iterate through the descriptor, copying up to a page at a time */ 1.110 while ( (from_pos < n) && (i < xencomm_ctxt_nr_addrs(&ctxt)) ) 1.111 { 1.112 - unsigned long dest_paddr = *xencomm_ctxt_address(&ctxt, i); 1.113 + unsigned long dest_paddr; 1.114 unsigned int pgoffset, chunksz, chunk_skip; 1.115 1.116 + if ( xencomm_ctxt_next(&ctxt, i) ) 1.117 + goto out; 1.118 + dest_paddr = *xencomm_ctxt_address(&ctxt); 1.119 if ( dest_paddr == XENCOMM_INVALID ) 1.120 { 1.121 i++; 1.122 @@ -402,22 +422,27 @@ int xencomm_add_offset(void **handle, un 1.123 { 1.124 struct xencomm_ctxt ctxt; 1.125 int i = 0; 1.126 + int res = 0; 1.127 1.128 if ( xencomm_is_inline(*handle) ) 1.129 return xencomm_inline_add_offset(handle, bytes); 1.130 1.131 - if ( xencomm_ctxt_init(handle, &ctxt) ) 1.132 - return -1; 1.133 + res = xencomm_ctxt_init(handle, &ctxt); 1.134 + if ( res != 0 ) 1.135 + return res; 1.136 1.137 /* Iterate through the descriptor incrementing addresses */ 1.138 while ( (bytes > 0) && (i < xencomm_ctxt_nr_addrs(&ctxt)) ) 1.139 { 1.140 - unsigned long *address = xencomm_ctxt_address(&ctxt, i); 1.141 - unsigned long dest_paddr = *address; 1.142 - unsigned int pgoffset; 1.143 - unsigned int chunksz; 1.144 - unsigned int chunk_skip; 1.145 + unsigned long *address; 1.146 + unsigned long dest_paddr; 1.147 + unsigned int pgoffset, chunksz, chunk_skip; 1.148 1.149 + res = xencomm_ctxt_next(&ctxt, i); 1.150 + if ( res ) 1.151 + goto out; 1.152 + address = xencomm_ctxt_address(&ctxt); 1.153 + dest_paddr = *address; 1.154 if ( dest_paddr == XENCOMM_INVALID ) 1.155 { 1.156 i++; 1.157 @@ -436,8 +461,10 @@ int xencomm_add_offset(void **handle, un 1.158 1.159 i++; 1.160 } 1.161 + 1.162 +out: 1.163 xencomm_ctxt_done(&ctxt); 1.164 - return 0; 1.165 + return res; 1.166 } 1.167 1.168 int xencomm_handle_is_null(void *handle) 1.169 @@ -454,7 +481,9 @@ int xencomm_handle_is_null(void *handle) 1.170 1.171 for ( i = 0; i < xencomm_ctxt_nr_addrs(&ctxt); i++ ) 1.172 { 1.173 - if ( *xencomm_ctxt_address(&ctxt, i) != XENCOMM_INVALID ) 1.174 + if ( xencomm_ctxt_next(&ctxt, i) ) 1.175 + goto out; 1.176 + if ( *xencomm_ctxt_address(&ctxt) != XENCOMM_INVALID ) 1.177 { 1.178 res = 0; 1.179 goto out;