ia64/xen-unstable

changeset 8402:47d947e07205

Work around a nasty BIOS/GRUB bug which causes fields in
the e820 map to not be initialized to zero when they should be.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Dec 16 04:11:41 2005 +0100 (2005-12-16)
parents 8ebcbcda3d37
children 3dc1c23dd508
files xen/arch/x86/setup.c
line diff
     1.1 --- a/xen/arch/x86/setup.c	Thu Dec 15 16:17:13 2005 -0700
     1.2 +++ b/xen/arch/x86/setup.c	Fri Dec 16 04:11:41 2005 +0100
     1.3 @@ -264,7 +264,7 @@ void __init __start_xen(multiboot_info_t
     1.4      unsigned long _initrd_start = 0, _initrd_len = 0;
     1.5      unsigned int initrdidx = 1;
     1.6      physaddr_t s, e;
     1.7 -    int i, e820_raw_nr = 0, bytes = 0;
     1.8 +    int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
     1.9      struct ns16550_defaults ns16550 = {
    1.10          .data_bits = 8,
    1.11          .parity    = 'n',
    1.12 @@ -313,6 +313,26 @@ void __init __start_xen(multiboot_info_t
    1.13          while ( bytes < mbi->mmap_length )
    1.14          {
    1.15              memory_map_t *map = __va(mbi->mmap_addr + bytes);
    1.16 +
    1.17 +            /*
    1.18 +             * This is a gross workaround for a BIOS/GRUB bug. GRUB does
    1.19 +             * not write e820 map entries into pre-zeroed memory. This is
    1.20 +             * okay if the BIOS fills in all fields of the map entry, but
    1.21 +             * some broken BIOSes do not bother to write the high word of
    1.22 +             * the length field if the length is smaller than 4GB. We
    1.23 +             * detect and fix this by flagging sections below 4GB that
    1.24 +             * appear to be larger than 4GB in size. We disable this check
    1.25 +             * for mbootpack and syslinux (which we can detect because they
    1.26 +             * place the mmap_addr list above 1MB in memory).
    1.27 +             */
    1.28 +            if ( (mbi->mmap_addr < 0x100000) &&
    1.29 +                 (map->base_addr_high == 0) &&
    1.30 +                 (map->length_high != 0) )
    1.31 +            {
    1.32 +                e820_warn = 1;
    1.33 +                map->length_high = 0;
    1.34 +            }
    1.35 +
    1.36              e820_raw[e820_raw_nr].addr = 
    1.37                  ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
    1.38              e820_raw[e820_raw_nr].size = 
    1.39 @@ -320,6 +340,7 @@ void __init __start_xen(multiboot_info_t
    1.40              e820_raw[e820_raw_nr].type = 
    1.41                  (map->type > E820_SHARED_PAGE) ? E820_RESERVED : map->type;
    1.42              e820_raw_nr++;
    1.43 +
    1.44              bytes += map->size + 4;
    1.45          }
    1.46      }
    1.47 @@ -339,6 +360,10 @@ void __init __start_xen(multiboot_info_t
    1.48          for ( ; ; ) ;
    1.49      }
    1.50  
    1.51 +    if ( e820_warn )
    1.52 +        printk("WARNING: Buggy e820 map detected and fixed "
    1.53 +               "(truncated length fields).\n");
    1.54 +
    1.55      max_page = init_e820(e820_raw, &e820_raw_nr);
    1.56  
    1.57      modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;