ia64/xen-unstable

changeset 1936:613602e2d771

bitkeeper revision 1.1108.26.1 (4106af006Bpl_nN84MShtvHA51xG0Q)

Domain allocations use the buddy allocator.
author kaf24@scramble.cl.cam.ac.uk
date Tue Jul 27 19:37:36 2004 +0000 (2004-07-27)
parents 9975cd31ac46
children 1e13ae874e9c
files xen/arch/x86/domain.c xen/arch/x86/shadow.c xen/common/dom0_ops.c xen/common/dom_mem_ops.c xen/common/domain.c xen/common/event_channel.c xen/common/kernel.c xen/common/memory.c xen/common/page_alloc.c xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/mm.h xen/include/asm-x86/page.h xen/include/xen/mm.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Tue Jul 27 14:55:17 2004 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Tue Jul 27 19:37:36 2004 +0000
     1.3 @@ -210,6 +210,11 @@ void machine_halt(void)
     1.4      __machine_halt(NULL);
     1.5  }
     1.6  
     1.7 +void free_perdomain_pt(struct domain *d)
     1.8 +{
     1.9 +    free_xenheap_page((unsigned long)d->mm.perdomain_pt);
    1.10 +}
    1.11 +
    1.12  void arch_do_createdomain(struct domain *d)
    1.13  {
    1.14      d->shared_info = (void *)alloc_xenheap_page();
     2.1 --- a/xen/arch/x86/shadow.c	Tue Jul 27 14:55:17 2004 +0000
     2.2 +++ b/xen/arch/x86/shadow.c	Tue Jul 27 19:37:36 2004 +0000
     2.3 @@ -64,11 +64,10 @@ interrupts enabled. Nothing can go wrong
     2.4  
     2.5  **/
     2.6  
     2.7 -static inline void free_shadow_page( struct mm_struct *m, 
     2.8 -                                     struct pfn_info *pfn_info )
     2.9 +static inline void free_shadow_page(struct mm_struct *m, 
    2.10 +                                    struct pfn_info *page)
    2.11  {
    2.12 -    unsigned long flags;
    2.13 -    unsigned long type = pfn_info->u.inuse.type_info & PGT_type_mask;
    2.14 +    unsigned long type = page->u.inuse.type_info & PGT_type_mask;
    2.15  
    2.16      m->shadow_page_count--;
    2.17  
    2.18 @@ -77,14 +76,9 @@ static inline void free_shadow_page( str
    2.19      else if (type == PGT_l2_page_table)
    2.20          perfc_decr(shadow_l2_pages);
    2.21      else printk("Free shadow weird page type pfn=%08x type=%08x\n",
    2.22 -                frame_table-pfn_info, pfn_info->u.inuse.type_info);
    2.23 +                frame_table-page, page->u.inuse.type_info);
    2.24      
    2.25 -    pfn_info->u.inuse.type_info = 0;
    2.26 -
    2.27 -    spin_lock_irqsave(&free_list_lock, flags);
    2.28 -    list_add(&pfn_info->list, &free_list);
    2.29 -    free_pfns++;
    2.30 -    spin_unlock_irqrestore(&free_list_lock, flags);
    2.31 +    free_domheap_page(page);
    2.32  }
    2.33  
    2.34  static void __free_shadow_table( struct mm_struct *m )
    2.35 @@ -518,7 +512,7 @@ int shadow_mode_control(struct domain *d
    2.36  static inline struct pfn_info *alloc_shadow_page(struct mm_struct *m)
    2.37  {
    2.38      m->shadow_page_count++;
    2.39 -    return alloc_domain_page(NULL);
    2.40 +    return alloc_domheap_page();
    2.41  }
    2.42  
    2.43  void unshadow_table( unsigned long gpfn, unsigned int type )
     3.1 --- a/xen/common/dom0_ops.c	Tue Jul 27 14:55:17 2004 +0000
     3.2 +++ b/xen/common/dom0_ops.c	Tue Jul 27 19:37:36 2004 +0000
     3.3 @@ -29,16 +29,16 @@ extern void arch_getdomaininfo_ctxt(stru
     3.4  
     3.5  static inline int is_free_domid(domid_t dom)
     3.6  {
     3.7 -    struct domain  *d;
     3.8 +    struct domain *d;
     3.9 +
    3.10 +    if ( dom >= DOMID_SELF )
    3.11 +        return 0;
    3.12  
    3.13 -    if (dom >= DOMID_SELF) return 0;
    3.14 -    d = find_domain_by_id(dom);
    3.15 -    if (d == NULL) {
    3.16 +    if ( (d = find_domain_by_id(dom)) == NULL )
    3.17          return 1;
    3.18 -    } else {
    3.19 -        put_domain(d);
    3.20 -        return 0;
    3.21 -    }
    3.22 +
    3.23 +    put_domain(d);
    3.24 +    return 0;
    3.25  }
    3.26  
    3.27  /** Allocate a free domain id. We try to reuse domain ids in a fairly low range,
    3.28 @@ -52,73 +52,43 @@ static int allocate_domid(domid_t *pdom)
    3.29      static domid_t curdom = 0;
    3.30      static domid_t topdom = 101;
    3.31      int err = 0;
    3.32 -    domid_t cur, dom, top;
    3.33 +    domid_t dom;
    3.34 +
    3.35 +    spin_lock(&domid_lock);
    3.36  
    3.37      /* Try to use a domain id in the range 0..topdom, starting at curdom. */
    3.38 -    spin_lock(&domid_lock);
    3.39 -    cur = curdom;
    3.40 -    dom = curdom;
    3.41 -    top = topdom;
    3.42 -    spin_unlock(&domid_lock);
    3.43 -    do {
    3.44 -        ++dom;
    3.45 -        if (dom == top) {
    3.46 +    for ( dom = curdom + 1; dom != curdom; dom++ )
    3.47 +    {
    3.48 +        if ( dom == topdom )
    3.49              dom = 1;
    3.50 -        }
    3.51 -        if (is_free_domid(dom)) goto exit;
    3.52 -    } while (dom != cur);
    3.53 +        if ( is_free_domid(dom) )
    3.54 +            goto exit;
    3.55 +    }
    3.56 +
    3.57      /* Couldn't find a free domain id in 0..topdom, try higher. */
    3.58 -    for (dom = top; dom < DOMID_SELF; dom++) {
    3.59 -        if(is_free_domid(dom)) goto exit;
    3.60 +    for ( dom = topdom; dom < DOMID_SELF; dom++ )
    3.61 +    {
    3.62 +        if ( is_free_domid(dom) )
    3.63 +        {
    3.64 +            topdom = dom + 1;
    3.65 +            goto exit;
    3.66 +        }
    3.67      }
    3.68 +
    3.69      /* No free domain ids. */
    3.70      err = -ENOMEM;
    3.71 +
    3.72    exit:
    3.73 -    if (err == 0) {
    3.74 -        spin_lock(&domid_lock);
    3.75 +    if ( err == 0 )
    3.76 +    {
    3.77          curdom = dom;
    3.78 -        if (dom >= topdom) {
    3.79 -            topdom = dom + 1;
    3.80 -        }
    3.81 -        spin_unlock(&domid_lock);
    3.82          *pdom = dom;
    3.83      }
    3.84 +
    3.85 +    spin_unlock(&domid_lock);
    3.86      return err;
    3.87  }
    3.88  
    3.89 -#if 0
    3.90 -        struct domain    *d;
    3.91 -        static domid_t    domnr = 0;
    3.92 -        static spinlock_t domnr_lock = SPIN_LOCK_UNLOCKED;
    3.93 -        unsigned int      pro;
    3.94 -        domid_t           dom;
    3.95 -
    3.96 -        ret = -ENOMEM;
    3.97 -
    3.98 -        if(op->u.createdomain.domain > 0){
    3.99 -            d = find_domain_by_id(dom);
   3.100 -            if(d){
   3.101 -                put_domain(d);
   3.102 -                ret = -EINVAL;
   3.103 -                break;
   3.104 -            }
   3.105 -        } else {
   3.106 -            /* Search for an unused domain identifier. */
   3.107 -            for ( ; ; )
   3.108 -            {
   3.109 -                spin_lock(&domnr_lock);
   3.110 -                /* Wrap the roving counter when we reach first special value. */
   3.111 -                if ( (dom = ++domnr) == DOMID_SELF )
   3.112 -                    dom = domnr = 1;
   3.113 -                spin_unlock(&domnr_lock);
   3.114 -                
   3.115 -                if ( (d = find_domain_by_id(dom)) == NULL )
   3.116 -                    break;
   3.117 -                put_domain(d);
   3.118 -             }
   3.119 -        }
   3.120 -#endif
   3.121 -
   3.122  long do_dom0_op(dom0_op_t *u_dom0_op)
   3.123  {
   3.124      long ret = 0;
   3.125 @@ -196,30 +166,23 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   3.126          unsigned int      pro;
   3.127          domid_t           dom;
   3.128  
   3.129 -        ret = -ENOMEM;
   3.130 -
   3.131          dom = op->u.createdomain.domain;
   3.132 -        if ( 0 < dom && dom < DOMID_SELF )
   3.133 +        if ( (dom > 0) && (dom < DOMID_SELF) )
   3.134          {
   3.135 +            ret = -EINVAL;
   3.136              if ( !is_free_domid(dom) )
   3.137 -            {
   3.138 -                ret = -EINVAL;
   3.139                  break;
   3.140 -            }
   3.141          }
   3.142 -        else
   3.143 -        {
   3.144 -            ret = allocate_domid(&dom);
   3.145 -            if ( ret ) break;
   3.146 -        }
   3.147 +        else if ( (ret = allocate_domid(&dom)) != 0 )
   3.148 +            break;
   3.149  
   3.150          if ( op->u.createdomain.cpu == -1 )
   3.151              pro = (unsigned int)dom % smp_num_cpus;
   3.152          else
   3.153              pro = op->u.createdomain.cpu % smp_num_cpus;
   3.154  
   3.155 -        d = do_createdomain(dom, pro);
   3.156 -        if ( d == NULL ) 
   3.157 +        ret = -ENOMEM;
   3.158 +        if ( (d = do_createdomain(dom, pro)) == NULL )
   3.159              break;
   3.160  
   3.161          if ( op->u.createdomain.name[0] )
   3.162 @@ -527,7 +490,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   3.163          pi->ht_per_core = ht;
   3.164          pi->cores       = smp_num_cpus / pi->ht_per_core;
   3.165          pi->total_pages = max_page;
   3.166 -        pi->free_pages  = free_pfns;
   3.167 +        pi->free_pages  = avail_domheap_pages();
   3.168          pi->cpu_khz     = cpu_khz;
   3.169  
   3.170          copy_to_user(u_dom0_op, op, sizeof(*op));
     4.1 --- a/xen/common/dom_mem_ops.c	Tue Jul 27 14:55:17 2004 +0000
     4.2 +++ b/xen/common/dom_mem_ops.c	Tue Jul 27 19:37:36 2004 +0000
     4.3 @@ -22,19 +22,8 @@ static long alloc_dom_mem(struct domain 
     4.4      struct pfn_info *page;
     4.5      unsigned long    i;
     4.6  
     4.7 -    /* Leave some slack pages; e.g., for the network. */
     4.8 -    if ( unlikely(free_pfns < (nr_pages + (SLACK_DOMAIN_MEM_KILOBYTES >> 
     4.9 -                                           (PAGE_SHIFT-10)))) )
    4.10 -    {
    4.11 -        DPRINTK("Not enough slack: %u %u\n",
    4.12 -                free_pfns,
    4.13 -                SLACK_DOMAIN_MEM_KILOBYTES >> (PAGE_SHIFT-10));
    4.14 -        return 0;
    4.15 -    }
    4.16 -
    4.17      for ( i = 0; i < nr_pages; i++ )
    4.18      {
    4.19 -        /* NB. 'alloc_domain_page' does limit-checking on pages per domain. */
    4.20          if ( unlikely((page = alloc_domain_page(d)) == NULL) )
    4.21          {
    4.22              DPRINTK("Could not allocate a frame\n");
     5.1 --- a/xen/common/domain.c	Tue Jul 27 14:55:17 2004 +0000
     5.2 +++ b/xen/common/domain.c	Tue Jul 27 19:37:36 2004 +0000
     5.3 @@ -197,20 +197,12 @@ void domain_shutdown(u8 reason)
     5.4  struct pfn_info *alloc_domain_page(struct domain *d)
     5.5  {
     5.6      struct pfn_info *page = NULL;
     5.7 -    unsigned long flags, mask, pfn_stamp, cpu_stamp;
     5.8 +    unsigned long mask, pfn_stamp, cpu_stamp;
     5.9      int i;
    5.10  
    5.11      ASSERT(!in_irq());
    5.12  
    5.13 -    spin_lock_irqsave(&free_list_lock, flags);
    5.14 -    if ( likely(!list_empty(&free_list)) )
    5.15 -    {
    5.16 -        page = list_entry(free_list.next, struct pfn_info, list);
    5.17 -        list_del(&page->list);
    5.18 -        free_pfns--;
    5.19 -    }
    5.20 -    spin_unlock_irqrestore(&free_list_lock, flags);
    5.21 -
    5.22 +    page = alloc_domheap_page();
    5.23      if ( unlikely(page == NULL) )
    5.24          return NULL;
    5.25  
    5.26 @@ -245,6 +237,7 @@ struct pfn_info *alloc_domain_page(struc
    5.27              DPRINTK("Over-allocation for domain %u: %u >= %u\n",
    5.28                      d->domain, d->tot_pages, d->max_pages);
    5.29              spin_unlock(&d->page_alloc_lock);
    5.30 +            page->u.inuse.domain = NULL;
    5.31              goto free_and_exit;
    5.32          }
    5.33          list_add_tail(&page->list, &d->page_list);
    5.34 @@ -257,16 +250,12 @@ struct pfn_info *alloc_domain_page(struc
    5.35      return page;
    5.36  
    5.37   free_and_exit:
    5.38 -    spin_lock_irqsave(&free_list_lock, flags);
    5.39 -    list_add(&page->list, &free_list);
    5.40 -    free_pfns++;
    5.41 -    spin_unlock_irqrestore(&free_list_lock, flags);
    5.42 +    free_domheap_page(page);
    5.43      return NULL;
    5.44  }
    5.45  
    5.46  void free_domain_page(struct pfn_info *page)
    5.47  {
    5.48 -    unsigned long  flags;
    5.49      int            drop_dom_ref;
    5.50      struct domain *d = page->u.inuse.domain;
    5.51  
    5.52 @@ -289,10 +278,7 @@ void free_domain_page(struct pfn_info *p
    5.53  
    5.54          page->u.inuse.count_info = 0;
    5.55          
    5.56 -        spin_lock_irqsave(&free_list_lock, flags);
    5.57 -        list_add(&page->list, &free_list);
    5.58 -        free_pfns++;
    5.59 -        spin_unlock_irqrestore(&free_list_lock, flags);
    5.60 +        free_domheap_page(page);
    5.61      }
    5.62  
    5.63      if ( drop_dom_ref )
    5.64 @@ -310,9 +296,7 @@ unsigned int alloc_new_dom_mem(struct do
    5.65      /* Grow the allocation if necessary. */
    5.66      for ( alloc_pfns = d->tot_pages; alloc_pfns < nr_pages; alloc_pfns++ )
    5.67      {
    5.68 -        if ( unlikely((page=alloc_domain_page(d)) == NULL) ||
    5.69 -             unlikely(free_pfns < (SLACK_DOMAIN_MEM_KILOBYTES >> 
    5.70 -                                   (PAGE_SHIFT-10))) )
    5.71 +        if ( unlikely((page=alloc_domain_page(d)) == NULL) )
    5.72          {
    5.73              domain_relinquish_memory(d);
    5.74              return -ENOMEM;
     6.1 --- a/xen/common/event_channel.c	Tue Jul 27 14:55:17 2004 +0000
     6.2 +++ b/xen/common/event_channel.c	Tue Jul 27 19:37:36 2004 +0000
     6.3 @@ -197,7 +197,6 @@ static long evtchn_bind_pirq(evtchn_bind
     6.4      if ( rc != 0 )
     6.5      {
     6.6          d->pirq_to_evtchn[pirq] = 0;
     6.7 -        DPRINTK("Couldn't bind to PIRQ %d (error=%d)\n", pirq, rc);
     6.8          goto out;
     6.9      }
    6.10  
     7.1 --- a/xen/common/kernel.c	Tue Jul 27 14:55:17 2004 +0000
     7.2 +++ b/xen/common/kernel.c	Tue Jul 27 19:37:36 2004 +0000
     7.3 @@ -220,7 +220,7 @@ void cmain(multiboot_info_t *mbi)
     7.4          for ( ; ; ) ;
     7.5      }
     7.6  
     7.7 -    ASSERT((sizeof(struct pfn_info) << 20) >
     7.8 +    ASSERT((sizeof(struct pfn_info) << 20) <=
     7.9             (FRAMETABLE_VIRT_END - FRAMETABLE_VIRT_START));
    7.10  
    7.11      init_frametable((void *)FRAMETABLE_VIRT_START, max_page);
    7.12 @@ -258,15 +258,15 @@ void cmain(multiboot_info_t *mbi)
    7.13             max_page >> (20-PAGE_SHIFT), max_page,
    7.14  	   max_mem  >> (20-PAGE_SHIFT));
    7.15  
    7.16 -    add_to_domain_alloc_list(dom0_memory_end, max_page << PAGE_SHIFT);
    7.17 -
    7.18      heap_start = memguard_init(&_end);
    7.19 -
    7.20 +    heap_start = __va(init_heap_allocator(__pa(heap_start), max_page));
    7.21 + 
    7.22 +    init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
    7.23      printk("Xen heap size is %luKB\n", 
    7.24  	   (xenheap_phys_end-__pa(heap_start))/1024 );
    7.25  
    7.26 -    init_page_allocator(__pa(heap_start), xenheap_phys_end);
    7.27 - 
    7.28 +    init_domheap_pages(dom0_memory_end, max_page << PAGE_SHIFT);
    7.29 +
    7.30      /* Initialise the slab allocator. */
    7.31      xmem_cache_init();
    7.32      xmem_cache_sizes_init(max_page);
    7.33 @@ -307,8 +307,8 @@ void cmain(multiboot_info_t *mbi)
    7.34          panic("Could not set up DOM0 guest OS\n");
    7.35  
    7.36      /* The stash space for the initial kernel image can now be freed up. */
    7.37 -    add_to_domain_alloc_list(__pa(frame_table) + frame_table_size,
    7.38 -                             dom0_memory_start);
    7.39 +    init_domheap_pages(__pa(frame_table) + frame_table_size,
    7.40 +                       dom0_memory_start);
    7.41  
    7.42      init_trace_bufs();
    7.43  
     8.1 --- a/xen/common/memory.c	Tue Jul 27 14:55:17 2004 +0000
     8.2 +++ b/xen/common/memory.c	Tue Jul 27 19:37:36 2004 +0000
     8.3 @@ -37,10 +37,6 @@ struct pfn_info *frame_table;
     8.4  unsigned long frame_table_size;
     8.5  unsigned long max_page;
     8.6  
     8.7 -struct list_head free_list;
     8.8 -spinlock_t free_list_lock;
     8.9 -unsigned int free_pfns;
    8.10 -
    8.11  extern void init_percpu_info(void);
    8.12  
    8.13  void __init init_frametable(void *frametable_vstart, unsigned long nr_pages)
    8.14 @@ -59,10 +55,6 @@ void __init init_frametable(void *framet
    8.15  
    8.16      memset(frame_table, 0, frame_table_size);
    8.17  
    8.18 -    spin_lock_init(&free_list_lock);
    8.19 -    INIT_LIST_HEAD(&free_list);    
    8.20 -    free_pfns = 0;
    8.21 -
    8.22      /* Initialise to a magic of 0x55555555 so easier to spot bugs later. */
    8.23      memset(machine_to_phys_mapping, 0x55, 4<<20);
    8.24  
    8.25 @@ -72,22 +64,7 @@ void __init init_frametable(void *framet
    8.26            mfn++ )
    8.27      {
    8.28          frame_table[mfn].u.inuse.count_info = 1 | PGC_allocated;
    8.29 -        frame_table[mfn].u.inuse.type_info = 1 | PGT_gdt_page; /* non-RW type */
    8.30 +        frame_table[mfn].u.inuse.type_info = 1 | PGT_gdt_page; /* non-RW */
    8.31          frame_table[mfn].u.inuse.domain = &idle0_task;
    8.32      }
    8.33  }
    8.34 -
    8.35 -
    8.36 -void add_to_domain_alloc_list(unsigned long ps, unsigned long pe)
    8.37 -{
    8.38 -    unsigned long i;
    8.39 -    unsigned long flags;
    8.40 -
    8.41 -    spin_lock_irqsave(&free_list_lock, flags);
    8.42 -    for ( i = ps >> PAGE_SHIFT; i < (pe >> PAGE_SHIFT); i++ )
    8.43 -    {
    8.44 -        list_add_tail(&frame_table[i].list, &free_list);
    8.45 -        free_pfns++;
    8.46 -    }
    8.47 -    spin_unlock_irqrestore(&free_list_lock, flags);
    8.48 -}
     9.1 --- a/xen/common/page_alloc.c	Tue Jul 27 14:55:17 2004 +0000
     9.2 +++ b/xen/common/page_alloc.c	Tue Jul 27 19:37:36 2004 +0000
     9.3 @@ -28,8 +28,6 @@
     9.4  #include <xen/spinlock.h>
     9.5  #include <xen/slab.h>
     9.6  
     9.7 -static spinlock_t alloc_lock = SPIN_LOCK_UNLOCKED;
     9.8 -
     9.9  
    9.10  /*********************
    9.11   * ALLOCATION BITMAP
    9.12 @@ -63,9 +61,6 @@ static void map_alloc(unsigned long firs
    9.13          ASSERT(!allocated_in_map(first_page + i));
    9.14  #endif
    9.15  
    9.16 -    memguard_unguard_range(phys_to_virt(first_page << PAGE_SHIFT), 
    9.17 -                           nr_pages << PAGE_SHIFT);
    9.18 -
    9.19      curr_idx  = first_page / PAGES_PER_MAPWORD;
    9.20      start_off = first_page & (PAGES_PER_MAPWORD-1);
    9.21      end_idx   = (first_page + nr_pages) / PAGES_PER_MAPWORD;
    9.22 @@ -95,9 +90,6 @@ static void map_free(unsigned long first
    9.23          ASSERT(allocated_in_map(first_page + i));
    9.24  #endif
    9.25  
    9.26 -    memguard_guard_range(phys_to_virt(first_page << PAGE_SHIFT), 
    9.27 -                         nr_pages << PAGE_SHIFT);
    9.28 -
    9.29      curr_idx = first_page / PAGES_PER_MAPWORD;
    9.30      start_off = first_page & (PAGES_PER_MAPWORD-1);
    9.31      end_idx   = (first_page + nr_pages) / PAGES_PER_MAPWORD;
    9.32 @@ -121,127 +113,138 @@ static void map_free(unsigned long first
    9.33   * BINARY BUDDY ALLOCATOR
    9.34   */
    9.35  
    9.36 -/* Linked lists of free chunks of different powers-of-two in size. */
    9.37 -#define NR_ORDERS 11 /* Up to 2^10 pages can be allocated at once. */
    9.38 -static struct list_head free_head[NR_ORDERS];
    9.39 +#define MEMZONE_XEN 0
    9.40 +#define MEMZONE_DOM 1
    9.41 +#define NR_ZONES    2
    9.42 +
    9.43 +/* Up to 2^10 pages can be allocated at once. */
    9.44 +#define MIN_ORDER  0
    9.45 +#define MAX_ORDER 10
    9.46 +#define NR_ORDERS (MAX_ORDER - MIN_ORDER + 1)
    9.47 +static struct list_head heap[NR_ZONES][NR_ORDERS];
    9.48 +
    9.49 +static unsigned long avail[NR_ZONES];
    9.50  
    9.51  #define round_pgdown(_p)  ((_p)&PAGE_MASK)
    9.52  #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
    9.53  
    9.54 +static spinlock_t heap_lock = SPIN_LOCK_UNLOCKED;
    9.55  
    9.56 -/*
    9.57 - * Initialise allocator, placing addresses [@min,@max] in free pool.
    9.58 - * @min and @max are PHYSICAL addresses.
    9.59 - */
    9.60 -void __init init_page_allocator(unsigned long min, unsigned long max)
    9.61 +
    9.62 +/* Initialise allocator to handle up to @max_pages. */
    9.63 +unsigned long init_heap_allocator(
    9.64 +    unsigned long bitmap_start, unsigned long max_pages)
    9.65  {
    9.66 -    int i;
    9.67 -    unsigned long range, bitmap_size;
    9.68 -    struct pfn_info *pg;
    9.69 +    int i, j;
    9.70 +    unsigned long bitmap_size;
    9.71 +
    9.72 +    memset(avail, 0, sizeof(avail));
    9.73  
    9.74 -    for ( i = 0; i < NR_ORDERS; i++ )
    9.75 -        INIT_LIST_HEAD(&free_head[i]);
    9.76 +    for ( i = 0; i < NR_ZONES; i++ )
    9.77 +        for ( j = 0; j < NR_ORDERS; j++ )
    9.78 +            INIT_LIST_HEAD(&heap[i][j]);
    9.79  
    9.80 -    min = round_pgup  (min);
    9.81 -    max = round_pgdown(max);
    9.82 +    bitmap_start = round_pgup(bitmap_start);
    9.83  
    9.84      /* Allocate space for the allocation bitmap. */
    9.85 -    bitmap_size  = (max+1) >> (PAGE_SHIFT+3);
    9.86 +    bitmap_size  = max_pages / 8;
    9.87      bitmap_size  = round_pgup(bitmap_size);
    9.88 -    alloc_bitmap = (unsigned long *)phys_to_virt(min);
    9.89 -    min         += bitmap_size;
    9.90 -    range        = max - min;
    9.91 +    alloc_bitmap = (unsigned long *)phys_to_virt(bitmap_start);
    9.92  
    9.93      /* All allocated by default. */
    9.94      memset(alloc_bitmap, ~0, bitmap_size);
    9.95 +
    9.96 +    return bitmap_start + bitmap_size;
    9.97 +}
    9.98 +
    9.99 +/* Hand the specified arbitrary page range to the specified heap zone. */
   9.100 +void init_heap_pages(int zone, struct pfn_info *pg, unsigned long nr_pages)
   9.101 +{
   9.102 +    int i;
   9.103 +    unsigned long flags;
   9.104 +
   9.105 +    spin_lock_irqsave(&heap_lock, flags);
   9.106 +
   9.107      /* Free up the memory we've been given to play with. */
   9.108 -    map_free(min>>PAGE_SHIFT, range>>PAGE_SHIFT);
   9.109 +    map_free(page_to_pfn(pg), nr_pages);
   9.110 +    avail[zone] += nr_pages;
   9.111      
   9.112 -    pg = &frame_table[min >> PAGE_SHIFT];
   9.113 -    while ( range != 0 )
   9.114 +    while ( nr_pages != 0 )
   9.115      {
   9.116          /*
   9.117           * Next chunk is limited by alignment of pg, but also must not be
   9.118           * bigger than remaining bytes.
   9.119           */
   9.120 -        for ( i = 0; i < NR_ORDERS; i++ )
   9.121 +        for ( i = 0; i < MAX_ORDER; i++ )
   9.122              if ( ((page_to_pfn(pg) & (1 << i)) != 0) ||
   9.123 -                 ((1 << (i + PAGE_SHIFT + 1)) > range) )
   9.124 +                 ((1 << (i + 1)) > nr_pages) )
   9.125                  break;
   9.126  
   9.127          PFN_ORDER(pg) = i;
   9.128 -        list_add_tail(&pg->list, &free_head[i]);
   9.129 +        list_add_tail(&pg->list, &heap[zone][i]);
   9.130  
   9.131 -        pg    += 1 << i;
   9.132 -        range -= 1 << (i + PAGE_SHIFT);
   9.133 +        pg       += 1 << i;
   9.134 +        nr_pages -= 1 << i;
   9.135      }
   9.136 +
   9.137 +    spin_unlock_irqrestore(&heap_lock, flags);
   9.138  }
   9.139  
   9.140  
   9.141 -/* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */
   9.142 -unsigned long alloc_xenheap_pages(int order)
   9.143 +/* Allocate 2^@order contiguous pages. */
   9.144 +struct pfn_info *alloc_heap_pages(int zone, int order)
   9.145  {
   9.146 -    int i, attempts = 0;
   9.147 +    int i;
   9.148      struct pfn_info *pg;
   9.149      unsigned long flags;
   9.150  
   9.151 -retry:
   9.152 -    spin_lock_irqsave(&alloc_lock, flags);
   9.153 +    spin_lock_irqsave(&heap_lock, flags);
   9.154  
   9.155      /* Find smallest order which can satisfy the request. */
   9.156      for ( i = order; i < NR_ORDERS; i++ )
   9.157 -	if ( !list_empty(&free_head[i]) )
   9.158 +	if ( !list_empty(&heap[zone][i]) )
   9.159  	    break;
   9.160  
   9.161      if ( i == NR_ORDERS ) 
   9.162          goto no_memory;
   9.163   
   9.164 -    pg = list_entry(free_head[i].next, struct pfn_info, list);
   9.165 +    pg = list_entry(heap[zone][i].next, struct pfn_info, list);
   9.166      list_del(&pg->list);
   9.167  
   9.168      /* We may have to halve the chunk a number of times. */
   9.169      while ( i != order )
   9.170      {
   9.171          PFN_ORDER(pg) = --i;
   9.172 -        list_add_tail(&pg->list, &free_head[i]);
   9.173 +        list_add_tail(&pg->list, &heap[zone][i]);
   9.174          pg += 1 << i;
   9.175      }
   9.176      
   9.177 -    map_alloc(page_to_pfn(pg), 1<<order);
   9.178 +    map_alloc(page_to_pfn(pg), 1 << order);
   9.179 +    avail[zone] -= 1 << order;
   9.180  
   9.181 -    spin_unlock_irqrestore(&alloc_lock, flags);
   9.182 +    spin_unlock_irqrestore(&heap_lock, flags);
   9.183  
   9.184 -    return (unsigned long)page_to_virt(pg);
   9.185 +    return pg;
   9.186  
   9.187   no_memory:
   9.188 -    spin_unlock_irqrestore(&alloc_lock, flags);
   9.189 -        
   9.190 -    if ( attempts++ < 8 )
   9.191 -    {
   9.192 -        xmem_cache_reap();
   9.193 -        goto retry;
   9.194 -    }
   9.195 -
   9.196 -    printk("Cannot handle page request order %d!\n", order);
   9.197 -    dump_slabinfo();
   9.198 -
   9.199 -    return 0;
   9.200 +    spin_unlock_irqrestore(&heap_lock, flags);
   9.201 +    return NULL;
   9.202  }
   9.203  
   9.204  
   9.205 -/* Free 2^@order pages at VIRTUAL address @p. */
   9.206 -void free_xenheap_pages(unsigned long p, int order)
   9.207 +/* Free 2^@order set of pages. */
   9.208 +void free_heap_pages(int zone, struct pfn_info *pg, int order)
   9.209  {
   9.210      unsigned long mask;
   9.211 -    struct pfn_info *pg = virt_to_page(p);
   9.212      unsigned long flags;
   9.213  
   9.214 -    spin_lock_irqsave(&alloc_lock, flags);
   9.215 +    spin_lock_irqsave(&heap_lock, flags);
   9.216  
   9.217 -    map_free(page_to_pfn(pg), 1<<order);
   9.218 +    map_free(page_to_pfn(pg), 1 << order);
   9.219 +    avail[zone] += 1 << order;
   9.220      
   9.221      /* Merge chunks as far as possible. */
   9.222 -    for ( ; ; )
   9.223 +    while ( order < MAX_ORDER )
   9.224      {
   9.225          mask = 1 << order;
   9.226  
   9.227 @@ -267,7 +270,79 @@ void free_xenheap_pages(unsigned long p,
   9.228      }
   9.229  
   9.230      PFN_ORDER(pg) = order;
   9.231 -    list_add_tail(&pg->list, &free_head[order]);
   9.232 +    list_add_tail(&pg->list, &heap[zone][order]);
   9.233 +
   9.234 +    spin_unlock_irqrestore(&heap_lock, flags);
   9.235 +}
   9.236 +
   9.237 +
   9.238 +
   9.239 +/*************************
   9.240 + * XEN-HEAP SUB-ALLOCATOR
   9.241 + */
   9.242 +
   9.243 +void init_xenheap_pages(unsigned long ps, unsigned long pe)
   9.244 +{
   9.245 +    ps = round_pgup(ps);
   9.246 +    pe = round_pgdown(pe);
   9.247 +    memguard_guard_range(__va(ps), pe - ps);
   9.248 +    init_heap_pages(MEMZONE_XEN, phys_to_page(ps), (pe - ps) >> PAGE_SHIFT);
   9.249 +}
   9.250 +
   9.251 +unsigned long alloc_xenheap_pages(int order)
   9.252 +{
   9.253 +    struct pfn_info *pg;
   9.254 +    int attempts = 0;
   9.255 +
   9.256 + retry:
   9.257 +    if ( unlikely((pg = alloc_heap_pages(MEMZONE_XEN, order)) == NULL) )
   9.258 +        goto no_memory;
   9.259 +    memguard_unguard_range(page_to_virt(pg), 1 << (order + PAGE_SHIFT));
   9.260 +    return (unsigned long)page_to_virt(pg);
   9.261 +
   9.262 + no_memory:
   9.263 +    if ( attempts++ < 8 )
   9.264 +    {
   9.265 +        xmem_cache_reap();
   9.266 +        goto retry;
   9.267 +    }
   9.268  
   9.269 -    spin_unlock_irqrestore(&alloc_lock, flags);
   9.270 +    printk("Cannot handle page request order %d!\n", order);
   9.271 +    dump_slabinfo();
   9.272 +    return 0;
   9.273 +}
   9.274 +
   9.275 +void free_xenheap_pages(unsigned long p, int order)
   9.276 +{
   9.277 +    memguard_guard_range((void *)p, 1 << (order + PAGE_SHIFT));    
   9.278 +    free_heap_pages(MEMZONE_XEN, virt_to_page(p), order);
   9.279  }
   9.280 +
   9.281 +
   9.282 +
   9.283 +/*************************
   9.284 + * DOMAIN-HEAP SUB-ALLOCATOR
   9.285 + */
   9.286 +
   9.287 +void init_domheap_pages(unsigned long ps, unsigned long pe)
   9.288 +{
   9.289 +    ps = round_pgup(ps);
   9.290 +    pe = round_pgdown(pe);
   9.291 +    init_heap_pages(MEMZONE_DOM, phys_to_page(ps), (pe - ps) >> PAGE_SHIFT);
   9.292 +}
   9.293 +
   9.294 +struct pfn_info *alloc_domheap_pages(int order)
   9.295 +{
   9.296 +    struct pfn_info *pg = alloc_heap_pages(MEMZONE_DOM, order);
   9.297 +    return pg;
   9.298 +}
   9.299 +
   9.300 +void free_domheap_pages(struct pfn_info *pg, int order)
   9.301 +{
   9.302 +    free_heap_pages(MEMZONE_DOM, pg, order);
   9.303 +}
   9.304 +
   9.305 +unsigned long avail_domheap_pages(void)
   9.306 +{
   9.307 +    return avail[MEMZONE_DOM];
   9.308 +}
    10.1 --- a/xen/include/asm-x86/config.h	Tue Jul 27 14:55:17 2004 +0000
    10.2 +++ b/xen/include/asm-x86/config.h	Tue Jul 27 19:37:36 2004 +0000
    10.3 @@ -58,12 +58,6 @@
    10.4  #define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
    10.5  #define ____cacheline_aligned __cacheline_aligned
    10.6  
    10.7 -/*
    10.8 - * Amount of slack domain memory to leave in system, in megabytes.
    10.9 - * Prevents a hard out-of-memory crunch for things like network receive.
   10.10 - */
   10.11 -#define SLACK_DOMAIN_MEM_KILOBYTES 2048
   10.12 -
   10.13  /* Linkage for x86 */
   10.14  #define asmlinkage        __attribute__((regparm(0)))
   10.15  #define __ALIGN .align 16,0x90
    11.1 --- a/xen/include/asm-x86/domain.h	Tue Jul 27 14:55:17 2004 +0000
    11.2 +++ b/xen/include/asm-x86/domain.h	Tue Jul 27 19:37:36 2004 +0000
    11.3 @@ -7,10 +7,7 @@ extern void arch_do_createdomain(struct 
    11.4  extern void arch_final_setup_guestos(
    11.5      struct domain *d, full_execution_context_t *c);
    11.6  
    11.7 -static inline void free_perdomain_pt(struct domain *d)
    11.8 -{
    11.9 -    free_xenheap_page((unsigned long)d->mm.perdomain_pt);
   11.10 -}
   11.11 +extern void free_perdomain_pt(struct domain *d);
   11.12  
   11.13  extern void domain_relinquish_memory(struct domain *d);
   11.14  
    12.1 --- a/xen/include/asm-x86/mm.h	Tue Jul 27 14:55:17 2004 +0000
    12.2 +++ b/xen/include/asm-x86/mm.h	Tue Jul 27 19:37:36 2004 +0000
    12.3 @@ -97,13 +97,13 @@ struct pfn_info
    12.4  
    12.5  #define SHARE_PFN_WITH_DOMAIN(_pfn, _dom)                                   \
    12.6      do {                                                                    \
    12.7 -        (_pfn)->u.inuse.domain = (_dom);                                          \
    12.8 +        (_pfn)->u.inuse.domain = (_dom);                                    \
    12.9          /* The incremented type count is intended to pin to 'writeable'. */ \
   12.10 -        (_pfn)->u.inuse.type_info  = PGT_writeable_page | PGT_validated | 1;   \
   12.11 +        (_pfn)->u.inuse.type_info  = PGT_writeable_page | PGT_validated | 1;\
   12.12          wmb(); /* install valid domain ptr before updating refcnt. */       \
   12.13          spin_lock(&(_dom)->page_alloc_lock);                                \
   12.14          /* _dom holds an allocation reference */                            \
   12.15 -        (_pfn)->u.inuse.count_info = PGC_allocated | 1;                        \
   12.16 +        (_pfn)->u.inuse.count_info = PGC_allocated | 1;                     \
   12.17          if ( unlikely((_dom)->xenheap_pages++ == 0) )                       \
   12.18              get_domain(_dom);                                               \
   12.19          spin_unlock(&(_dom)->page_alloc_lock);                              \
   12.20 @@ -111,14 +111,10 @@ struct pfn_info
   12.21  
   12.22  extern struct pfn_info *frame_table;
   12.23  extern unsigned long frame_table_size;
   12.24 -extern struct list_head free_list;
   12.25 -extern spinlock_t free_list_lock;
   12.26 -extern unsigned int free_pfns;
   12.27  extern unsigned long max_page;
   12.28  void init_frametable(void *frametable_vstart, unsigned long nr_pages);
   12.29 -void add_to_domain_alloc_list(unsigned long ps, unsigned long pe);
   12.30  
   12.31 -struct pfn_info *alloc_domain_page(struct domain *p);
   12.32 +struct pfn_info *alloc_domain_page(struct domain *d);
   12.33  void free_domain_page(struct pfn_info *page);
   12.34  
   12.35  int alloc_page_type(struct pfn_info *page, unsigned int type);
   12.36 @@ -287,10 +283,10 @@ static inline int get_page_and_type(stru
   12.37      return rc;
   12.38  }
   12.39  
   12.40 -#define ASSERT_PAGE_IS_TYPE(_p, _t)                \
   12.41 -    ASSERT(((_p)->u.inuse.type_info & PGT_type_mask) == (_t));  \
   12.42 +#define ASSERT_PAGE_IS_TYPE(_p, _t)                            \
   12.43 +    ASSERT(((_p)->u.inuse.type_info & PGT_type_mask) == (_t)); \
   12.44      ASSERT(((_p)->u.inuse.type_info & PGT_count_mask) != 0)
   12.45 -#define ASSERT_PAGE_IS_DOMAIN(_p, _d)              \
   12.46 +#define ASSERT_PAGE_IS_DOMAIN(_p, _d)                          \
   12.47      ASSERT(((_p)->u.inuse.count_info & PGC_count_mask) != 0);  \
   12.48      ASSERT((_p)->u.inuse.domain == (_d))
   12.49  
    13.1 --- a/xen/include/asm-x86/page.h	Tue Jul 27 14:55:17 2004 +0000
    13.2 +++ b/xen/include/asm-x86/page.h	Tue Jul 27 19:37:36 2004 +0000
    13.3 @@ -102,6 +102,7 @@ typedef struct { unsigned long pt_lo; } 
    13.4  #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
    13.5  #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
    13.6  #define page_address(_p)        (__va(((_p) - frame_table) << PAGE_SHIFT))
    13.7 +#define phys_to_page(kaddr)     (frame_table + ((kaddr) >> PAGE_SHIFT))
    13.8  #define virt_to_page(kaddr)	(frame_table + (__pa(kaddr) >> PAGE_SHIFT))
    13.9  #define VALID_PAGE(page)	((page - frame_table) < max_mapnr)
   13.10  
    14.1 --- a/xen/include/xen/mm.h	Tue Jul 27 14:55:17 2004 +0000
    14.2 +++ b/xen/include/xen/mm.h	Tue Jul 27 19:37:36 2004 +0000
    14.3 @@ -2,13 +2,28 @@
    14.4  #ifndef __XEN_MM_H__
    14.5  #define __XEN_MM_H__
    14.6  
    14.7 -/* page_alloc.c */
    14.8 -void init_page_allocator(unsigned long min, unsigned long max);
    14.9 +#include <asm/mm.h>
   14.10 +
   14.11 +/* Generic allocator */
   14.12 +unsigned long init_heap_allocator(
   14.13 +    unsigned long bitmap_start, unsigned long max_pages);
   14.14 +void init_heap_pages(int zone, struct pfn_info *pg, unsigned long nr_pages);
   14.15 +struct pfn_info *alloc_heap_pages(int zone, int order);
   14.16 +void free_heap_pages(int zone, struct pfn_info *pg, int order);
   14.17 +
   14.18 +/* Xen suballocator */
   14.19 +void init_xenheap_pages(unsigned long ps, unsigned long pe);
   14.20  unsigned long alloc_xenheap_pages(int order);
   14.21  void free_xenheap_pages(unsigned long p, int order);
   14.22  #define alloc_xenheap_page() (alloc_xenheap_pages(0))
   14.23  #define free_xenheap_page(_p) (free_xenheap_pages(_p,0))
   14.24  
   14.25 -#include <asm/mm.h>
   14.26 +/* Domain suballocator */
   14.27 +void init_domheap_pages(unsigned long ps, unsigned long pe);
   14.28 +struct pfn_info *alloc_domheap_pages(int order);
   14.29 +void free_domheap_pages(struct pfn_info *pg, int order);
   14.30 +unsigned long avail_domheap_pages(void);
   14.31 +#define alloc_domheap_page() (alloc_domheap_pages(0))
   14.32 +#define free_domheap_page(_p) (free_domheap_pages(_p,0))
   14.33  
   14.34  #endif /* __XEN_MM_H__ */