# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1185948714 -32400 # Node ID c4d697f2367e389f3a2f1b6866ae971206198efc # Parent 039f2ccb1e383a52eb44ba3ed80859548932b95e remove xencomm page size limit. Currently xencomm has page size limit so that a domain with many memory (e.g. 100GB+) can't be created. This patch allows that the address array of struct xencomm_desc to cross page boundary so that the size of struct xencomm_desc can exceed page size. Note that struct xencomm_desc itself can't page boundary. PATCHNAME: remove_xencomm_page_size_limit_xen_side Signed-off-by: Isaku Yamahata diff -r 039f2ccb1e38 -r c4d697f2367e xen/arch/ia64/xen/xencomm.c --- a/xen/arch/ia64/xen/xencomm.c Tue Jul 31 10:30:40 2007 -0600 +++ b/xen/arch/ia64/xen/xencomm.c Wed Aug 01 15:11:54 2007 +0900 @@ -34,6 +34,15 @@ static int xencomm_debug = 1; /* extreme #else #define xencomm_debug 0 #endif + +static int +xencomm_desc_cross_page_boundary(unsigned long paddr) +{ + unsigned long offset = paddr & ~PAGE_MASK; + if (offset > PAGE_SIZE - sizeof(struct xencomm_desc)) + return 1; + return 0; +} static int xencomm_copy_chunk_from( @@ -87,6 +96,8 @@ xencomm_copy_from_guest( { struct xencomm_desc *desc; unsigned long desc_addr; + struct xencomm_desc *desc_paddr; + unsigned long *address; unsigned int from_pos = 0; unsigned int to_pos = 0; unsigned int i = 0; @@ -121,6 +132,9 @@ xencomm_copy_from_guest( return 0; } + /* check if struct desc doesn't cross page boundry */ + if (xencomm_desc_cross_page_boundary((unsigned long)from)) + return -EINVAL; /* first we need to access the descriptor */ desc_addr = xencomm_paddr_to_maddr((unsigned long)from); if (desc_addr == 0) @@ -132,18 +146,26 @@ xencomm_copy_from_guest( __func__, desc, desc->magic); return -EFAULT; } + desc_paddr = (struct xencomm_desc *)from; + address = &desc->address[i]; /* 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 long src_paddr; unsigned int pgoffset; unsigned int chunksz; unsigned int chunk_skip; - if (src_paddr == XENCOMM_INVALID) { - i++; - continue; - } + /* When crossing page boundary, machine address must be calculated. */ + if (((unsigned long)address & ~PAGE_MASK) == 0) { + address = (unsigned long*)xencomm_paddr_to_maddr( + (unsigned long)&desc_paddr->address[i]); + if (address == NULL) + return -EFAULT; + } + src_paddr = *address; + if (src_paddr == XENCOMM_INVALID) + goto skip_to_next; pgoffset = src_paddr % PAGE_SIZE; chunksz = PAGE_SIZE - pgoffset; @@ -170,7 +192,9 @@ xencomm_copy_from_guest( to_pos += bytes; } + skip_to_next: i++; + address++; } return n - to_pos; @@ -228,6 +252,8 @@ xencomm_copy_to_guest( { struct xencomm_desc *desc; unsigned long desc_addr; + struct xencomm_desc *desc_paddr; + unsigned long *address; unsigned int from_pos = 0; unsigned int to_pos = 0; unsigned int i = 0; @@ -263,6 +289,9 @@ xencomm_copy_to_guest( return 0; } + /* check if struct desc doesn't cross page boundry */ + if (xencomm_desc_cross_page_boundary((unsigned long)to)) + return -EINVAL; /* first we need to access the descriptor */ desc_addr = xencomm_paddr_to_maddr((unsigned long)to); if (desc_addr == 0) @@ -273,18 +302,26 @@ xencomm_copy_to_guest( printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic); return -EFAULT; } + desc_paddr = (struct xencomm_desc*)to; + address = &desc->address[i]; /* 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 long dest_paddr; unsigned int pgoffset; unsigned int chunksz; unsigned int chunk_skip; - if (dest_paddr == XENCOMM_INVALID) { - i++; - continue; - } + /* When crossing page boundary, machine address must be calculated. */ + if (((unsigned long)address & ~PAGE_MASK) == 0) { + address = (unsigned long*)xencomm_paddr_to_maddr( + (unsigned long)&desc_paddr->address[i]); + if (address == NULL) + return -EFAULT; + } + dest_paddr = *address; + if (dest_paddr == XENCOMM_INVALID) + goto skip_to_next; pgoffset = dest_paddr % PAGE_SIZE; chunksz = PAGE_SIZE - pgoffset; @@ -308,7 +345,9 @@ xencomm_copy_to_guest( to_pos += bytes; } + skip_to_next: i++; + address++; } return n - from_pos; } @@ -322,11 +361,16 @@ xencomm_add_offset( { struct xencomm_desc *desc; unsigned long desc_addr; + struct xencomm_desc *desc_paddr; + unsigned long *address; int i = 0; if (XENCOMM_IS_INLINE(handle)) return (void *)((unsigned long)handle + bytes); + /* check if struct desc doesn't cross page boundry */ + if (xencomm_desc_cross_page_boundary((unsigned long)handle)) + return NULL; /* first we need to access the descriptor */ desc_addr = xencomm_paddr_to_maddr((unsigned long)handle); if (desc_addr == 0) @@ -337,18 +381,26 @@ xencomm_add_offset( printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic); return NULL; } + desc_paddr = (struct xencomm_desc*)handle; + address = &desc->address[i]; /* iterate through the descriptor incrementing addresses */ while ((bytes > 0) && (i < desc->nr_addrs)) { - unsigned long dest_paddr = desc->address[i]; + unsigned long dest_paddr; unsigned int pgoffset; unsigned int chunksz; unsigned int chunk_skip; - if (dest_paddr == XENCOMM_INVALID) { - i++; - continue; - } + /* When crossing page boundary, machine address must be calculated. */ + if (((unsigned long)address & ~PAGE_MASK) == 0) { + address = (unsigned long*)xencomm_paddr_to_maddr( + (unsigned long)&desc_paddr->address[i]); + if (address == NULL) + return NULL; + } + dest_paddr = *address; + if (dest_paddr == XENCOMM_INVALID) + goto skip_to_next; pgoffset = dest_paddr % PAGE_SIZE; chunksz = PAGE_SIZE - pgoffset; @@ -356,13 +408,15 @@ xencomm_add_offset( chunk_skip = min(chunksz, bytes); if (chunk_skip == chunksz) { /* exhausted this page */ - desc->address[i] = XENCOMM_INVALID; + *address = XENCOMM_INVALID; } else { - desc->address[i] += chunk_skip; + *address += chunk_skip; } bytes -= chunk_skip; - - i++; + + skip_to_next: + i++; + address++; } return handle; }