ia64/xen-unstable

changeset 6331:2052ce3345c1

Apply Ross Mcilroy's balloon_dealloc_empty_page_range patch
and generally clean up the ballon driver a bunch.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Aug 22 16:38:13 2005 +0000 (2005-08-22)
parents 531ad4bde8f2
children 8c58bf335465 3a8f27c6d56c
files linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c linux-2.6-xen-sparse/drivers/xen/netback/netback.c linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c linux-2.6-xen-sparse/include/asm-xen/balloon.h linux-2.6-xen-sparse/include/asm-xen/hypervisor.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c	Mon Aug 22 10:21:18 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c	Mon Aug 22 16:38:13 2005 +0000
     1.3 @@ -405,54 +405,6 @@ void xen_destroy_contiguous_region(unsig
     1.4  	balloon_unlock(flags);
     1.5  }
     1.6  
     1.7 -
     1.8 -unsigned long allocate_empty_lowmem_region(unsigned long pages)
     1.9 -{
    1.10 -	pgd_t         *pgd;
    1.11 -	pud_t         *pud; 
    1.12 -	pmd_t         *pmd;
    1.13 -	pte_t         *pte;
    1.14 -	unsigned long *pfn_array;
    1.15 -	unsigned long  vstart;
    1.16 -	unsigned long  i;
    1.17 -	unsigned int   order = get_order(pages*PAGE_SIZE);
    1.18 -
    1.19 -	vstart = __get_free_pages(GFP_KERNEL, order);
    1.20 -	if (vstart == 0)
    1.21 -		return 0UL;
    1.22 -
    1.23 -	scrub_pages(vstart, 1 << order);
    1.24 -
    1.25 -	pfn_array = vmalloc((1<<order) * sizeof(*pfn_array));
    1.26 -	BUG_ON(pfn_array == NULL);
    1.27 -
    1.28 -	for (i = 0; i < (1<<order); i++) {
    1.29 -		pgd = pgd_offset_k(   (vstart + (i*PAGE_SIZE)));
    1.30 -		pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
    1.31 -		pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
    1.32 -		pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); 
    1.33 -		pfn_array[i] = pte_mfn(*pte);
    1.34 -#ifdef CONFIG_X86_64
    1.35 -		xen_l1_entry_update(pte, __pte(0));
    1.36 -#else
    1.37 -		BUG_ON(HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), 
    1.38 -						    __pte_ma(0), 0));
    1.39 -#endif
    1.40 -		phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
    1.41 -			INVALID_P2M_ENTRY;
    1.42 -	}
    1.43 -
    1.44 -	flush_tlb_all();
    1.45 -
    1.46 -	balloon_put_pages(pfn_array, 1 << order);
    1.47 -
    1.48 -	vfree(pfn_array);
    1.49 -
    1.50 -	return vstart;
    1.51 -}
    1.52 -
    1.53 -EXPORT_SYMBOL(allocate_empty_lowmem_region);
    1.54 -
    1.55  /*
    1.56   * Local variables:
    1.57   *  c-file-style: "linux"
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Mon Aug 22 10:21:18 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Mon Aug 22 16:38:13 2005 +0000
     2.3 @@ -83,12 +83,15 @@ static struct timer_list balloon_timer;
     2.4  
     2.5  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
     2.6  /* Use the private and mapping fields of struct page as a list. */
     2.7 -#define PAGE_TO_LIST(p) ( (struct list_head *)&p->private )
     2.8 -#define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l),   \
     2.9 -                                      struct page, private ) )
    2.10 -#define UNLIST_PAGE(p)  do { list_del(PAGE_TO_LIST(p));       \
    2.11 -                             p->mapping = NULL;               \
    2.12 -                             p->private = 0; } while(0)
    2.13 +#define PAGE_TO_LIST(p) ((struct list_head *)&p->private)
    2.14 +#define LIST_TO_PAGE(l)				\
    2.15 +	(list_entry(((unsigned long *)l), struct page, private))
    2.16 +#define UNLIST_PAGE(p)				\
    2.17 +	do {					\
    2.18 +		list_del(PAGE_TO_LIST(p));	\
    2.19 +		p->mapping = NULL;		\
    2.20 +		p->private = 0;			\
    2.21 +	} while(0)
    2.22  #else
    2.23  /* There's a dedicated list field in struct page we can use.    */
    2.24  #define PAGE_TO_LIST(p) ( &p->list )
    2.25 @@ -104,56 +107,53 @@ static struct timer_list balloon_timer;
    2.26  #endif
    2.27  
    2.28  #define IPRINTK(fmt, args...) \
    2.29 -    printk(KERN_INFO "xen_mem: " fmt, ##args)
    2.30 +	printk(KERN_INFO "xen_mem: " fmt, ##args)
    2.31  #define WPRINTK(fmt, args...) \
    2.32 -    printk(KERN_WARNING "xen_mem: " fmt, ##args)
    2.33 +	printk(KERN_WARNING "xen_mem: " fmt, ##args)
    2.34  
    2.35  /* balloon_append: add the given page to the balloon. */
    2.36  static void balloon_append(struct page *page)
    2.37  {
    2.38 -    /* Low memory is re-populated first, so highmem pages go at list tail. */
    2.39 -    if ( PageHighMem(page) )
    2.40 -    {
    2.41 -        list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
    2.42 -        balloon_high++;
    2.43 -    }
    2.44 -    else
    2.45 -    {
    2.46 -        list_add(PAGE_TO_LIST(page), &ballooned_pages);
    2.47 -        balloon_low++;
    2.48 -    }
    2.49 +	/* Lowmem is re-populated first, so highmem pages go at list tail. */
    2.50 +	if (PageHighMem(page)) {
    2.51 +		list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
    2.52 +		balloon_high++;
    2.53 +	} else {
    2.54 +		list_add(PAGE_TO_LIST(page), &ballooned_pages);
    2.55 +		balloon_low++;
    2.56 +	}
    2.57  }
    2.58  
    2.59  /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
    2.60  static struct page *balloon_retrieve(void)
    2.61  {
    2.62 -    struct page *page;
    2.63 +	struct page *page;
    2.64  
    2.65 -    if ( list_empty(&ballooned_pages) )
    2.66 -        return NULL;
    2.67 +	if (list_empty(&ballooned_pages))
    2.68 +		return NULL;
    2.69  
    2.70 -    page = LIST_TO_PAGE(ballooned_pages.next);
    2.71 -    UNLIST_PAGE(page);
    2.72 +	page = LIST_TO_PAGE(ballooned_pages.next);
    2.73 +	UNLIST_PAGE(page);
    2.74  
    2.75 -    if ( PageHighMem(page) )
    2.76 -        balloon_high--;
    2.77 -    else
    2.78 -        balloon_low--;
    2.79 +	if (PageHighMem(page))
    2.80 +		balloon_high--;
    2.81 +	else
    2.82 +		balloon_low--;
    2.83  
    2.84 -    return page;
    2.85 +	return page;
    2.86  }
    2.87  
    2.88  static void balloon_alarm(unsigned long unused)
    2.89  {
    2.90 -    schedule_work(&balloon_worker);
    2.91 +	schedule_work(&balloon_worker);
    2.92  }
    2.93  
    2.94  static unsigned long current_target(void)
    2.95  {
    2.96 -    unsigned long target = min(target_pages, hard_limit);
    2.97 -    if ( target > (current_pages + balloon_low + balloon_high) )
    2.98 -        target = current_pages + balloon_low + balloon_high;
    2.99 -    return target;
   2.100 +	unsigned long target = min(target_pages, hard_limit);
   2.101 +	if (target > (current_pages + balloon_low + balloon_high))
   2.102 +		target = current_pages + balloon_low + balloon_high;
   2.103 +	return target;
   2.104  }
   2.105  
   2.106  /*
   2.107 @@ -164,161 +164,147 @@ static unsigned long current_target(void
   2.108   */
   2.109  static void balloon_process(void *unused)
   2.110  {
   2.111 -    unsigned long *mfn_list, pfn, i, flags;
   2.112 -    struct page   *page;
   2.113 -    long           credit, debt, rc;
   2.114 -    void          *v;
   2.115 +	unsigned long *mfn_list, pfn, i, flags;
   2.116 +	struct page   *page;
   2.117 +	long           credit, debt, rc;
   2.118 +	void          *v;
   2.119  
   2.120 -    down(&balloon_mutex);
   2.121 +	down(&balloon_mutex);
   2.122  
   2.123   retry:
   2.124 -    mfn_list = NULL;
   2.125 +	mfn_list = NULL;
   2.126  
   2.127 -    if ( (credit = current_target() - current_pages) > 0 )
   2.128 -    {
   2.129 -        mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list));
   2.130 -        if ( mfn_list == NULL )
   2.131 -            goto out;
   2.132 +	if ((credit = current_target() - current_pages) > 0) {
   2.133 +		mfn_list = vmalloc(credit * sizeof(*mfn_list));
   2.134 +		if (mfn_list == NULL)
   2.135 +			goto out;
   2.136  
   2.137 -        balloon_lock(flags);
   2.138 -        rc = HYPERVISOR_dom_mem_op(
   2.139 -            MEMOP_increase_reservation, mfn_list, credit, 0);
   2.140 -        balloon_unlock(flags);
   2.141 -        if ( rc < credit )
   2.142 -        {
   2.143 -            /* We hit the Xen hard limit: reprobe. */
   2.144 -            if ( HYPERVISOR_dom_mem_op(
   2.145 -                MEMOP_decrease_reservation, mfn_list, rc, 0) != rc )
   2.146 -                BUG();
   2.147 -            hard_limit = current_pages + rc - driver_pages;
   2.148 -            vfree(mfn_list);
   2.149 -            goto retry;
   2.150 -        }
   2.151 +		balloon_lock(flags);
   2.152 +		rc = HYPERVISOR_dom_mem_op(
   2.153 +			MEMOP_increase_reservation, mfn_list, credit, 0);
   2.154 +		balloon_unlock(flags);
   2.155 +		if (rc < credit) {
   2.156 +			/* We hit the Xen hard limit: reprobe. */
   2.157 +			BUG_ON(HYPERVISOR_dom_mem_op(
   2.158 +				MEMOP_decrease_reservation,
   2.159 +				mfn_list, rc, 0) != rc);
   2.160 +			hard_limit = current_pages + rc - driver_pages;
   2.161 +			vfree(mfn_list);
   2.162 +			goto retry;
   2.163 +		}
   2.164  
   2.165 -        for ( i = 0; i < credit; i++ )
   2.166 -        {
   2.167 -            if ( (page = balloon_retrieve()) == NULL )
   2.168 -                BUG();
   2.169 +		for (i = 0; i < credit; i++) {
   2.170 +			page = balloon_retrieve();
   2.171 +			BUG_ON(page == NULL);
   2.172  
   2.173 -            pfn = page - mem_map;
   2.174 -            if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY )
   2.175 -                BUG();
   2.176 +			pfn = page - mem_map;
   2.177 +			if (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY)
   2.178 +				BUG();
   2.179  
   2.180 -            /* Update P->M and M->P tables. */
   2.181 -            phys_to_machine_mapping[pfn] = mfn_list[i];
   2.182 -            xen_machphys_update(mfn_list[i], pfn);
   2.183 +			/* Update P->M and M->P tables. */
   2.184 +			phys_to_machine_mapping[pfn] = mfn_list[i];
   2.185 +			xen_machphys_update(mfn_list[i], pfn);
   2.186              
   2.187 -            /* Link back into the page tables if it's not a highmem page. */
   2.188 -            if ( pfn < max_low_pfn )
   2.189 -            {
   2.190 -                BUG_ON(HYPERVISOR_update_va_mapping(
   2.191 -                    (unsigned long)__va(pfn << PAGE_SHIFT),
   2.192 -                    pfn_pte_ma(mfn_list[i], PAGE_KERNEL), 0));
   2.193 -            }
   2.194 +			/* Link back into the page tables if not highmem. */
   2.195 +			if (pfn < max_low_pfn)
   2.196 +				BUG_ON(HYPERVISOR_update_va_mapping(
   2.197 +					(unsigned long)__va(pfn << PAGE_SHIFT),
   2.198 +					pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
   2.199 +					0));
   2.200  
   2.201 -            /* Finally, relinquish the memory back to the system allocator. */
   2.202 -            ClearPageReserved(page);
   2.203 -            set_page_count(page, 1);
   2.204 -            __free_page(page);
   2.205 -        }
   2.206 +			/* Relinquish the page back to the allocator. */
   2.207 +			ClearPageReserved(page);
   2.208 +			set_page_count(page, 1);
   2.209 +			__free_page(page);
   2.210 +		}
   2.211  
   2.212 -        current_pages += credit;
   2.213 -    }
   2.214 -    else if ( credit < 0 )
   2.215 -    {
   2.216 -        debt = -credit;
   2.217 +		current_pages += credit;
   2.218 +	} else if (credit < 0) {
   2.219 +		debt = -credit;
   2.220  
   2.221 -        mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list));
   2.222 -        if ( mfn_list == NULL )
   2.223 -            goto out;
   2.224 +		mfn_list = vmalloc(debt * sizeof(*mfn_list));
   2.225 +		if (mfn_list == NULL)
   2.226 +			goto out;
   2.227  
   2.228 -        for ( i = 0; i < debt; i++ )
   2.229 -        {
   2.230 -            if ( (page = alloc_page(GFP_HIGHUSER)) == NULL )
   2.231 -            {
   2.232 -                debt = i;
   2.233 -                break;
   2.234 -            }
   2.235 +		for (i = 0; i < debt; i++) {
   2.236 +			if ((page = alloc_page(GFP_HIGHUSER)) == NULL) {
   2.237 +				debt = i;
   2.238 +				break;
   2.239 +			}
   2.240  
   2.241 -            pfn = page - mem_map;
   2.242 -            mfn_list[i] = phys_to_machine_mapping[pfn];
   2.243 +			pfn = page - mem_map;
   2.244 +			mfn_list[i] = phys_to_machine_mapping[pfn];
   2.245  
   2.246 -            if ( !PageHighMem(page) )
   2.247 -            {
   2.248 -                v = phys_to_virt(pfn << PAGE_SHIFT);
   2.249 -                scrub_pages(v, 1);
   2.250 -                BUG_ON(HYPERVISOR_update_va_mapping(
   2.251 -                    (unsigned long)v, __pte_ma(0), 0));
   2.252 -            }
   2.253 +			if (!PageHighMem(page)) {
   2.254 +				v = phys_to_virt(pfn << PAGE_SHIFT);
   2.255 +				scrub_pages(v, 1);
   2.256 +				BUG_ON(HYPERVISOR_update_va_mapping(
   2.257 +					(unsigned long)v, __pte_ma(0), 0));
   2.258 +			}
   2.259  #ifdef CONFIG_XEN_SCRUB_PAGES
   2.260 -            else
   2.261 -            {
   2.262 -                v = kmap(page);
   2.263 -                scrub_pages(v, 1);
   2.264 -                kunmap(page);
   2.265 -            }
   2.266 +			else {
   2.267 +				v = kmap(page);
   2.268 +				scrub_pages(v, 1);
   2.269 +				kunmap(page);
   2.270 +			}
   2.271  #endif
   2.272 -        }
   2.273 +		}
   2.274  
   2.275 -        /* Ensure that ballooned highmem pages don't have cached mappings. */
   2.276 -        kmap_flush_unused();
   2.277 -        flush_tlb_all();
   2.278 +		/* Ensure that ballooned highmem pages don't have kmaps. */
   2.279 +		kmap_flush_unused();
   2.280 +		flush_tlb_all();
   2.281  
   2.282 -        /* No more mappings: invalidate pages in P2M and add to balloon. */
   2.283 -        for ( i = 0; i < debt; i++ )
   2.284 -        {
   2.285 -            pfn = mfn_to_pfn(mfn_list[i]);
   2.286 -            phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
   2.287 -            balloon_append(pfn_to_page(pfn));
   2.288 -        }
   2.289 +		/* No more mappings: invalidate P2M and add to balloon. */
   2.290 +		for (i = 0; i < debt; i++) {
   2.291 +			pfn = mfn_to_pfn(mfn_list[i]);
   2.292 +			phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
   2.293 +			balloon_append(pfn_to_page(pfn));
   2.294 +		}
   2.295  
   2.296 -        if ( HYPERVISOR_dom_mem_op(
   2.297 -            MEMOP_decrease_reservation, mfn_list, debt, 0) != debt )
   2.298 -            BUG();
   2.299 +		BUG_ON(HYPERVISOR_dom_mem_op(
   2.300 +			MEMOP_decrease_reservation,mfn_list, debt, 0) != debt);
   2.301  
   2.302 -        current_pages -= debt;
   2.303 -    }
   2.304 +		current_pages -= debt;
   2.305 +	}
   2.306  
   2.307   out:
   2.308 -    if ( mfn_list != NULL )
   2.309 -        vfree(mfn_list);
   2.310 +	if (mfn_list != NULL)
   2.311 +		vfree(mfn_list);
   2.312  
   2.313 -    /* Schedule more work if there is some still to be done. */
   2.314 -    if ( current_target() != current_pages )
   2.315 -        mod_timer(&balloon_timer, jiffies + HZ);
   2.316 +	/* Schedule more work if there is some still to be done. */
   2.317 +	if (current_target() != current_pages)
   2.318 +		mod_timer(&balloon_timer, jiffies + HZ);
   2.319  
   2.320 -    up(&balloon_mutex);
   2.321 +	up(&balloon_mutex);
   2.322  }
   2.323  
   2.324  /* Resets the Xen limit, sets new target, and kicks off processing. */
   2.325  static void set_new_target(unsigned long target)
   2.326  {
   2.327 -    /* No need for lock. Not read-modify-write updates. */
   2.328 -    hard_limit   = ~0UL;
   2.329 -    target_pages = target;
   2.330 -    schedule_work(&balloon_worker);
   2.331 +	/* No need for lock. Not read-modify-write updates. */
   2.332 +	hard_limit   = ~0UL;
   2.333 +	target_pages = target;
   2.334 +	schedule_work(&balloon_worker);
   2.335  }
   2.336  
   2.337  static struct xenbus_watch target_watch =
   2.338  {
   2.339 -    .node = "memory/target"
   2.340 +	.node = "memory/target"
   2.341  };
   2.342  
   2.343  /* React to a change in the target key */
   2.344  static void watch_target(struct xenbus_watch *watch, const char *node)
   2.345  {
   2.346 -    unsigned long new_target;
   2.347 -    int err;
   2.348 +	unsigned long new_target;
   2.349 +	int err;
   2.350  
   2.351 -    err = xenbus_scanf("memory", "target", "%lu", &new_target);
   2.352 +	err = xenbus_scanf("memory", "target", "%lu", &new_target);
   2.353 +	if (err != 1) {
   2.354 +		printk(KERN_ERR "Unable to read memory/target\n");
   2.355 +		return;
   2.356 +	} 
   2.357          
   2.358 -    if(err != 1) 
   2.359 -    {
   2.360 -        printk(KERN_ERR "Unable to read memory/target\n");
   2.361 -        return;
   2.362 -    } 
   2.363 -        
   2.364 -    set_new_target(new_target >> PAGE_SHIFT);
   2.365 +	set_new_target(new_target >> PAGE_SHIFT);
   2.366      
   2.367  }
   2.368  
   2.369 @@ -329,141 +315,185 @@ int balloon_init_watcher(struct notifier
   2.370                           unsigned long event,
   2.371                           void *data)
   2.372  {
   2.373 -    int err;
   2.374 +	int err;
   2.375  
   2.376 -    BUG_ON(down_trylock(&xenbus_lock) == 0);
   2.377 -
   2.378 -    err = register_xenbus_watch(&target_watch);
   2.379 +	BUG_ON(down_trylock(&xenbus_lock) == 0);
   2.380  
   2.381 -    if (err) {
   2.382 -        printk(KERN_ERR "Failed to set balloon watcher\n");
   2.383 -    }
   2.384 +	err = register_xenbus_watch(&target_watch);
   2.385 +	if (err)
   2.386 +		printk(KERN_ERR "Failed to set balloon watcher\n");
   2.387  
   2.388 -    return NOTIFY_DONE;
   2.389 +	return NOTIFY_DONE;
   2.390      
   2.391  }
   2.392  
   2.393  static int balloon_write(struct file *file, const char __user *buffer,
   2.394                           unsigned long count, void *data)
   2.395  {
   2.396 -    char memstring[64], *endchar;
   2.397 -    unsigned long long target_bytes;
   2.398 +	char memstring[64], *endchar;
   2.399 +	unsigned long long target_bytes;
   2.400  
   2.401 -    if ( !capable(CAP_SYS_ADMIN) )
   2.402 -        return -EPERM;
   2.403 +	if (!capable(CAP_SYS_ADMIN))
   2.404 +		return -EPERM;
   2.405  
   2.406 -    if ( count <= 1 )
   2.407 -        return -EBADMSG; /* runt */
   2.408 -    if ( count > sizeof(memstring) )
   2.409 -        return -EFBIG;   /* too long */
   2.410 +	if (count <= 1)
   2.411 +		return -EBADMSG; /* runt */
   2.412 +	if (count > sizeof(memstring))
   2.413 +		return -EFBIG;   /* too long */
   2.414  
   2.415 -    if ( copy_from_user(memstring, buffer, count) )
   2.416 -        return -EFAULT;
   2.417 -    memstring[sizeof(memstring)-1] = '\0';
   2.418 +	if (copy_from_user(memstring, buffer, count))
   2.419 +		return -EFAULT;
   2.420 +	memstring[sizeof(memstring)-1] = '\0';
   2.421  
   2.422 -    target_bytes = memparse(memstring, &endchar);
   2.423 -    set_new_target(target_bytes >> PAGE_SHIFT);
   2.424 +	target_bytes = memparse(memstring, &endchar);
   2.425 +	set_new_target(target_bytes >> PAGE_SHIFT);
   2.426  
   2.427 -    return count;
   2.428 +	return count;
   2.429  }
   2.430  
   2.431  static int balloon_read(char *page, char **start, off_t off,
   2.432                          int count, int *eof, void *data)
   2.433  {
   2.434 -    int len;
   2.435 +	int len;
   2.436  
   2.437 -    len = sprintf(
   2.438 -        page,
   2.439 -        "Current allocation: %8lu kB\n"
   2.440 -        "Requested target:   %8lu kB\n"
   2.441 -        "Low-mem balloon:    %8lu kB\n"
   2.442 -        "High-mem balloon:   %8lu kB\n"
   2.443 -        "Xen hard limit:     ",
   2.444 -        PAGES2KB(current_pages), PAGES2KB(target_pages), 
   2.445 -        PAGES2KB(balloon_low), PAGES2KB(balloon_high));
   2.446 +	len = sprintf(
   2.447 +		page,
   2.448 +		"Current allocation: %8lu kB\n"
   2.449 +		"Requested target:   %8lu kB\n"
   2.450 +		"Low-mem balloon:    %8lu kB\n"
   2.451 +		"High-mem balloon:   %8lu kB\n"
   2.452 +		"Xen hard limit:     ",
   2.453 +		PAGES2KB(current_pages), PAGES2KB(target_pages), 
   2.454 +		PAGES2KB(balloon_low), PAGES2KB(balloon_high));
   2.455  
   2.456 -    if ( hard_limit != ~0UL )
   2.457 -        len += sprintf(
   2.458 -            page + len, 
   2.459 -            "%8lu kB (inc. %8lu kB driver headroom)\n",
   2.460 -            PAGES2KB(hard_limit), PAGES2KB(driver_pages));
   2.461 -    else
   2.462 -        len += sprintf(
   2.463 -            page + len,
   2.464 -            "     ??? kB\n");
   2.465 +	if (hard_limit != ~0UL) {
   2.466 +		len += sprintf(
   2.467 +			page + len, 
   2.468 +			"%8lu kB (inc. %8lu kB driver headroom)\n",
   2.469 +			PAGES2KB(hard_limit), PAGES2KB(driver_pages));
   2.470 +	} else {
   2.471 +		len += sprintf(
   2.472 +			page + len,
   2.473 +			"     ??? kB\n");
   2.474 +	}
   2.475  
   2.476 -    *eof = 1;
   2.477 -    return len;
   2.478 +	*eof = 1;
   2.479 +	return len;
   2.480  }
   2.481  
   2.482  static struct notifier_block xenstore_notifier;
   2.483  
   2.484  static int __init balloon_init(void)
   2.485  {
   2.486 -    unsigned long pfn;
   2.487 -    struct page *page;
   2.488 +	unsigned long pfn;
   2.489 +	struct page *page;
   2.490  
   2.491 -    IPRINTK("Initialising balloon driver.\n");
   2.492 +	IPRINTK("Initialising balloon driver.\n");
   2.493  
   2.494 -    current_pages = min(xen_start_info.nr_pages, max_pfn);
   2.495 -    target_pages  = current_pages;
   2.496 -    balloon_low   = 0;
   2.497 -    balloon_high  = 0;
   2.498 -    driver_pages  = 0UL;
   2.499 -    hard_limit    = ~0UL;
   2.500 +	current_pages = min(xen_start_info.nr_pages, max_pfn);
   2.501 +	target_pages  = current_pages;
   2.502 +	balloon_low   = 0;
   2.503 +	balloon_high  = 0;
   2.504 +	driver_pages  = 0UL;
   2.505 +	hard_limit    = ~0UL;
   2.506  
   2.507 -    init_timer(&balloon_timer);
   2.508 -    balloon_timer.data = 0;
   2.509 -    balloon_timer.function = balloon_alarm;
   2.510 +	init_timer(&balloon_timer);
   2.511 +	balloon_timer.data = 0;
   2.512 +	balloon_timer.function = balloon_alarm;
   2.513      
   2.514 -    if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL )
   2.515 -    {
   2.516 -        WPRINTK("Unable to create /proc/xen/balloon.\n");
   2.517 -        return -1;
   2.518 -    }
   2.519 +	if ((balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL) {
   2.520 +		WPRINTK("Unable to create /proc/xen/balloon.\n");
   2.521 +		return -1;
   2.522 +	}
   2.523  
   2.524 -    balloon_pde->read_proc  = balloon_read;
   2.525 -    balloon_pde->write_proc = balloon_write;
   2.526 +	balloon_pde->read_proc  = balloon_read;
   2.527 +	balloon_pde->write_proc = balloon_write;
   2.528      
   2.529 -    /* Initialise the balloon with excess memory space. */
   2.530 -    for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ )
   2.531 -    {
   2.532 -        page = &mem_map[pfn];
   2.533 -        if ( !PageReserved(page) )
   2.534 -            balloon_append(page);
   2.535 -    }
   2.536 +	/* Initialise the balloon with excess memory space. */
   2.537 +	for (pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++) {
   2.538 +		page = &mem_map[pfn];
   2.539 +		if (!PageReserved(page))
   2.540 +			balloon_append(page);
   2.541 +	}
   2.542  
   2.543 -    target_watch.callback = watch_target;
   2.544 -    xenstore_notifier.notifier_call = balloon_init_watcher;
   2.545 +	target_watch.callback = watch_target;
   2.546 +	xenstore_notifier.notifier_call = balloon_init_watcher;
   2.547  
   2.548 -    register_xenstore_notifier(&xenstore_notifier);
   2.549 +	register_xenstore_notifier(&xenstore_notifier);
   2.550      
   2.551 -    return 0;
   2.552 +	return 0;
   2.553  }
   2.554  
   2.555  subsys_initcall(balloon_init);
   2.556  
   2.557  void balloon_update_driver_allowance(long delta)
   2.558  {
   2.559 -    unsigned long flags;
   2.560 -    balloon_lock(flags);
   2.561 -    driver_pages += delta; /* non-atomic update */
   2.562 -    balloon_unlock(flags);
   2.563 +	unsigned long flags;
   2.564 +	balloon_lock(flags);
   2.565 +	driver_pages += delta; /* non-atomic update */
   2.566 +	balloon_unlock(flags);
   2.567  }
   2.568  
   2.569 -void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns)
   2.570 +struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
   2.571  {
   2.572 -    unsigned long flags;
   2.573 +	int f(pte_t *pte, struct page *pte_page,
   2.574 +	      unsigned long addr, void *data)
   2.575 +	{
   2.576 +		unsigned long mfn = pte_mfn(*pte);
   2.577 +		set_pte(pte, __pte_ma(0));
   2.578 +		phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] =
   2.579 +			INVALID_P2M_ENTRY;
   2.580 +		BUG_ON(HYPERVISOR_dom_mem_op(
   2.581 +			MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
   2.582 +		return 0;
   2.583 +        }
   2.584 +
   2.585 +	unsigned long vstart, flags;
   2.586 +	unsigned int  order = get_order(nr_pages * PAGE_SIZE);
   2.587 +
   2.588 +	vstart = __get_free_pages(GFP_KERNEL, order);
   2.589 +	if (vstart == 0)
   2.590 +		return NULL;
   2.591 +
   2.592 +	scrub_pages(vstart, 1 << order);
   2.593  
   2.594 -    balloon_lock(flags);
   2.595 -    if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 
   2.596 -                               mfn_list, nr_mfns, 0) != nr_mfns )
   2.597 -        BUG();
   2.598 -    current_pages -= nr_mfns; /* non-atomic update */
   2.599 -    balloon_unlock(flags);
   2.600 +	balloon_lock(flags);
   2.601 +	BUG_ON(generic_page_range(
   2.602 +		&init_mm, vstart, PAGE_SIZE << order, f, NULL) != 0);
   2.603 +	current_pages -= 1UL << order;
   2.604 +	balloon_unlock(flags);
   2.605 +
   2.606 +	schedule_work(&balloon_worker);
   2.607 +
   2.608 +	flush_tlb_all();
   2.609 +
   2.610 +	return virt_to_page(vstart);
   2.611 +}
   2.612  
   2.613 -    schedule_work(&balloon_worker);
   2.614 +void balloon_dealloc_empty_page_range(
   2.615 +	struct page *page, unsigned long nr_pages)
   2.616 +{
   2.617 +	unsigned long i, flags;
   2.618 +	unsigned int  order = get_order(nr_pages * PAGE_SIZE);
   2.619 +
   2.620 +	balloon_lock(flags);
   2.621 +	for (i = 0; i < (1UL << order); i++)
   2.622 +		balloon_append(page + i);
   2.623 +	balloon_unlock(flags);
   2.624 +
   2.625 +	schedule_work(&balloon_worker);
   2.626  }
   2.627  
   2.628  EXPORT_SYMBOL(balloon_update_driver_allowance);
   2.629 -EXPORT_SYMBOL(balloon_put_pages);
   2.630 +EXPORT_SYMBOL(balloon_alloc_empty_page_range);
   2.631 +EXPORT_SYMBOL(balloon_dealloc_empty_page_range);
   2.632 +
   2.633 +/*
   2.634 + * Local variables:
   2.635 + *  c-file-style: "linux"
   2.636 + *  indent-tabs-mode: t
   2.637 + *  c-indent-level: 8
   2.638 + *  c-basic-offset: 8
   2.639 + *  tab-width: 8
   2.640 + * End:
   2.641 + */
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c	Mon Aug 22 10:21:18 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c	Mon Aug 22 16:38:13 2005 +0000
     3.3 @@ -569,6 +569,7 @@ void blkif_deschedule(blkif_t *blkif)
     3.4  static int __init blkif_init(void)
     3.5  {
     3.6      int i;
     3.7 +    struct page *page;
     3.8  
     3.9      if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
    3.10           !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) )
    3.11 @@ -576,8 +577,9 @@ static int __init blkif_init(void)
    3.12  
    3.13      blkif_interface_init();
    3.14  
    3.15 -    if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
    3.16 -        BUG();
    3.17 +    page = balloon_alloc_empty_page_range(MMAP_PAGES);
    3.18 +    BUG_ON(page == NULL);
    3.19 +    mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
    3.20  
    3.21      pending_cons = 0;
    3.22      pending_prod = MAX_PENDING_REQS;
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Mon Aug 22 10:21:18 2005 +0000
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Mon Aug 22 16:38:13 2005 +0000
     4.3 @@ -775,9 +775,11 @@ static struct miscdevice blktap_miscdev 
     4.4  int blktap_init(void)
     4.5  {
     4.6      int err, i, j;
     4.7 +    struct page *page;
     4.8  
     4.9 -    if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
    4.10 -        BUG();
    4.11 +    page = balloon_alloc_empty_page_range(MMAP_PAGES);
    4.12 +    BUG_ON(page == NULL);
    4.13 +    mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
    4.14  
    4.15  #ifdef CONFIG_XEN_BLKDEV_GRANT
    4.16      for (i=0; i<MAX_PENDING_REQS ; i++)
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Aug 22 10:21:18 2005 +0000
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Aug 22 16:38:13 2005 +0000
     5.3 @@ -968,8 +968,9 @@ static int __init netback_init(void)
     5.4      
     5.5      netif_interface_init();
     5.6  
     5.7 -    mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS);
     5.8 -    BUG_ON(mmap_vstart == 0);
     5.9 +    page = balloon_alloc_empty_page_range(MAX_PENDING_REQS);
    5.10 +    BUG_ON(page == NULL);
    5.11 +    mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
    5.12  
    5.13      for ( i = 0; i < MAX_PENDING_REQS; i++ )
    5.14      {
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c	Mon Aug 22 10:21:18 2005 +0000
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c	Mon Aug 22 16:38:13 2005 +0000
     6.3 @@ -1027,13 +1027,15 @@ void usbif_release_ports(usbif_priv_t *u
     6.4  static int __init usbif_init(void)
     6.5  {
     6.6      int i;
     6.7 +    struct page *page;
     6.8  
     6.9      if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
    6.10           !(xen_start_info.flags & SIF_USB_BE_DOMAIN) )
    6.11          return 0;
    6.12 -    
    6.13 -    if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
    6.14 -        BUG();
    6.15 +
    6.16 +    page = balloon_alloc_empty_page_range(MMAP_PAGES);
    6.17 +    BUG_ON(page == NULL);
    6.18 +    mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
    6.19  
    6.20      pending_cons = 0;
    6.21      pending_prod = MAX_PENDING_REQS;
     7.1 --- a/linux-2.6-xen-sparse/include/asm-xen/balloon.h	Mon Aug 22 10:21:18 2005 +0000
     7.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/balloon.h	Mon Aug 22 16:38:13 2005 +0000
     7.3 @@ -35,10 +35,19 @@
     7.4   * Inform the balloon driver that it should allow some slop for device-driver
     7.5   * memory activities.
     7.6   */
     7.7 -extern void balloon_update_driver_allowance(long delta);
     7.8 +extern void
     7.9 +balloon_update_driver_allowance(
    7.10 +	long delta);
    7.11  
    7.12 -/* Give up unmapped pages to the balloon driver. */
    7.13 -extern void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns);
    7.14 +/* Allocate an empty low-memory page range. */
    7.15 +extern struct page *
    7.16 +balloon_alloc_empty_page_range(
    7.17 +	unsigned long nr_pages);
    7.18 +
    7.19 +/* Deallocate an empty page range, adding to the balloon. */
    7.20 +extern void
    7.21 +balloon_dealloc_empty_page_range(
    7.22 +	struct page *page, unsigned long nr_pages);
    7.23  
    7.24  /*
    7.25   * Prevent the balloon driver from changing the memory reservation during
     8.1 --- a/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h	Mon Aug 22 10:21:18 2005 +0000
     8.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h	Mon Aug 22 16:38:13 2005 +0000
     8.3 @@ -137,9 +137,6 @@ void xen_invlpg_mask(cpumask_t *mask, un
     8.4  void xen_create_contiguous_region(unsigned long vstart, unsigned int order);
     8.5  void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
     8.6  
     8.7 -/* Allocate a contiguous empty region of low memory. Return virtual start. */
     8.8 -unsigned long allocate_empty_lowmem_region(unsigned long pages);
     8.9 -
    8.10  #include <asm/hypercall.h>
    8.11  
    8.12  #if defined(CONFIG_X86_64)