ia64/xen-unstable

changeset 15801:df860912f348

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.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author kfraser@localhost.localdomain
date Thu Aug 30 14:58:40 2007 +0100 (2007-08-30)
parents 104aba61893e
children 263fc122f62b
files tools/libxc/xc_core.c tools/libxc/xc_core.h
line diff
     1.1 --- a/tools/libxc/xc_core.c	Thu Aug 30 14:57:24 2007 +0100
     1.2 +++ b/tools/libxc/xc_core.c	Thu Aug 30 14:58:40 2007 +0100
     1.3 @@ -17,8 +17,8 @@
     1.4   *  |    .xen_prstatus                                       |
     1.5   *  |    .xen_ia64_mmapped_regs if ia64                      |
     1.6   *  |    .xen_shared_info if present                         |
     1.7 + *  |    .xen_pages                                          |
     1.8   *  |    .xen_p2m or .xen_pfn                                |
     1.9 - *  |    .xen_pages                                          |
    1.10   *  +--------------------------------------------------------+
    1.11   *  |.note.Xen:note section                                  |
    1.12   *  |    "Xen" is used as note name,                         |
    1.13 @@ -37,13 +37,13 @@
    1.14   *  +--------------------------------------------------------+
    1.15   *  |.xen_shared_info if possible                            |
    1.16   *  +--------------------------------------------------------+
    1.17 + *  |.xen_pages                                              |
    1.18 + *  |    page * nr_pages                                     |
    1.19 + *  +--------------------------------------------------------+
    1.20   *  |.xen_p2m or .xen_pfn                                    |
    1.21   *  |    .xen_p2m: struct xen_dumpcore_p2m[nr_pages]         |
    1.22   *  |    .xen_pfn: uint64_t[nr_pages]                        |
    1.23   *  +--------------------------------------------------------+
    1.24 - *  |.xen_pages                                              |
    1.25 - *  |    page * nr_pages                                     |
    1.26 - *  +--------------------------------------------------------+
    1.27   *  |.shstrtab: section header string table                  |
    1.28   *  +--------------------------------------------------------+
    1.29   *
    1.30 @@ -58,21 +58,6 @@
    1.31  /* number of pages to write at a time */
    1.32  #define DUMP_INCREMENT (4 * 1024)
    1.33  
    1.34 -static int
    1.35 -copy_from_domain_page(int xc_handle,
    1.36 -                      uint32_t domid,
    1.37 -                      unsigned long mfn,
    1.38 -                      void *dst_page)
    1.39 -{
    1.40 -    void *vaddr = xc_map_foreign_range(
    1.41 -        xc_handle, domid, PAGE_SIZE, PROT_READ, mfn);
    1.42 -    if ( vaddr == NULL )
    1.43 -        return -1;
    1.44 -    memcpy(dst_page, vaddr, PAGE_SIZE);
    1.45 -    munmap(vaddr, PAGE_SIZE);
    1.46 -    return 0;
    1.47 -}
    1.48 -
    1.49  /* string table */
    1.50  struct xc_core_strtab {
    1.51      char       *strings;
    1.52 @@ -520,47 +505,6 @@ xc_domain_dumpcore_via_callback(int xc_h
    1.53          }
    1.54      }
    1.55  
    1.56 -    /* create .xen_p2m or .xen_pfn */
    1.57 -    j = 0;
    1.58 -    for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
    1.59 -    {
    1.60 -        uint64_t pfn_start;
    1.61 -        uint64_t pfn_end;
    1.62 -
    1.63 -        pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
    1.64 -        pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
    1.65 -        for ( i = pfn_start; i < pfn_end; i++ )
    1.66 -        {
    1.67 -            if ( !auto_translated_physmap )
    1.68 -            {
    1.69 -                if ( p2m[i] == INVALID_P2M_ENTRY )
    1.70 -                    continue;
    1.71 -                p2m_array[j].pfn = i;
    1.72 -                p2m_array[j].gmfn = p2m[i];
    1.73 -            }
    1.74 -            else
    1.75 -            {
    1.76 -                /* try to map page to determin wheter it has underlying page */
    1.77 -                void *vaddr = xc_map_foreign_range(xc_handle, domid,
    1.78 -                                                   PAGE_SIZE, PROT_READ, i);
    1.79 -                if ( vaddr == NULL )
    1.80 -                    continue;
    1.81 -                munmap(vaddr, PAGE_SIZE);
    1.82 -                pfn_array[j] = i;
    1.83 -            }
    1.84 -
    1.85 -            j++;
    1.86 -        }
    1.87 -    }
    1.88 -    if ( j != nr_pages )
    1.89 -    {
    1.90 -        PERROR("j (%ld) != nr_pages (%ld)", j , nr_pages);
    1.91 -        /* When live dump-mode (-L option) is specified,
    1.92 -         * guest domain may change its mapping.
    1.93 -         */
    1.94 -        nr_pages = j;
    1.95 -    }
    1.96 -
    1.97      /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
    1.98      xc_core_ehdr_init(&ehdr);
    1.99  
   1.100 @@ -660,6 +604,33 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.101          offset += filesz;
   1.102      }
   1.103  
   1.104 +    /*
   1.105 +     * pages and p2m/pfn are the last section to allocate section headers
   1.106 +     * so that we know the number of section headers here.
   1.107 +     * 2 = pages section and p2m/pfn table section
   1.108 +     */
   1.109 +    fixup = (sheaders->num + 2) * sizeof(*shdr);
   1.110 +    /* zeroth section should have zero offset */
   1.111 +    for ( i = 1; i < sheaders->num; i++ )
   1.112 +        sheaders->shdrs[i].sh_offset += fixup;
   1.113 +    offset += fixup;
   1.114 +    dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
   1.115 +    offset += dummy_len;
   1.116 +
   1.117 +    /* pages */
   1.118 +    shdr = xc_core_shdr_get(sheaders);
   1.119 +    if ( shdr == NULL )
   1.120 +    {
   1.121 +        PERROR("could not get section headers for .xen_pages");
   1.122 +        goto out;
   1.123 +    }
   1.124 +    filesz = nr_pages * PAGE_SIZE;
   1.125 +    sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
   1.126 +                           offset, filesz, PAGE_SIZE, PAGE_SIZE);
   1.127 +    if ( sts != 0 )
   1.128 +        goto out;
   1.129 +    offset += filesz;
   1.130 +
   1.131      /* p2m/pfn table */
   1.132      shdr = xc_core_shdr_get(sheaders);
   1.133      if ( shdr == NULL )
   1.134 @@ -674,8 +645,6 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.135                                 SHT_PROGBITS,
   1.136                                 offset, filesz, __alignof__(p2m_array[0]),
   1.137                                 sizeof(p2m_array[0]));
   1.138 -        if ( sts != 0 )
   1.139 -            goto out;
   1.140      }
   1.141      else
   1.142      {
   1.143 @@ -684,34 +653,7 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.144                                 SHT_PROGBITS,
   1.145                                 offset, filesz, __alignof__(pfn_array[0]),
   1.146                                 sizeof(pfn_array[0]));
   1.147 -        if ( sts != 0 )
   1.148 -            goto out;
   1.149 -    }
   1.150 -    offset += filesz;
   1.151 -
   1.152 -    /* pages */
   1.153 -    shdr = xc_core_shdr_get(sheaders);
   1.154 -    if ( shdr == NULL )
   1.155 -    {
   1.156 -        PERROR("could not get section headers for .xen_pages");
   1.157 -        goto out;
   1.158      }
   1.159 -
   1.160 -    /*
   1.161 -     * pages are the last section to allocate section headers
   1.162 -     * so that we know the number of section headers here.
   1.163 -     */
   1.164 -    fixup = sheaders->num * sizeof(*shdr);
   1.165 -    /* zeroth section should have zero offset */
   1.166 -    for ( i = 1; i < sheaders->num; i++ )
   1.167 -        sheaders->shdrs[i].sh_offset += fixup;
   1.168 -    offset += fixup;
   1.169 -    dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
   1.170 -    offset += dummy_len;
   1.171 -
   1.172 -    filesz = nr_pages * PAGE_SIZE;
   1.173 -    sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
   1.174 -                           offset, filesz, PAGE_SIZE, PAGE_SIZE);
   1.175      if ( sts != 0 )
   1.176          goto out;
   1.177      offset += filesz;
   1.178 @@ -736,7 +678,7 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.179  
   1.180      /* elf note section: xen core header */
   1.181      sts = elfnote_dump_none(args, dump_rtn);
   1.182 -    if ( sts != 0)
   1.183 +    if ( sts != 0 )
   1.184          goto out;
   1.185  
   1.186      /* elf note section: xen core header */
   1.187 @@ -772,16 +714,6 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.188      if ( sts != 0 )
   1.189          goto out;
   1.190  
   1.191 -    /* p2m/pfn table: .xen_p2m/.xen_pfn */
   1.192 -    if ( !auto_translated_physmap )
   1.193 -        sts = dump_rtn(args, (char *)p2m_array,
   1.194 -                       sizeof(p2m_array[0]) * nr_pages);
   1.195 -    else
   1.196 -        sts = dump_rtn(args, (char *)pfn_array,
   1.197 -                       sizeof(pfn_array[0]) * nr_pages);
   1.198 -    if ( sts != 0 )
   1.199 -        goto out;
   1.200 -
   1.201      /* Pad the output data to page alignment. */
   1.202      memset(dummy, 0, PAGE_SIZE);
   1.203      sts = dump_rtn(args, dummy, dummy_len);
   1.204 @@ -789,25 +721,100 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.205          goto out;
   1.206  
   1.207      /* dump pages: .xen_pages */
   1.208 -    for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ )
   1.209 +    j = 0;
   1.210 +    dump_mem = dump_mem_start;
   1.211 +    for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
   1.212      {
   1.213 -        uint64_t gmfn;
   1.214 -        if ( !auto_translated_physmap )
   1.215 -            gmfn = p2m_array[i].gmfn;
   1.216 -        else
   1.217 -            gmfn = pfn_array[i];
   1.218 +        uint64_t pfn_start;
   1.219 +        uint64_t pfn_end;
   1.220  
   1.221 -        copy_from_domain_page(xc_handle, domid, gmfn, dump_mem);
   1.222 -        dump_mem += PAGE_SIZE;
   1.223 -        if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) )
   1.224 +        pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
   1.225 +        pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
   1.226 +        for ( i = pfn_start; i < pfn_end; i++ )
   1.227          {
   1.228 -            sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
   1.229 +            uint64_t gmfn;
   1.230 +            void *vaddr;
   1.231 +            
   1.232 +            if ( j >= nr_pages )
   1.233 +            {
   1.234 +                /*
   1.235 +                 * When live dump-mode (-L option) is specified,
   1.236 +                 * guest domain may increase memory.
   1.237 +                 */
   1.238 +                IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages);
   1.239 +                goto copy_done;
   1.240 +            }
   1.241 +
   1.242 +            if ( !auto_translated_physmap )
   1.243 +            {
   1.244 +                gmfn = p2m[i];
   1.245 +                if ( gmfn == INVALID_P2M_ENTRY )
   1.246 +                    continue;
   1.247 +
   1.248 +                p2m_array[j].pfn = i;
   1.249 +                p2m_array[j].gmfn = gmfn;
   1.250 +            }
   1.251 +            else
   1.252 +            {
   1.253 +                gmfn = i;
   1.254 +                pfn_array[j] = i;
   1.255 +            }
   1.256 +
   1.257 +            vaddr = xc_map_foreign_range(
   1.258 +                xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn);
   1.259 +            if ( vaddr == NULL )
   1.260 +                continue;
   1.261 +            memcpy(dump_mem, vaddr, PAGE_SIZE);
   1.262 +            munmap(vaddr, PAGE_SIZE);
   1.263 +            dump_mem += PAGE_SIZE;
   1.264 +            if ( (j + 1) % DUMP_INCREMENT == 0 )
   1.265 +            {
   1.266 +                sts = dump_rtn(
   1.267 +                    args, dump_mem_start, dump_mem - dump_mem_start);
   1.268 +                if ( sts != 0 )
   1.269 +                    goto out;
   1.270 +                dump_mem = dump_mem_start;
   1.271 +            }
   1.272 +
   1.273 +            j++;
   1.274 +        }
   1.275 +    }
   1.276 +
   1.277 +copy_done:
   1.278 +    sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
   1.279 +    if ( sts != 0 )
   1.280 +        goto out;
   1.281 +    if ( j < nr_pages )
   1.282 +    {
   1.283 +        /* When live dump-mode (-L option) is specified,
   1.284 +         * guest domain may reduce memory. pad with zero pages.
   1.285 +         */
   1.286 +        IPRINTF("j (%ld) != nr_pages (%ld)", j , nr_pages);
   1.287 +        memset(dump_mem_start, 0, PAGE_SIZE);
   1.288 +        for (; j < nr_pages; j++) {
   1.289 +            sts = dump_rtn(args, dump_mem_start, PAGE_SIZE);
   1.290              if ( sts != 0 )
   1.291                  goto out;
   1.292 -            dump_mem = dump_mem_start;
   1.293 +            if ( !auto_translated_physmap )
   1.294 +            {
   1.295 +                p2m_array[j].pfn = XC_CORE_INVALID_PFN;
   1.296 +                p2m_array[j].gmfn = XC_CORE_INVALID_GMFN;
   1.297 +            }
   1.298 +            else
   1.299 +                pfn_array[j] = XC_CORE_INVALID_PFN;
   1.300          }
   1.301      }
   1.302  
   1.303 +    /* p2m/pfn table: .xen_p2m/.xen_pfn */
   1.304 +    if ( !auto_translated_physmap )
   1.305 +        sts = dump_rtn(
   1.306 +            args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
   1.307 +    else
   1.308 +        sts = dump_rtn(
   1.309 +            args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
   1.310 +    if ( sts != 0 )
   1.311 +        goto out;
   1.312 +
   1.313      /* elf section header string table: .shstrtab */
   1.314      sts = dump_rtn(args, strtab->strings, strtab->current);
   1.315      if ( sts != 0 )
   1.316 @@ -816,6 +823,8 @@ xc_domain_dumpcore_via_callback(int xc_h
   1.317      sts = 0;
   1.318  
   1.319  out:
   1.320 +    if ( memory_map != NULL )
   1.321 +        free(memory_map);
   1.322      if ( p2m != NULL )
   1.323          munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
   1.324      if ( p2m_array != NULL )
     2.1 --- a/tools/libxc/xc_core.h	Thu Aug 30 14:57:24 2007 +0100
     2.2 +++ b/tools/libxc/xc_core.h	Thu Aug 30 14:58:40 2007 +0100
     2.3 @@ -107,6 +107,8 @@ struct xen_dumpcore_elfnote_format_versi
     2.4      struct xen_dumpcore_elfnote_format_version_desc     format_version;
     2.5  };
     2.6  
     2.7 +#define XC_CORE_INVALID_PFN     (~(uint64_t)0)
     2.8 +#define XC_CORE_INVALID_GMFN    (~(uint64_t)0)
     2.9  struct xen_dumpcore_p2m {
    2.10      uint64_t    pfn;
    2.11      uint64_t    gmfn;