# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1160120293 -32400 # Node ID a562ca4f96299cac97df6dc431fde4d2a23069a7 # Parent 16e6a40851945ec162e2846fc3862ad5c4d5c910 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 16e6a4085194 -r a562ca4f9629 xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Fri Oct 06 16:31:18 2006 +0900 +++ b/xen/arch/ia64/xen/dom_fw.c Fri Oct 06 16:38:13 2006 +0900 @@ -486,7 +486,54 @@ 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. */ +extern unsigned long dom0_align; static int complete_dom0_memmap(struct domain *d, struct fw_tables *tables, @@ -588,6 +635,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 +670,30 @@ 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 = real 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 I/O address by + // populating only in real machine's conventional memory + // region. + mem_start = end; + while (mem_start + dom0_align < 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; + mem_start = ALIGN_UP(mem_start, dom0_align); + mem_end = ALIGN_DOWN(mem_end, dom0_align); + if (error == 0 && mem_start < mem_end - dom0_align) { + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + mem_start, mem_end); + } + mem_start = next_mem_start; + } if (next_start >= maxmem) break; diff -r 16e6a4085194 -r a562ca4f9629 xen/include/asm-ia64/config.h --- a/xen/include/asm-ia64/config.h Fri Oct 06 16:31:18 2006 +0900 +++ b/xen/include/asm-ia64/config.h Fri Oct 06 16:38:13 2006 +0900 @@ -55,6 +55,11 @@ typedef unsigned long paddr_t; typedef unsigned long paddr_t; // from include/linux/kernel.h #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + +// from asm-powerpc/config.h +/* align addr on a size boundary - adjust address up/down if needed */ +#define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) +#define ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) //////////////////////////////////////