# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1160964212 -32400 # Node ID 94f013f5032b59553445532160143d4238fafc93 # Parent 6bf2a43d253f615beff16d2f2329c44d3099c664 fix dom0 builder so that xen doesn't assign memory on I/O area. TODO: the meaning of the xen boot option, dom0_mem, is changed. dom0 memory is populated in the intersection of [baremetal conventional memory] and [0, dom0_mem). Consequently if baremetal memory is sparsely populated, the total memory assigned to dom0 might be much less than dom0_mem. PATCHNAME: fix_dom0_builder Signed-off-by: Isaku Yamahata diff -r 6bf2a43d253f -r 94f013f5032b xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Mon Oct 16 10:54:00 2006 +0900 +++ b/xen/arch/ia64/xen/dom_fw.c Mon Oct 16 11:03:32 2006 +0900 @@ -486,6 +486,49 @@ struct fw_tables { #define FW_FIELD_MPA(field) \ FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field) +static int +clip_dom0_mem(unsigned long* start, unsigned long* end) +{ + void *efi_map_start, *efi_map_end; + u64 efi_desc_size; + void *p; + + efi_map_start = __va(ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; + BUG_ON(*start > *end); + + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + efi_memory_desc_t *md = p; + unsigned long md_start = md->phys_addr; + unsigned long md_end = + md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); + + if (md_end <= *start) + continue; + if (*end < md_start) { + *end = md_start; + return -ENOENT; + } + + if (md->type != EFI_CONVENTIONAL_MEMORY || + !(md->attribute & EFI_MEMORY_WB)) + continue; + + if (*start < md_start) + *start = md->phys_addr; + if (md_end < *end) + *end = md_end; + if (*end <= *start) { + *end = *start; + return -ENOENT; + } + return 0; + } + *end = ~0UL; + return -ENOENT; +} + /* Complete the dom0 memmap. */ static int complete_dom0_memmap(struct domain *d, @@ -588,6 +631,7 @@ complete_dom0_memmap(struct domain *d, for (j = 0; j < num_mds; j++) { unsigned long end; unsigned long next_start; + unsigned long mem_start; md = &tables->efi_memmap[j]; end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); @@ -622,9 +666,28 @@ complete_dom0_memmap(struct domain *d, /* No room for memory. */ if (end >= next_start) continue; - - MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - end, next_start); + + // dom0 needs to see all I/O devices and wants to + // see them at the address where mpaddr = machine physaddr. + // However EFI doesn't cover all I/O area. + // e.g. PCI brige might not be covered. + // So we must be carefull not to use resions used for I/O by + // populating only in real machine's conventional memory + // region. + mem_start = end; + while (mem_start < next_start) { + unsigned long mem_end = next_start; + int error; + unsigned long next_mem_start; + + error = clip_dom0_mem(&mem_start, &mem_end); + next_mem_start = mem_end; + if (error == 0 && mem_start < mem_end) { + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + mem_start, mem_end); + } + mem_start = next_mem_start; + } if (next_start >= maxmem) break;