ia64/xen-unstable

changeset 16791:4fbde3a39909

[IA64] Improve boot loader data moving logic in start_kernel()

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Thu Jan 17 12:05:43 2008 -0700 (2008-01-17)
parents bba0419a05f1
children 8977f087351a
files xen/arch/ia64/xen/xensetup.c
line diff
     1.1 --- a/xen/arch/ia64/xen/xensetup.c	Thu Jan 17 12:05:43 2008 -0700
     1.2 +++ b/xen/arch/ia64/xen/xensetup.c	Thu Jan 17 12:05:43 2008 -0700
     1.3 @@ -77,7 +77,7 @@ void *xen_pickle_offset __read_mostly;
     1.4  
     1.5  static void __init parse_xenheap_megabytes(char *s)
     1.6  {
     1.7 -    unsigned long megabytes = parse_size_and_unit(s, NULL);
     1.8 +    unsigned long megabytes = simple_strtoll(s, NULL, 0);
     1.9  
    1.10  #define XENHEAP_MEGABYTES_MIN   16
    1.11      if (megabytes < XENHEAP_MEGABYTES_MIN)
    1.12 @@ -241,12 +241,21 @@ is_xenheap_usable_memory(efi_memory_desc
    1.13  }
    1.14  
    1.15  static inline int __init
    1.16 -md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
    1.17 +md_overlaps(const efi_memory_desc_t *md, unsigned long phys_addr)
    1.18  {
    1.19      return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
    1.20  }
    1.21  
    1.22 +static inline int __init
    1.23 +md_overlap_with_boot_param(const efi_memory_desc_t *md)
    1.24 +{
    1.25 +    return md_overlaps(md, __pa(ia64_boot_param)) ||
    1.26 +        md_overlaps(md, ia64_boot_param->efi_memmap) ||
    1.27 +        md_overlaps(md, ia64_boot_param->command_line);
    1.28 +}
    1.29 +
    1.30  #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
    1.31 +#define MD_END(md) ((md)->phys_addr + ((md)->num_pages << EFI_PAGE_SHIFT))
    1.32  
    1.33  extern char __init_begin[], __init_end[];
    1.34  static void noinline init_done(void)
    1.35 @@ -366,27 +375,34 @@ void __init start_kernel(void)
    1.36      while (relo_start + relo_size >= md_end) {
    1.37          md = efi_get_md(md_end);
    1.38  
    1.39 -        BUG_ON(!md);
    1.40 -        BUG_ON(!is_xenheap_usable_memory(md));
    1.41 +        if (md == NULL) {
    1.42 +            printk("no room to move loader data. skip moving loader data\n");
    1.43 +            goto skip_move;
    1.44 +        }
    1.45 +        
    1.46 +        md_end = MD_END(md);
    1.47 +        if (relo_start < md->phys_addr)
    1.48 +            relo_start = md->phys_addr;
    1.49 +        
    1.50 +        if (!is_xenheap_usable_memory(md))
    1.51 +            continue;
    1.52  
    1.53 -        md_end = md->phys_addr + MD_SIZE(md);
    1.54          /*
    1.55           * The dom0 kernel or initrd could overlap, reserve space
    1.56           * at the end to relocate them later.
    1.57           */
    1.58          if (md->type == EFI_LOADER_DATA) {
    1.59              /* Test for ranges we're not prepared to move */
    1.60 -            BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) ||
    1.61 -                   md_overlaps(md, ia64_boot_param->efi_memmap) ||
    1.62 -                   md_overlaps(md, ia64_boot_param->command_line));
    1.63 +            if (!md_overlap_with_boot_param(md))
    1.64 +                relo_size += MD_SIZE(md);
    1.65  
    1.66 -            relo_size += MD_SIZE(md);
    1.67              /* If range overlaps the end, push out the relocation start */
    1.68              if (md_end > relo_start)
    1.69                  relo_start = md_end;
    1.70          }
    1.71      }
    1.72      last_md = md;
    1.73 +    relo_start = md_end - relo_size;
    1.74      relo_end = relo_start + relo_size;
    1.75  
    1.76      md_end = __pa(ia64_imva(&_end));
    1.77 @@ -397,9 +413,9 @@ void __init start_kernel(void)
    1.78       * and set to zero pages.
    1.79       */
    1.80      for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
    1.81 -        md_end = md->phys_addr + MD_SIZE(md);
    1.82 +        md_end = MD_END(md);
    1.83  
    1.84 -        if (md->type == EFI_LOADER_DATA) {
    1.85 +        if (md->type == EFI_LOADER_DATA && !md_overlap_with_boot_param(md)) {
    1.86              unsigned long relo_offset;
    1.87  
    1.88              if (md_overlaps(md, ia64_boot_param->domain_start)) {
    1.89 @@ -421,27 +437,14 @@ void __init start_kernel(void)
    1.90              relo_start += MD_SIZE(md);
    1.91          }
    1.92  
    1.93 -        if (md == kern_md)
    1.94 -            continue;
    1.95          if (md == last_md)
    1.96              break;
    1.97 -
    1.98 -        md->phys_addr = relo_end;
    1.99 -        md->num_pages = 0;
   1.100      }
   1.101  
   1.102      /* Trim the last entry */
   1.103 -    md->phys_addr = relo_end;
   1.104 -    md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT;
   1.105 +    md->num_pages -= (relo_size >> EFI_PAGE_SHIFT);
   1.106  
   1.107 -    /*
   1.108 -     * Expand the new kernel/xenheap (and maybe dom0/initrd) out to
   1.109 -     * the full size.  This range will already be type EFI_LOADER_DATA,
   1.110 -     * therefore the xenheap area is now protected being allocated for
   1.111 -     * use by find_memmap_space() in efi.c
   1.112 -     */
   1.113 -    kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT;
   1.114 -
   1.115 +skip_move:
   1.116      reserve_memory();
   1.117  
   1.118      /* first find highest page frame number */
   1.119 @@ -485,10 +488,21 @@ void __init start_kernel(void)
   1.120      if (vmx_enabled)
   1.121          xen_heap_start = vmx_init_env(xen_heap_start, xenheap_phys_end);
   1.122  
   1.123 -    init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end);
   1.124 +    md_end = __pa(xen_heap_start);
   1.125 +    for (md = efi_get_md(md_end);
   1.126 +         md != NULL && md->phys_addr < xenheap_phys_end;
   1.127 +         md = efi_get_md(md_end)) {
   1.128 +        md_end = MD_END(md);
   1.129 +
   1.130 +        if (md == kern_md ||
   1.131 +            (md->type == EFI_LOADER_DATA && !md_overlap_with_boot_param(md)) ||
   1.132 +            (md->attribute & EFI_MEMORY_WB))
   1.133 +            init_xenheap_pages(max(__pa(xen_heap_start), md->phys_addr),
   1.134 +                               min(md_end, xenheap_phys_end));
   1.135 +    }
   1.136      printk("Xen heap: %luMB (%lukB)\n",
   1.137 -	(xenheap_phys_end-__pa(xen_heap_start)) >> 20,
   1.138 -	(xenheap_phys_end-__pa(xen_heap_start)) >> 10);
   1.139 +           (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
   1.140 +           (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
   1.141  
   1.142      end_boot_allocator();
   1.143