ia64/xen-unstable

changeset 3238:fdd2c0ba9164

bitkeeper revision 1.1159.187.52 (41af401feJ8RiM76UNPjXCq_P54GJQ)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-2.0-testing.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xen-2.0-testing.bk
author kaf24@scramble.cl.cam.ac.uk
date Thu Dec 02 16:17:35 2004 +0000 (2004-12-02)
parents 6e409bc26f22 a193790c4961
children 5c16d6acb085 0559e0d05589
files .rootkeys linux-2.4.28-xen-sparse/mkbuildtree linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c linux-2.6.9-xen-sparse/drivers/xen/Makefile linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c linux-2.6.9-xen-sparse/include/asm-xen/balloon.h linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h
line diff
     1.1 --- a/.rootkeys	Thu Dec 02 10:24:43 2004 +0000
     1.2 +++ b/.rootkeys	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     2.2 +++ b/linux-2.4.28-xen-sparse/mkbuildtree	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     5.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     6.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     7.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     8.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c	Thu Dec 02 16:17:35 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 10:24:43 2004 +0000
     9.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c	Thu Dec 02 16:17:35 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:35 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 10:24:43 2004 +0000
    11.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h	Thu Dec 02 16:17:35 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  /*