debuggers.hg
changeset 3275:a193790c4961
bitkeeper revision 1.1159.203.1 (41af4018fV44p80Jw5YxFLlk5sh8jg)
Cleaned balloon driver internals. Better integration with device
drivers that also inc/dec memory reservation. Should be more
informative (cat /proc/xen/balloon) and more stable. Needs testing
with Linux 2.4...
Cleaned balloon driver internals. Better integration with device
drivers that also inc/dec memory reservation. Should be more
informative (cat /proc/xen/balloon) and more stable. Needs testing
with Linux 2.4...
line diff
1.1 --- a/.rootkeys Thu Dec 02 09:21:31 2004 +0000 1.2 +++ b/.rootkeys Thu Dec 02 16:17:28 2004 +0000 1.3 @@ -237,6 +237,7 @@ 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6 1.4 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/tlbflush.h 1.5 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/vga.h 1.6 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/xor.h 1.7 +41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.9-xen-sparse/include/asm-xen/balloon.h 1.8 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.9-xen-sparse/include/asm-xen/ctrl_if.h 1.9 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h 1.10 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.9-xen-sparse/include/asm-xen/foreign_page.h
2.1 --- a/linux-2.4.28-xen-sparse/mkbuildtree Thu Dec 02 09:21:31 2004 +0000 2.2 +++ b/linux-2.4.28-xen-sparse/mkbuildtree Thu Dec 02 16:17:28 2004 +0000 2.3 @@ -204,6 +204,7 @@ ln -sf ../asm-i386/unaligned.h 2.4 ln -sf ../asm-i386/unistd.h 2.5 ln -sf ../asm-i386/user.h 2.6 ln -sf ../asm-i386/vm86.h 2.7 +ln -sf ../../${LINUX_26}/include/asm-xen/balloon.h 2.8 ln -sf ../../${LINUX_26}/include/asm-xen/ctrl_if.h 2.9 ln -sf ../../${LINUX_26}/include/asm-xen/evtchn.h 2.10 ln -sf ../../${LINUX_26}/include/asm-xen/gnttab.h
3.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c Thu Dec 02 09:21:31 2004 +0000 3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c Thu Dec 02 16:17:28 2004 +0000 3.3 @@ -13,6 +13,7 @@ 3.4 #include <linux/pci.h> 3.5 #include <linux/version.h> 3.6 #include <asm/io.h> 3.7 +#include <asm-xen/balloon.h> 3.8 3.9 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) 3.10 #define pte_offset_kernel pte_offset 3.11 @@ -37,9 +38,12 @@ xen_contig_memory(unsigned long vstart, 3.12 pgd_t *pgd; 3.13 pmd_t *pmd; 3.14 pte_t *pte; 3.15 - unsigned long pfn, i; 3.16 + unsigned long pfn, i, flags; 3.17 3.18 scrub_pages(vstart, 1 << order); 3.19 + 3.20 + balloon_lock(flags); 3.21 + 3.22 /* 1. Zap current PTEs, giving away the underlying pages. */ 3.23 for (i = 0; i < (1<<order); i++) { 3.24 pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE))); 3.25 @@ -70,6 +74,8 @@ xen_contig_memory(unsigned long vstart, 3.26 } 3.27 /* Flush updates through and flush the TLB. */ 3.28 xen_tlb_flush(); 3.29 + 3.30 + balloon_unlock(flags); 3.31 } 3.32 3.33 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
4.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c Thu Dec 02 09:21:31 2004 +0000 4.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c Thu Dec 02 16:17:28 2004 +0000 4.3 @@ -35,6 +35,7 @@ 4.4 #include <asm/pgtable.h> 4.5 #include <asm-xen/hypervisor.h> 4.6 #include <asm-xen/multicall.h> 4.7 +#include <asm-xen/balloon.h> 4.8 4.9 /* 4.10 * This suffices to protect us if we ever move to SMP domains. 4.11 @@ -352,7 +353,6 @@ unsigned long allocate_empty_lowmem_regi 4.12 unsigned long *pfn_array; 4.13 unsigned long vstart; 4.14 unsigned long i; 4.15 - int ret; 4.16 unsigned int order = get_order(pages*PAGE_SIZE); 4.17 4.18 vstart = __get_free_pages(GFP_KERNEL, order); 4.19 @@ -378,57 +378,11 @@ unsigned long allocate_empty_lowmem_regi 4.20 /* Flush updates through and flush the TLB. */ 4.21 xen_tlb_flush(); 4.22 4.23 - ret = HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 4.24 - pfn_array, 1<<order, 0); 4.25 - if ( unlikely(ret != (1<<order)) ) 4.26 - { 4.27 - printk(KERN_WARNING "Unable to reduce memory reservation (%d)\n", ret); 4.28 - BUG(); 4.29 - } 4.30 + balloon_put_pages(pfn_array, 1 << order); 4.31 4.32 vfree(pfn_array); 4.33 4.34 return vstart; 4.35 } 4.36 4.37 -void deallocate_lowmem_region(unsigned long vstart, unsigned long pages) 4.38 -{ 4.39 - pgd_t *pgd; 4.40 - pmd_t *pmd; 4.41 - pte_t *pte; 4.42 - unsigned long *pfn_array; 4.43 - unsigned long i; 4.44 - int ret; 4.45 - unsigned int order = get_order(pages*PAGE_SIZE); 4.46 - 4.47 - pfn_array = vmalloc((1<<order) * sizeof(*pfn_array)); 4.48 - if ( pfn_array == NULL ) 4.49 - BUG(); 4.50 - 4.51 - ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, 4.52 - pfn_array, 1<<order, 0); 4.53 - if ( unlikely(ret != (1<<order)) ) 4.54 - { 4.55 - printk(KERN_WARNING "Unable to increase memory reservation (%d)\n", 4.56 - ret); 4.57 - BUG(); 4.58 - } 4.59 - 4.60 - for ( i = 0; i < (1<<order); i++ ) 4.61 - { 4.62 - pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE))); 4.63 - pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE))); 4.64 - pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); 4.65 - queue_l1_entry_update(pte, (pfn_array[i]<<PAGE_SHIFT)|__PAGE_KERNEL); 4.66 - queue_machphys_update(pfn_array[i], __pa(vstart)>>PAGE_SHIFT); 4.67 - phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = pfn_array[i]; 4.68 - } 4.69 - 4.70 - flush_page_update_queue(); 4.71 - 4.72 - vfree(pfn_array); 4.73 - 4.74 - free_pages(vstart, order); 4.75 -} 4.76 - 4.77 #endif /* CONFIG_XEN_PHYSDEV_ACCESS */
5.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/Makefile Thu Dec 02 09:21:31 2004 +0000 5.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile Thu Dec 02 16:17:28 2004 +0000 5.3 @@ -2,9 +2,9 @@ 5.4 5.5 obj-y += console/ 5.6 obj-y += evtchn/ 5.7 -obj-y += privcmd/ 5.8 -obj-y += balloon/ 5.9 +obj-y += balloon/ 5.10 5.11 +obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += privcmd/ 5.12 obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/ 5.13 obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ 5.14 obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/
6.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c Thu Dec 02 09:21:31 2004 +0000 6.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c Thu Dec 02 16:17:28 2004 +0000 6.3 @@ -29,8 +29,8 @@ 6.4 */ 6.5 6.6 #include <linux/config.h> 6.7 +#include <linux/kernel.h> 6.8 #include <linux/module.h> 6.9 -#include <linux/kernel.h> 6.10 #include <linux/sched.h> 6.11 #include <linux/errno.h> 6.12 #include <linux/mm.h> 6.13 @@ -43,16 +43,41 @@ 6.14 #include <asm-xen/xen_proc.h> 6.15 #include <asm-xen/hypervisor.h> 6.16 #include <asm-xen/ctrl_if.h> 6.17 +#include <asm-xen/balloon.h> 6.18 #include <asm/pgalloc.h> 6.19 #include <asm/pgtable.h> 6.20 #include <asm/uaccess.h> 6.21 #include <asm/tlb.h> 6.22 #include <linux/list.h> 6.23 6.24 +#define MIN_TARGET ((16 << 20) >> PAGE_SHIFT) /* 16MB */ 6.25 + 6.26 static struct proc_dir_entry *balloon_pde; 6.27 6.28 -unsigned long credit; 6.29 +static DECLARE_MUTEX(balloon_mutex); 6.30 +spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED; 6.31 + 6.32 +/* We aim for 'current allocation' == 'target allocation'. */ 6.33 static unsigned long current_pages; 6.34 +static unsigned long target_pages; 6.35 + 6.36 +/* We may hit the hard limit in Xen. If we do then we remember it. */ 6.37 +static unsigned long hard_limit; 6.38 + 6.39 +/* 6.40 + * Drivers may alter the memory reservation independently, but they must 6.41 + * inform the balloon driver so that we can avoid hitting the hard limit. 6.42 + */ 6.43 +static unsigned long driver_pages; 6.44 + 6.45 +/* List of ballooned pages, threaded through the mem_map array. */ 6.46 +static LIST_HEAD(ballooned_pages); 6.47 +static unsigned long balloon_low, balloon_high; 6.48 + 6.49 +/* Main work function, always executed in process context. */ 6.50 +static void balloon_process(void *unused); 6.51 +static DECLARE_WORK(balloon_worker, balloon_process, NULL); 6.52 +static struct timer_list balloon_timer; 6.53 6.54 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 6.55 /* Use the private and mapping fields of struct page as a list. */ 6.56 @@ -75,17 +100,24 @@ static unsigned long current_pages; 6.57 #define WPRINTK(fmt, args...) \ 6.58 printk(KERN_WARNING "xen_mem: " fmt, ##args) 6.59 6.60 -/* List of ballooned pages, threaded through the mem_map array. */ 6.61 -LIST_HEAD(ballooned_pages); 6.62 - 6.63 /* balloon_append: add the given page to the balloon. */ 6.64 -void balloon_append(struct page *page) 6.65 +static void balloon_append(struct page *page) 6.66 { 6.67 - list_add(PAGE_TO_LIST(page), &ballooned_pages); 6.68 + /* Low memory is re-populated first, so highmem pages go at list tail. */ 6.69 + if ( PageHighMem(page) ) 6.70 + { 6.71 + list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); 6.72 + balloon_high++; 6.73 + } 6.74 + else 6.75 + { 6.76 + list_add(PAGE_TO_LIST(page), &ballooned_pages); 6.77 + balloon_low++; 6.78 + } 6.79 } 6.80 6.81 /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ 6.82 -struct page *balloon_retrieve(void) 6.83 +static struct page *balloon_retrieve(void) 6.84 { 6.85 struct page *page; 6.86 6.87 @@ -94,6 +126,12 @@ struct page *balloon_retrieve(void) 6.88 6.89 page = LIST_TO_PAGE(ballooned_pages.next); 6.90 UNLIST_PAGE(page); 6.91 + 6.92 + if ( PageHighMem(page) ) 6.93 + balloon_high--; 6.94 + else 6.95 + balloon_low--; 6.96 + 6.97 return page; 6.98 } 6.99 6.100 @@ -111,194 +149,148 @@ static inline pte_t *get_ptep(unsigned l 6.101 return pte_offset_kernel(pmd, addr); 6.102 } 6.103 6.104 -/* Main function for relinquishing memory. */ 6.105 -static unsigned long inflate_balloon(unsigned long num_pages) 6.106 +static void balloon_alarm(unsigned long unused) 6.107 { 6.108 - unsigned long *parray, *currp, curraddr, ret = 0, i, j, mfn, pfn; 6.109 - struct page *page; 6.110 - 6.111 - parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long)); 6.112 - if ( parray == NULL ) 6.113 - { 6.114 - WPRINTK("inflate_balloon: Unable to vmalloc parray\n"); 6.115 - return -ENOMEM; 6.116 - } 6.117 - 6.118 - currp = parray; 6.119 - 6.120 - for ( i = 0; i < num_pages; i++, currp++ ) 6.121 - { 6.122 - page = alloc_page(GFP_HIGHUSER); 6.123 - pfn = page - mem_map; 6.124 - 6.125 - /* If allocation fails then free all reserved pages. */ 6.126 - if ( page == NULL ) 6.127 - { 6.128 - printk(KERN_ERR "Unable to inflate balloon by %ld, only" 6.129 - " %ld pages free.", num_pages, i); 6.130 - currp = parray; 6.131 - for ( j = 0; j < i; j++, currp++ ) 6.132 - __free_page((struct page *) (mem_map + *currp)); 6.133 - 6.134 - ret = -EFAULT; 6.135 - goto cleanup; 6.136 - } 6.137 - 6.138 - *currp = pfn; 6.139 - } 6.140 + schedule_work(&balloon_worker); 6.141 +} 6.142 6.143 - for ( i = 0, currp = parray; i < num_pages; i++, currp++ ) 6.144 - { 6.145 - mfn = phys_to_machine_mapping[*currp]; 6.146 - curraddr = (unsigned long)page_address(mem_map + *currp); 6.147 - /* Blow away page contents for security, and also p.t. ref if any. */ 6.148 - if ( curraddr != 0 ) 6.149 - { 6.150 - scrub_pages(curraddr, 1); 6.151 - queue_l1_entry_update(get_ptep(curraddr), 0); 6.152 - } 6.153 -#ifdef CONFIG_XEN_SCRUB_PAGES 6.154 - else 6.155 - { 6.156 - void *p = kmap(&mem_map[*currp]); 6.157 - scrub_pages(p, 1); 6.158 - kunmap(&mem_map[*currp]); 6.159 - } 6.160 -#endif 6.161 - 6.162 - balloon_append(&mem_map[*currp]); 6.163 - 6.164 - phys_to_machine_mapping[*currp] = INVALID_P2M_ENTRY; 6.165 - *currp = mfn; 6.166 - } 6.167 - 6.168 - /* Flush updates through and flush the TLB. */ 6.169 - xen_tlb_flush(); 6.170 - 6.171 - ret = HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 6.172 - parray, num_pages, 0); 6.173 - if ( unlikely(ret != num_pages) ) 6.174 - { 6.175 - printk(KERN_ERR "Unable to inflate balloon, error %lx\n", ret); 6.176 - goto cleanup; 6.177 - } 6.178 - 6.179 - credit += num_pages; 6.180 - ret = num_pages; 6.181 - 6.182 - cleanup: 6.183 - vfree(parray); 6.184 - 6.185 - return ret; 6.186 +static unsigned long current_target(void) 6.187 +{ 6.188 + unsigned long target = min(target_pages, hard_limit); 6.189 + if ( target > (current_pages + balloon_low + balloon_high) ) 6.190 + target = current_pages + balloon_low + balloon_high; 6.191 + if ( target < MIN_TARGET ) 6.192 + target = MIN_TARGET; 6.193 + return target; 6.194 } 6.195 6.196 -/* Install a set of new pages (@mfn_list, @nr_mfns) into the memory map. */ 6.197 -static unsigned long process_returned_pages( 6.198 - unsigned long *mfn_list, unsigned long nr_mfns) 6.199 +static void balloon_process(void *unused) 6.200 { 6.201 - unsigned long pfn, i; 6.202 - struct page *page; 6.203 + unsigned long *mfn_list, pfn, i, flags; 6.204 + struct page *page; 6.205 + long credit, debt, rc; 6.206 + void *v; 6.207 + 6.208 + down(&balloon_mutex); 6.209 + 6.210 + retry: 6.211 + mfn_list = NULL; 6.212 + 6.213 + if ( (credit = current_target() - current_pages) > 0 ) 6.214 + { 6.215 + mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list)); 6.216 + if ( mfn_list == NULL ) 6.217 + goto out; 6.218 + 6.219 + balloon_lock(flags); 6.220 + rc = HYPERVISOR_dom_mem_op( 6.221 + MEMOP_increase_reservation, mfn_list, credit, 0); 6.222 + balloon_unlock(flags); 6.223 + if ( rc < credit ) 6.224 + { 6.225 + /* We hit the Xen hard limit: reprobe. */ 6.226 + if ( HYPERVISOR_dom_mem_op( 6.227 + MEMOP_decrease_reservation, mfn_list, rc, 0) != rc ) 6.228 + BUG(); 6.229 + hard_limit = current_pages + rc - driver_pages; 6.230 + vfree(mfn_list); 6.231 + goto retry; 6.232 + } 6.233 + 6.234 + for ( i = 0; i < credit; i++ ) 6.235 + { 6.236 + if ( (page = balloon_retrieve()) == NULL ) 6.237 + BUG(); 6.238 + 6.239 + pfn = page - mem_map; 6.240 + if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) 6.241 + BUG(); 6.242 6.243 - for ( i = 0; i < nr_mfns; i++ ) 6.244 + /* Update P->M and M->P tables. */ 6.245 + phys_to_machine_mapping[pfn] = mfn_list[i]; 6.246 + queue_machphys_update(mfn_list[i], pfn); 6.247 + 6.248 + /* Link back into the page tables if it's not a highmem page. */ 6.249 + if ( pfn < max_low_pfn ) 6.250 + queue_l1_entry_update( 6.251 + get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), 6.252 + (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); 6.253 + 6.254 + /* Finally, relinquish the memory back to the system allocator. */ 6.255 + ClearPageReserved(page); 6.256 + set_page_count(page, 1); 6.257 + __free_page(page); 6.258 + } 6.259 + 6.260 + current_pages += credit; 6.261 + } 6.262 + else if ( credit < 0 ) 6.263 { 6.264 - if ( (page = balloon_retrieve()) != NULL ) 6.265 - break; 6.266 + debt = -credit; 6.267 + 6.268 + mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list)); 6.269 + if ( mfn_list == NULL ) 6.270 + goto out; 6.271 + 6.272 + for ( i = 0; i < debt; i++ ) 6.273 + { 6.274 + if ( (page = alloc_page(GFP_HIGHUSER)) == NULL ) 6.275 + { 6.276 + debt = i; 6.277 + break; 6.278 + } 6.279 + 6.280 + pfn = page - mem_map; 6.281 + mfn_list[i] = phys_to_machine_mapping[pfn]; 6.282 + phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; 6.283 6.284 - pfn = page - mem_map; 6.285 - if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) 6.286 + if ( !PageHighMem(page) ) 6.287 + { 6.288 + v = phys_to_virt((page - mem_map) << PAGE_SHIFT); 6.289 + scrub_pages(v, 1); 6.290 + queue_l1_entry_update(get_ptep((unsigned long)v), 0); 6.291 + } 6.292 +#ifdef CONFIG_XEN_SCRUB_PAGES 6.293 + else 6.294 + { 6.295 + v = kmap(page); 6.296 + scrub_pages(v, 1); 6.297 + kunmap(page); 6.298 + } 6.299 +#endif 6.300 + 6.301 + balloon_append(page); 6.302 + } 6.303 + 6.304 + /* Flush updates through and flush the TLB. */ 6.305 + xen_tlb_flush(); 6.306 + 6.307 + if ( HYPERVISOR_dom_mem_op( 6.308 + MEMOP_decrease_reservation, mfn_list, debt, 0) != debt ) 6.309 BUG(); 6.310 6.311 - /* Update P->M and M->P tables. */ 6.312 - phys_to_machine_mapping[pfn] = mfn_list[i]; 6.313 - queue_machphys_update(mfn_list[i], pfn); 6.314 - 6.315 - /* Link back into the page tables if it's not a highmem page. */ 6.316 - if ( pfn < max_low_pfn ) 6.317 - queue_l1_entry_update( 6.318 - get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), 6.319 - (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); 6.320 - 6.321 - /* Finally, relinquish the memory back to the system allocator. */ 6.322 - ClearPageReserved(page); 6.323 - set_page_count(page, 1); 6.324 - __free_page(page); 6.325 - } 6.326 - 6.327 - return i; 6.328 -} 6.329 - 6.330 -unsigned long deflate_balloon(unsigned long num_pages) 6.331 -{ 6.332 - unsigned long ret; 6.333 - unsigned long *parray; 6.334 - 6.335 - if ( num_pages > credit ) 6.336 - { 6.337 - printk(KERN_ERR "deflate_balloon: %lu pages > %lu credit.\n", 6.338 - num_pages, credit); 6.339 - return -EAGAIN; 6.340 + current_pages -= debt; 6.341 } 6.342 6.343 - parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long)); 6.344 - if ( parray == NULL ) 6.345 - { 6.346 - printk(KERN_ERR "deflate_balloon: Unable to vmalloc parray\n"); 6.347 - return 0; 6.348 - } 6.349 - 6.350 - ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, 6.351 - parray, num_pages, 0); 6.352 - if ( unlikely(ret != num_pages) ) 6.353 - { 6.354 - printk(KERN_ERR "deflate_balloon: xen increase_reservation err %lx\n", 6.355 - ret); 6.356 - goto cleanup; 6.357 - } 6.358 + out: 6.359 + if ( mfn_list != NULL ) 6.360 + vfree(mfn_list); 6.361 6.362 - if ( (ret = process_returned_pages(parray, num_pages)) < num_pages ) 6.363 - { 6.364 - printk(KERN_WARNING 6.365 - "deflate_balloon: restored only %lx of %lx pages.\n", 6.366 - ret, num_pages); 6.367 - goto cleanup; 6.368 - } 6.369 + /* Schedule more work if there is some still to be done. */ 6.370 + if ( current_target() != current_pages ) 6.371 + mod_timer(&balloon_timer, jiffies + HZ); 6.372 6.373 - ret = num_pages; 6.374 - credit -= num_pages; 6.375 - 6.376 - cleanup: 6.377 - vfree(parray); 6.378 - 6.379 - return ret; 6.380 + up(&balloon_mutex); 6.381 } 6.382 6.383 -#define PAGE_TO_MB_SHIFT 8 6.384 - 6.385 -static int balloon_try_target(int target) 6.386 +/* Resets the Xen limit, sets new target, and kicks off processing. */ 6.387 +static void set_new_target(unsigned long target) 6.388 { 6.389 - int change, reclaim; 6.390 - 6.391 - if ( target < current_pages ) 6.392 - { 6.393 - if ( (change = inflate_balloon(current_pages-target)) <= 0 ) 6.394 - return change; 6.395 - current_pages -= change; 6.396 - printk(KERN_INFO "Relinquish %dMB to xen. Domain now has %luMB\n", 6.397 - change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); 6.398 - } 6.399 - else if ( (reclaim = target - current_pages) > 0 ) 6.400 - { 6.401 - if ( (change = deflate_balloon(reclaim)) <= 0 ) 6.402 - return change; 6.403 - current_pages += change; 6.404 - printk(KERN_INFO "Reclaim %dMB from xen. Domain now has %luMB\n", 6.405 - change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); 6.406 - } 6.407 - 6.408 - return 1; 6.409 + hard_limit = ~0UL; 6.410 + target_pages = target; 6.411 + balloon_process(NULL); 6.412 } 6.413 6.414 - 6.415 static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) 6.416 { 6.417 switch ( msg->subtype ) 6.418 @@ -308,7 +300,8 @@ static void balloon_ctrlif_rx(ctrl_msg_t 6.419 goto parse_error; 6.420 { 6.421 mem_request_t *req = (mem_request_t *)&msg->msg[0]; 6.422 - req->status = balloon_try_target(req->target); 6.423 + set_new_target(req->target); 6.424 + req->status = 0; 6.425 } 6.426 break; 6.427 default: 6.428 @@ -323,20 +316,13 @@ static void balloon_ctrlif_rx(ctrl_msg_t 6.429 ctrl_if_send_response(msg); 6.430 } 6.431 6.432 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 6.433 -typedef size_t count_t; 6.434 -#else 6.435 -typedef u_long count_t; 6.436 -#endif 6.437 - 6.438 -static int do_balloon_write(const char *buffer, count_t count) 6.439 +static int balloon_write(struct file *file, const char *buffer, 6.440 + size_t count, loff_t *offp) 6.441 { 6.442 char memstring[64], *endchar; 6.443 int len, i; 6.444 - unsigned long target; 6.445 - unsigned long long targetbytes; 6.446 + unsigned long long target_bytes; 6.447 6.448 - /* Only admin can play with the balloon :) */ 6.449 if ( !capable(CAP_SYS_ADMIN) ) 6.450 return -EPERM; 6.451 6.452 @@ -344,8 +330,10 @@ static int do_balloon_write(const char * 6.453 return -EFBIG; 6.454 6.455 len = strnlen_user(buffer, count); 6.456 - if ( len == 0 ) return -EBADMSG; 6.457 - if ( len == 1 ) return 1; /* input starts with a NUL char */ 6.458 + if ( len == 0 ) 6.459 + return -EBADMSG; 6.460 + if ( len == 1 ) 6.461 + goto out; /* input starts with a NUL char */ 6.462 if ( strncpy_from_user(memstring, buffer, len) < 0 ) 6.463 return -EFAULT; 6.464 6.465 @@ -356,24 +344,10 @@ static int do_balloon_write(const char * 6.466 if ( i == 0 ) 6.467 return -EBADMSG; 6.468 6.469 - targetbytes = memparse(memstring,&endchar); 6.470 - target = targetbytes >> PAGE_SHIFT; 6.471 - 6.472 - i = balloon_try_target(target); 6.473 - 6.474 - if ( i <= 0 ) return i; 6.475 + target_bytes = memparse(memstring,&endchar); 6.476 + set_new_target(target_bytes >> PAGE_SHIFT); 6.477 6.478 - return len; 6.479 -} 6.480 - 6.481 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 6.482 -static int balloon_write(struct file *file, const char *buffer, 6.483 - size_t count, loff_t *offp) 6.484 -{ 6.485 - int len = do_balloon_write(buffer, count); 6.486 - 6.487 - if ( len <= 0 ) return len; 6.488 - 6.489 + out: 6.490 *offp += len; 6.491 return len; 6.492 } 6.493 @@ -381,18 +355,44 @@ static int balloon_write(struct file *fi 6.494 static int balloon_read(struct file *filp, char *buffer, 6.495 size_t count, loff_t *offp) 6.496 { 6.497 - static char priv_buf[32]; 6.498 - char *priv_bufp = priv_buf; 6.499 + char *priv_buf; 6.500 int len; 6.501 - len = sprintf(priv_buf,"%lu\n",current_pages<<PAGE_SHIFT); 6.502 + 6.503 + priv_buf = (char *)__get_free_page(GFP_KERNEL); 6.504 + if ( priv_buf == NULL ) 6.505 + return -ENOMEM; 6.506 + 6.507 +#define K(_p) ((_p)<<(PAGE_SHIFT-10)) 6.508 + len = sprintf( 6.509 + priv_buf, 6.510 + "Current allocation: %8lu kB\n" 6.511 + "Target allocation: %8lu kB / %8lu kB (actual / requested)\n" 6.512 + "Unused heap space: %8lu kB / %8lu kB (low-mem / high-mem)\n" 6.513 + "Xen hard limit: ", 6.514 + K(current_pages), 6.515 + K(current_target()), K(target_pages), 6.516 + K(balloon_low), K(balloon_high)); 6.517 + 6.518 + if ( hard_limit != ~0UL ) 6.519 + len += sprintf( 6.520 + priv_buf + len, 6.521 + "%8lu kB (inc. %8lu kB driver headroom)\n", 6.522 + K(hard_limit), K(driver_pages)); 6.523 + else 6.524 + len += sprintf( 6.525 + priv_buf + len, 6.526 + " ??? kB\n"); 6.527 6.528 len -= *offp; 6.529 - priv_bufp += *offp; 6.530 - if (len>count) len = count; 6.531 - if (len<0) len = 0; 6.532 + if ( len > count) 6.533 + len = count; 6.534 + if ( len < 0 ) 6.535 + len = 0; 6.536 6.537 - if ( copy_to_user(buffer, priv_bufp, len) != 0 ) 6.538 - return -EFAULT; 6.539 + if ( len != 0 ) 6.540 + (void)copy_to_user(buffer, &priv_buf[*offp], len); 6.541 + 6.542 + free_page((unsigned long)priv_buf); 6.543 6.544 *offp += len; 6.545 return len; 6.546 @@ -403,30 +403,6 @@ static struct file_operations balloon_fo 6.547 .write = balloon_write 6.548 }; 6.549 6.550 -#else 6.551 - 6.552 -static int balloon_write(struct file *file, const char *buffer, 6.553 - u_long count, void *data) 6.554 -{ 6.555 - return do_balloon_write(buffer, count); 6.556 -} 6.557 - 6.558 -static int balloon_read(char *page, char **start, off_t off, 6.559 - int count, int *eof, void *data) 6.560 -{ 6.561 - int len; 6.562 - len = sprintf(page,"%lu\n",current_pages<<PAGE_SHIFT); 6.563 - 6.564 - if (len <= off+count) *eof = 1; 6.565 - *start = page + off; 6.566 - len -= off; 6.567 - if (len>count) len = count; 6.568 - if (len<0) len = 0; 6.569 - return len; 6.570 -} 6.571 - 6.572 -#endif 6.573 - 6.574 static int __init balloon_init(void) 6.575 { 6.576 unsigned long pfn; 6.577 @@ -435,20 +411,23 @@ static int __init balloon_init(void) 6.578 IPRINTK("Initialising balloon driver.\n"); 6.579 6.580 current_pages = min(xen_start_info.nr_pages, max_pfn); 6.581 - if ( (balloon_pde = create_xen_proc_entry("memory_target", 0644)) == NULL ) 6.582 + target_pages = current_pages; 6.583 + balloon_low = 0; 6.584 + balloon_high = 0; 6.585 + driver_pages = 0UL; 6.586 + hard_limit = ~0UL; 6.587 + 6.588 + init_timer(&balloon_timer); 6.589 + balloon_timer.data = 0; 6.590 + balloon_timer.function = balloon_alarm; 6.591 + 6.592 + if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL ) 6.593 { 6.594 - WPRINTK("Unable to create balloon driver proc entry!"); 6.595 + WPRINTK("Unable to create /proc/xen/balloon.\n"); 6.596 return -1; 6.597 } 6.598 6.599 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 6.600 - balloon_pde->owner = THIS_MODULE; 6.601 - balloon_pde->nlink = 1; 6.602 balloon_pde->proc_fops = &balloon_fops; 6.603 -#else 6.604 - balloon_pde->write_proc = balloon_write; 6.605 - balloon_pde->read_proc = balloon_read; 6.606 -#endif 6.607 6.608 (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 6.609 CALLBACK_IN_BLOCKING_CONTEXT); 6.610 @@ -464,14 +443,29 @@ static int __init balloon_init(void) 6.611 return 0; 6.612 } 6.613 6.614 -static void __exit balloon_cleanup(void) 6.615 +__initcall(balloon_init); 6.616 + 6.617 +void balloon_update_driver_allowance(long delta) 6.618 { 6.619 - if ( balloon_pde != NULL ) 6.620 - { 6.621 - remove_xen_proc_entry("memory_target"); 6.622 - balloon_pde = NULL; 6.623 - } 6.624 + unsigned long flags; 6.625 + balloon_lock(flags); 6.626 + driver_pages += delta; 6.627 + balloon_unlock(flags); 6.628 } 6.629 6.630 -module_init(balloon_init); 6.631 -module_exit(balloon_cleanup); 6.632 +void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) 6.633 +{ 6.634 + unsigned long flags; 6.635 + 6.636 + balloon_lock(flags); 6.637 + if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 6.638 + mfn_list, nr_mfns, 0) != nr_mfns ) 6.639 + BUG(); 6.640 + current_pages -= nr_mfns; 6.641 + balloon_unlock(flags); 6.642 + 6.643 + schedule_work(&balloon_worker); 6.644 +} 6.645 + 6.646 +EXPORT_SYMBOL(balloon_update_driver_allowance); 6.647 +EXPORT_SYMBOL(balloon_put_pages);
7.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c Thu Dec 02 09:21:31 2004 +0000 7.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c Thu Dec 02 16:17:28 2004 +0000 7.3 @@ -11,6 +11,7 @@ 7.4 */ 7.5 7.6 #include "common.h" 7.7 +#include <asm-xen/balloon.h> 7.8 7.9 static void netif_page_release(struct page *page); 7.10 static void netif_skb_release(struct sk_buff *skb); 7.11 @@ -29,6 +30,8 @@ static DECLARE_TASKLET(net_tx_tasklet, n 7.12 static void net_rx_action(unsigned long unused); 7.13 static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0); 7.14 7.15 +static struct timer_list net_timer; 7.16 + 7.17 static struct sk_buff_head rx_queue; 7.18 static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2]; 7.19 static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE*3]; 7.20 @@ -69,27 +72,20 @@ static unsigned long mfn_list[MAX_MFN_AL 7.21 static unsigned int alloc_index = 0; 7.22 static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED; 7.23 7.24 -static void __refresh_mfn_list(void) 7.25 +static unsigned long alloc_mfn(void) 7.26 { 7.27 - int ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, 7.28 - mfn_list, MAX_MFN_ALLOC, 0); 7.29 - if ( unlikely(ret != MAX_MFN_ALLOC) ) 7.30 - BUG(); 7.31 - alloc_index = MAX_MFN_ALLOC; 7.32 -} 7.33 - 7.34 -static unsigned long get_new_mfn(void) 7.35 -{ 7.36 - unsigned long mfn, flags; 7.37 + unsigned long mfn = 0, flags; 7.38 spin_lock_irqsave(&mfn_lock, flags); 7.39 - if ( alloc_index == 0 ) 7.40 - __refresh_mfn_list(); 7.41 - mfn = mfn_list[--alloc_index]; 7.42 + if ( unlikely(alloc_index == 0) ) 7.43 + alloc_index = HYPERVISOR_dom_mem_op( 7.44 + MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0); 7.45 + if ( alloc_index != 0 ) 7.46 + mfn = mfn_list[--alloc_index]; 7.47 spin_unlock_irqrestore(&mfn_lock, flags); 7.48 return mfn; 7.49 } 7.50 7.51 -static void dealloc_mfn(unsigned long mfn) 7.52 +static void free_mfn(unsigned long mfn) 7.53 { 7.54 unsigned long flags; 7.55 spin_lock_irqsave(&mfn_lock, flags); 7.56 @@ -210,8 +206,16 @@ static void net_rx_action(unsigned long 7.57 netif = (netif_t *)skb->dev->priv; 7.58 vdata = (unsigned long)skb->data; 7.59 mdata = virt_to_machine(vdata); 7.60 - new_mfn = get_new_mfn(); 7.61 - 7.62 + 7.63 + /* Memory squeeze? Back off for an arbitrary while. */ 7.64 + if ( (new_mfn = alloc_mfn()) == 0 ) 7.65 + { 7.66 + if ( net_ratelimit() ) 7.67 + printk(KERN_WARNING "Memory squeeze in netback driver.\n"); 7.68 + mod_timer(&net_timer, jiffies + HZ); 7.69 + break; 7.70 + } 7.71 + 7.72 /* 7.73 * Set the new P2M table entry before reassigning the old data page. 7.74 * Heed the comment in pgtable-2level.h:pte_page(). :-) 7.75 @@ -280,7 +284,7 @@ static void net_rx_action(unsigned long 7.76 if ( unlikely(mcl[1].args[5] != 0) ) 7.77 { 7.78 DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid); 7.79 - dealloc_mfn(mdata >> PAGE_SHIFT); 7.80 + free_mfn(mdata >> PAGE_SHIFT); 7.81 status = NETIF_RSP_ERROR; 7.82 } 7.83 7.84 @@ -307,7 +311,7 @@ static void net_rx_action(unsigned long 7.85 } 7.86 7.87 /* More work to do? */ 7.88 - if ( !skb_queue_empty(&rx_queue) ) 7.89 + if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) ) 7.90 tasklet_schedule(&net_rx_tasklet); 7.91 #if 0 7.92 else 7.93 @@ -315,6 +319,11 @@ static void net_rx_action(unsigned long 7.94 #endif 7.95 } 7.96 7.97 +static void net_alarm(unsigned long unused) 7.98 +{ 7.99 + tasklet_schedule(&net_rx_tasklet); 7.100 +} 7.101 + 7.102 struct net_device_stats *netif_be_get_stats(struct net_device *dev) 7.103 { 7.104 netif_t *netif = dev->priv; 7.105 @@ -781,9 +790,16 @@ static int __init netback_init(void) 7.106 7.107 printk("Initialising Xen netif backend\n"); 7.108 7.109 + /* We can increase reservation by this much in net_rx_action(). */ 7.110 + balloon_update_driver_allowance(NETIF_RX_RING_SIZE); 7.111 + 7.112 skb_queue_head_init(&rx_queue); 7.113 skb_queue_head_init(&tx_queue); 7.114 7.115 + init_timer(&net_timer); 7.116 + net_timer.data = 0; 7.117 + net_timer.function = net_alarm; 7.118 + 7.119 netif_interface_init(); 7.120 7.121 if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 )
8.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c Thu Dec 02 09:21:31 2004 +0000 8.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c Thu Dec 02 16:17:28 2004 +0000 8.3 @@ -45,6 +45,7 @@ 8.4 #include <asm-xen/evtchn.h> 8.5 #include <asm-xen/ctrl_if.h> 8.6 #include <asm-xen/xen-public/io/netif.h> 8.7 +#include <asm-xen/balloon.h> 8.8 #include <asm/page.h> 8.9 8.10 #include <net/arp.h> 8.11 @@ -409,6 +410,9 @@ static void network_alloc_rx_buffers(str 8.12 rx_mcl[i].args[3] = 0; 8.13 rx_mcl[i].args[4] = DOMID_SELF; 8.14 8.15 + /* Tell the ballon driver what is going on. */ 8.16 + balloon_update_driver_allowance(i); 8.17 + 8.18 /* Zap PTEs and give away pages in one big multicall. */ 8.19 (void)HYPERVISOR_multicall(rx_mcl, i+1); 8.20 8.21 @@ -557,14 +561,15 @@ static int netif_poll(struct net_device 8.22 /* 8.23 * An error here is very odd. Usually indicates a backend bug, 8.24 * low-memory condition, or that we didn't have reservation headroom. 8.25 - * Whatever - print an error and queue the id again straight away. 8.26 */ 8.27 if ( unlikely(rx->status <= 0) ) 8.28 { 8.29 - printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status); 8.30 + if ( net_ratelimit() ) 8.31 + printk(KERN_WARNING "Bad rx buffer (memory squeeze?).\n"); 8.32 np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; 8.33 wmb(); 8.34 np->rx->req_prod++; 8.35 + work_done--; 8.36 continue; 8.37 } 8.38 8.39 @@ -595,6 +600,9 @@ static int netif_poll(struct net_device 8.40 __skb_queue_tail(&rxq, skb); 8.41 } 8.42 8.43 + /* Some pages are no longer absent... */ 8.44 + balloon_update_driver_allowance(-work_done); 8.45 + 8.46 /* Do all the remapping work, and M->P updates, in one big hypercall. */ 8.47 if ( likely((mcl - rx_mcl) != 0) ) 8.48 {
9.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Dec 02 09:21:31 2004 +0000 9.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Dec 02 16:17:28 2004 +0000 9.3 @@ -7,7 +7,6 @@ 9.4 */ 9.5 9.6 #include <linux/config.h> 9.7 -#include <linux/module.h> 9.8 #include <linux/kernel.h> 9.9 #include <linux/sched.h> 9.10 #include <linux/slab.h> 9.11 @@ -213,23 +212,9 @@ static int __init privcmd_init(void) 9.12 9.13 privcmd_intf = create_xen_proc_entry("privcmd", 0400); 9.14 if ( privcmd_intf != NULL ) 9.15 - { 9.16 - privcmd_intf->owner = THIS_MODULE; 9.17 - privcmd_intf->nlink = 1; 9.18 - privcmd_intf->proc_fops = &privcmd_file_ops; 9.19 - } 9.20 + privcmd_intf->proc_fops = &privcmd_file_ops; 9.21 9.22 return 0; 9.23 } 9.24 9.25 - 9.26 -static void __exit privcmd_cleanup(void) 9.27 -{ 9.28 - if ( privcmd_intf == NULL ) return; 9.29 - remove_xen_proc_entry("privcmd"); 9.30 - privcmd_intf = NULL; 9.31 -} 9.32 - 9.33 - 9.34 -module_init(privcmd_init); 9.35 -module_exit(privcmd_cleanup); 9.36 +__initcall(privcmd_init);
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/balloon.h Thu Dec 02 16:17:28 2004 +0000 10.3 @@ -0,0 +1,51 @@ 10.4 +/****************************************************************************** 10.5 + * balloon.h 10.6 + * 10.7 + * Xen balloon driver - enables returning/claiming memory to/from Xen. 10.8 + * 10.9 + * Copyright (c) 2003, B Dragovic 10.10 + * Copyright (c) 2003-2004, M Williamson, K Fraser 10.11 + * 10.12 + * This file may be distributed separately from the Linux kernel, or 10.13 + * incorporated into other software packages, subject to the following license: 10.14 + * 10.15 + * Permission is hereby granted, free of charge, to any person obtaining a copy 10.16 + * of this source file (the "Software"), to deal in the Software without 10.17 + * restriction, including without limitation the rights to use, copy, modify, 10.18 + * merge, publish, distribute, sublicense, and/or sell copies of the Software, 10.19 + * and to permit persons to whom the Software is furnished to do so, subject to 10.20 + * the following conditions: 10.21 + * 10.22 + * The above copyright notice and this permission notice shall be included in 10.23 + * all copies or substantial portions of the Software. 10.24 + * 10.25 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10.26 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10.27 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10.28 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 10.29 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 10.30 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 10.31 + * IN THE SOFTWARE. 10.32 + */ 10.33 + 10.34 +#ifndef __ASM_BALLOON_H__ 10.35 +#define __ASM_BALLOON_H__ 10.36 + 10.37 +/* 10.38 + * Inform the balloon driver that it should allow some slop for device-driver 10.39 + * memory activities. 10.40 + */ 10.41 +extern void balloon_update_driver_allowance(long delta); 10.42 + 10.43 +/* Give up unmapped pages to the balloon driver. */ 10.44 +extern void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns); 10.45 + 10.46 +/* 10.47 + * Prevent the balloon driver from changing the memory reservation during 10.48 + * a driver critical region. 10.49 + */ 10.50 +extern spinlock_t balloon_lock; 10.51 +#define balloon_lock(__flags) spin_lock_irqsave(&balloon_lock, __flags) 10.52 +#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags) 10.53 + 10.54 +#endif /* __ASM_BALLOON_H__ */
11.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h Thu Dec 02 09:21:31 2004 +0000 11.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h Thu Dec 02 16:17:28 2004 +0000 11.3 @@ -102,8 +102,6 @@ void MULTICALL_flush_page_update_queue(v 11.4 #ifdef CONFIG_XEN_PHYSDEV_ACCESS 11.5 /* Allocate a contiguous empty region of low memory. Return virtual start. */ 11.6 unsigned long allocate_empty_lowmem_region(unsigned long pages); 11.7 -/* Deallocate a contiguous region of low memory. Return it to the allocator. */ 11.8 -void deallocate_lowmem_region(unsigned long vstart, unsigned long pages); 11.9 #endif 11.10 11.11 /*