# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1188381736 -32400 # Node ID 97c0b1a793162f39251183672b7b057386772aa8 # Parent a630c1ba002b8ecbafd50691c90ca96f3a45dc3e Optimize xc_core.c implementation. optimize out unnecessary map/unmap foreign domain page by moving p2m/pfn talbe after pages array. This patch doesn't change the xm dump-core format. PATCHNAME: xc_core_c_optimize Signed-off-by: Isaku Yamahata diff -r a630c1ba002b -r 97c0b1a79316 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Tue Aug 28 13:11:51 2007 +0900 +++ b/tools/libxc/xc_core.c Wed Aug 29 19:02:16 2007 +0900 @@ -17,8 +17,8 @@ * | .xen_prstatus | * | .xen_ia64_mmapped_regs if ia64 | * | .xen_shared_info if present | + * | .xen_pages | * | .xen_p2m or .xen_pfn | - * | .xen_pages | * +--------------------------------------------------------+ * |.note.Xen:note section | * | "Xen" is used as note name, | @@ -37,12 +37,12 @@ * +--------------------------------------------------------+ * |.xen_shared_info if possible | * +--------------------------------------------------------+ + * |.xen_pages | + * | page * nr_pages | + * +--------------------------------------------------------+ * |.xen_p2m or .xen_pfn | * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] | * | .xen_pfn: uint64_t[nr_pages] | - * +--------------------------------------------------------+ - * |.xen_pages | - * | page * nr_pages | * +--------------------------------------------------------+ * |.shstrtab: section header string table | * +--------------------------------------------------------+ @@ -57,21 +57,6 @@ /* number of pages to write at a time */ #define DUMP_INCREMENT (4 * 1024) - -static int -copy_from_domain_page(int xc_handle, - uint32_t domid, - unsigned long mfn, - void *dst_page) -{ - void *vaddr = xc_map_foreign_range( - xc_handle, domid, PAGE_SIZE, PROT_READ, mfn); - if ( vaddr == NULL ) - return -1; - memcpy(dst_page, vaddr, PAGE_SIZE); - munmap(vaddr, PAGE_SIZE); - return 0; -} /* string table */ struct xc_core_strtab { @@ -520,47 +505,6 @@ xc_domain_dumpcore_via_callback(int xc_h } } - /* create .xen_p2m or .xen_pfn */ - j = 0; - for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ ) - { - uint64_t pfn_start; - uint64_t pfn_end; - - pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT; - pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT); - for ( i = pfn_start; i < pfn_end; i++ ) - { - if ( !auto_translated_physmap ) - { - if ( p2m[i] == INVALID_P2M_ENTRY ) - continue; - p2m_array[j].pfn = i; - p2m_array[j].gmfn = p2m[i]; - } - else - { - /* try to map page to determin wheter it has underlying page */ - void *vaddr = xc_map_foreign_range(xc_handle, domid, - PAGE_SIZE, PROT_READ, i); - if ( vaddr == NULL ) - continue; - munmap(vaddr, PAGE_SIZE); - pfn_array[j] = i; - } - - j++; - } - } - if ( j != nr_pages ) - { - PERROR("j (%ld) != nr_pages (%ld)", j , nr_pages); - /* When live dump-mode (-L option) is specified, - * guest domain may change its mapping. - */ - nr_pages = j; - } - /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/ xc_core_ehdr_init(&ehdr); @@ -660,48 +604,12 @@ xc_domain_dumpcore_via_callback(int xc_h offset += filesz; } - /* p2m/pfn table */ - shdr = xc_core_shdr_get(sheaders); - if ( shdr == NULL ) - { - PERROR("Could not get section header for .xen_{p2m, pfn} table"); - goto out; - } - if ( !auto_translated_physmap ) - { - filesz = nr_pages * sizeof(p2m_array[0]); - sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M, - SHT_PROGBITS, - offset, filesz, __alignof__(p2m_array[0]), - sizeof(p2m_array[0])); - if ( sts != 0 ) - goto out; - } - else - { - filesz = nr_pages * sizeof(pfn_array[0]); - sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN, - SHT_PROGBITS, - offset, filesz, __alignof__(pfn_array[0]), - sizeof(pfn_array[0])); - if ( sts != 0 ) - goto out; - } - offset += filesz; - - /* pages */ - shdr = xc_core_shdr_get(sheaders); - if ( shdr == NULL ) - { - PERROR("could not get section headers for .xen_pages"); - goto out; - } - /* - * pages are the last section to allocate section headers + * pages and p2m/pfn are the last section to allocate section headers * so that we know the number of section headers here. + * 2 = pages section and p2m/pfn table section */ - fixup = sheaders->num * sizeof(*shdr); + fixup = (sheaders->num + 2) * sizeof(*shdr); /* zeroth section should have zero offset */ for ( i = 1; i < sheaders->num; i++ ) sheaders->shdrs[i].sh_offset += fixup; @@ -709,9 +617,43 @@ xc_domain_dumpcore_via_callback(int xc_h dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */ offset += dummy_len; + /* pages */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("could not get section headers for .xen_pages"); + goto out; + } filesz = nr_pages * PAGE_SIZE; sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS, offset, filesz, PAGE_SIZE, PAGE_SIZE); + if ( sts != 0 ) + goto out; + offset += filesz; + + /* p2m/pfn table */ + shdr = xc_core_shdr_get(sheaders); + if ( shdr == NULL ) + { + PERROR("Could not get section header for .xen_{p2m, pfn} table"); + goto out; + } + if ( !auto_translated_physmap ) + { + filesz = nr_pages * sizeof(p2m_array[0]); + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M, + SHT_PROGBITS, + offset, filesz, __alignof__(p2m_array[0]), + sizeof(p2m_array[0])); + } + else + { + filesz = nr_pages * sizeof(pfn_array[0]); + sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN, + SHT_PROGBITS, + offset, filesz, __alignof__(pfn_array[0]), + sizeof(pfn_array[0])); + } if ( sts != 0 ) goto out; offset += filesz; @@ -736,7 +678,7 @@ xc_domain_dumpcore_via_callback(int xc_h /* elf note section: xen core header */ sts = elfnote_dump_none(args, dump_rtn); - if ( sts != 0) + if ( sts != 0 ) goto out; /* elf note section: xen core header */ @@ -772,16 +714,6 @@ xc_domain_dumpcore_via_callback(int xc_h if ( sts != 0 ) goto out; - /* p2m/pfn table: .xen_p2m/.xen_pfn */ - if ( !auto_translated_physmap ) - sts = dump_rtn(args, (char *)p2m_array, - sizeof(p2m_array[0]) * nr_pages); - else - sts = dump_rtn(args, (char *)pfn_array, - sizeof(pfn_array[0]) * nr_pages); - if ( sts != 0 ) - goto out; - /* Pad the output data to page alignment. */ memset(dummy, 0, PAGE_SIZE); sts = dump_rtn(args, dummy, dummy_len); @@ -789,24 +721,99 @@ xc_domain_dumpcore_via_callback(int xc_h goto out; /* dump pages: .xen_pages */ - for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ ) - { - uint64_t gmfn; - if ( !auto_translated_physmap ) - gmfn = p2m_array[i].gmfn; - else - gmfn = pfn_array[i]; - - copy_from_domain_page(xc_handle, domid, gmfn, dump_mem); - dump_mem += PAGE_SIZE; - if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) ) + j = 0; + dump_mem = dump_mem_start; + for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ ) + { + uint64_t pfn_start; + uint64_t pfn_end; + + pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT; + pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT); + for ( i = pfn_start; i < pfn_end; i++ ) { - sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start); + uint64_t gmfn; + void *vaddr; + + if ( j >= nr_pages ) + { + /* + * When live dump-mode (-L option) is specified, + * guest domain may increase memory. + */ + IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages); + goto copy_done; + } + + if ( !auto_translated_physmap ) + { + gmfn = p2m[i]; + if ( gmfn == INVALID_P2M_ENTRY ) + continue; + + p2m_array[j].pfn = i; + p2m_array[j].gmfn = gmfn; + } + else + { + gmfn = i; + pfn_array[j] = i; + } + + vaddr = xc_map_foreign_range( + xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn); + if ( vaddr == NULL ) + continue; + memcpy(dump_mem, vaddr, PAGE_SIZE); + munmap(vaddr, PAGE_SIZE); + dump_mem += PAGE_SIZE; + if ( (j + 1) % DUMP_INCREMENT == 0 ) + { + sts = dump_rtn( + args, dump_mem_start, dump_mem - dump_mem_start); + if ( sts != 0 ) + goto out; + dump_mem = dump_mem_start; + } + + j++; + } + } + +copy_done: + sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start); + if ( sts != 0 ) + goto out; + if ( j < nr_pages ) + { + /* When live dump-mode (-L option) is specified, + * guest domain may reduce memory. pad with zero pages. + */ + IPRINTF("j (%ld) != nr_pages (%ld)", j , nr_pages); + memset(dump_mem_start, 0, PAGE_SIZE); + for (; j < nr_pages; j++) { + sts = dump_rtn(args, dump_mem_start, PAGE_SIZE); if ( sts != 0 ) goto out; - dump_mem = dump_mem_start; - } - } + if ( !auto_translated_physmap ) + { + p2m_array[j].pfn = XC_CORE_INVALID_PFN; + p2m_array[j].gmfn = XC_CORE_INVALID_GMFN; + } + else + pfn_array[j] = XC_CORE_INVALID_PFN; + } + } + + /* p2m/pfn table: .xen_p2m/.xen_pfn */ + if ( !auto_translated_physmap ) + sts = dump_rtn( + args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages); + else + sts = dump_rtn( + args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages); + if ( sts != 0 ) + goto out; /* elf section header string table: .shstrtab */ sts = dump_rtn(args, strtab->strings, strtab->current); @@ -816,6 +823,8 @@ xc_domain_dumpcore_via_callback(int xc_h sts = 0; out: + if ( memory_map != NULL ) + free(memory_map); if ( p2m != NULL ) munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES); if ( p2m_array != NULL ) diff -r a630c1ba002b -r 97c0b1a79316 tools/libxc/xc_core.h --- a/tools/libxc/xc_core.h Tue Aug 28 13:11:51 2007 +0900 +++ b/tools/libxc/xc_core.h Wed Aug 29 19:02:16 2007 +0900 @@ -107,6 +107,8 @@ struct xen_dumpcore_elfnote_format_versi struct xen_dumpcore_elfnote_format_version_desc format_version; }; +#define XC_CORE_INVALID_PFN (~(uint64_t)0) +#define XC_CORE_INVALID_GMFN (~(uint64_t)0) struct xen_dumpcore_p2m { uint64_t pfn; uint64_t gmfn;