ia64/xen-unstable

view tools/libxc/xc_core.c @ 14114:59b8d5168cc1

Reduce impact of saving/restoring/dumping large domains on Dom0 memory
usage by means of fadvise64() to tell the OS to discard the cache
pages used for the save/dump file.

Signed-off-by: Simon Graham <Simon.Graham@stratus.com>
author Keir Fraser <keir@xensource.com>
date Sat Feb 24 14:48:17 2007 +0000 (2007-02-24)
parents 3dac99b6034e
children 047748faa4aa
line source
1 /*
2 * Elf format, (pfn, gmfn) table, IA64 support.
3 * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
4 * VA Linux Systems Japan K.K.
5 *
6 * xen dump-core file format follows ELF format specification.
7 * Analisys tools shouldn't depends on the order of sections.
8 * They should follow elf header and check section names.
9 *
10 * +--------------------------------------------------------+
11 * |ELF header |
12 * +--------------------------------------------------------+
13 * |section headers |
14 * | null section header |
15 * | .shstrtab |
16 * | .note.Xen |
17 * | .xen_prstatus |
18 * | .xen_ia64_mmapped_regs if ia64 |
19 * | .xen_shared_info if present |
20 * | .xen_p2m or .xen_pfn |
21 * | .xen_pages |
22 * +--------------------------------------------------------+
23 * |.note.Xen:note section |
24 * | "Xen" is used as note name, |
25 * | types are defined in xen/include/public/elfnote.h |
26 * | and descriptors are defined in xc_core.h. |
27 * | dumpcore none |
28 * | dumpcore header |
29 * | dumpcore xen version |
30 * | dumpcore format version |
31 * +--------------------------------------------------------+
32 * |.xen_prstatus |
33 * | vcpu_guest_context_t[nr_vcpus] |
34 * +--------------------------------------------------------+
35 * |.xen_ia64_mmapped_regs if ia64 |
36 * | mmapped_regs_t[nr_vcpus] |
37 * +--------------------------------------------------------+
38 * |.xen_shared_info if possible |
39 * +--------------------------------------------------------+
40 * |.xen_p2m or .xen_pfn |
41 * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] |
42 * | .xen_pfn: uint64_t[nr_pages] |
43 * +--------------------------------------------------------+
44 * |.xen_pages |
45 * | page * nr_pages |
46 * +--------------------------------------------------------+
47 * |.shstrtab: section header string table |
48 * +--------------------------------------------------------+
49 *
50 */
52 #include "xg_private.h"
53 #include "xc_core.h"
54 #include "xc_dom.h"
55 #include <stdlib.h>
56 #include <unistd.h>
58 /* number of pages to write at a time */
59 #define DUMP_INCREMENT (4 * 1024)
61 static int
62 copy_from_domain_page(int xc_handle,
63 uint32_t domid,
64 unsigned long mfn,
65 void *dst_page)
66 {
67 void *vaddr = xc_map_foreign_range(
68 xc_handle, domid, PAGE_SIZE, PROT_READ, mfn);
69 if ( vaddr == NULL )
70 return -1;
71 memcpy(dst_page, vaddr, PAGE_SIZE);
72 munmap(vaddr, PAGE_SIZE);
73 return 0;
74 }
76 /* string table */
77 struct xc_core_strtab {
78 char *strings;
79 uint16_t current;
80 uint16_t max;
81 };
83 static struct xc_core_strtab*
84 xc_core_strtab_init(void)
85 {
86 struct xc_core_strtab *strtab;
87 char *strings;
88 strtab = malloc(sizeof(strtab));
89 if ( strtab == NULL )
90 return NULL;
92 strings = malloc(PAGE_SIZE);
93 if ( strings == NULL )
94 {
95 PERROR("Could not allocate string table init");
96 free(strtab);
97 return NULL;
98 }
99 strtab->strings = strings;
100 strtab->max = PAGE_SIZE;
102 /* index 0 represents none */
103 strtab->strings[0] = '\0';
104 strtab->current = 1;
106 return strtab;
107 }
109 static void
110 xc_core_strtab_free(struct xc_core_strtab *strtab)
111 {
112 free(strtab->strings);
113 free(strtab);
114 }
116 static uint16_t
117 xc_core_strtab_get(struct xc_core_strtab *strtab, const char *name)
118 {
119 uint16_t ret = 0;
120 uint16_t len = strlen(name) + 1;
122 if ( strtab->current + len > strtab->max )
123 {
124 char *tmp;
125 if ( strtab->max * 2 < strtab->max )
126 {
127 PERROR("too long string table");
128 errno = ENOMEM;
129 return ret;
130 }
133 tmp = realloc(strtab->strings, strtab->max * 2);
134 if ( tmp == NULL )
135 {
136 PERROR("Could not allocate string table");
137 return ret;
138 }
140 strtab->strings = tmp;
141 strtab->max *= 2;
142 }
144 ret = strtab->current;
145 strcpy(strtab->strings + strtab->current, name);
146 strtab->current += len;
147 return ret;
148 }
151 /* section headers */
152 struct xc_core_section_headers {
153 uint16_t num;
154 uint16_t num_max;
156 Elf_Shdr *shdrs;
157 };
158 #define SHDR_INIT 16
159 #define SHDR_INC 4
161 static struct xc_core_section_headers*
162 xc_core_shdr_init(void)
163 {
164 struct xc_core_section_headers *sheaders;
165 sheaders = malloc(sizeof(*sheaders));
166 if ( sheaders == NULL )
167 return NULL;
169 sheaders->num = 0;
170 sheaders->num_max = SHDR_INIT;
171 sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
172 if ( sheaders->shdrs == NULL )
173 {
174 free(sheaders);
175 return NULL;
176 }
177 return sheaders;
178 }
180 static void
181 xc_core_shdr_free(struct xc_core_section_headers *sheaders)
182 {
183 free(sheaders->shdrs);
184 free(sheaders);
185 }
187 Elf_Shdr*
188 xc_core_shdr_get(struct xc_core_section_headers *sheaders)
189 {
190 Elf_Shdr *shdr;
192 if ( sheaders->num == sheaders->num_max )
193 {
194 Elf_Shdr *shdrs;
195 if ( sheaders->num_max + SHDR_INC < sheaders->num_max )
196 {
197 errno = E2BIG;
198 return NULL;
199 }
200 sheaders->num_max += SHDR_INC;
201 shdrs = realloc(sheaders->shdrs,
202 sizeof(sheaders->shdrs[0]) * sheaders->num_max);
203 if ( shdrs == NULL )
204 return NULL;
205 sheaders->shdrs = shdrs;
206 }
208 shdr = &sheaders->shdrs[sheaders->num];
209 sheaders->num++;
210 memset(shdr, 0, sizeof(*shdr));
211 return shdr;
212 }
214 int
215 xc_core_shdr_set(Elf_Shdr *shdr,
216 struct xc_core_strtab *strtab,
217 const char *name, uint32_t type,
218 uint64_t offset, uint64_t size,
219 uint64_t addralign, uint64_t entsize)
220 {
221 uint64_t name_idx = xc_core_strtab_get(strtab, name);
222 if ( name_idx == 0 )
223 return -1;
225 shdr->sh_name = name_idx;
226 shdr->sh_type = type;
227 shdr->sh_offset = offset;
228 shdr->sh_size = size;
229 shdr->sh_addralign = addralign;
230 shdr->sh_entsize = entsize;
231 return 0;
232 }
234 static int
235 elfnote_fill_xen_version(int xc_handle,
236 struct xen_dumpcore_elfnote_xen_version_desc
237 *xen_version)
238 {
239 int rc;
240 memset(xen_version, 0, sizeof(*xen_version));
242 rc = xc_version(xc_handle, XENVER_version, NULL);
243 if ( rc < 0 )
244 return rc;
245 xen_version->major_version = rc >> 16;
246 xen_version->minor_version = rc & ((1 << 16) - 1);
248 rc = xc_version(xc_handle, XENVER_extraversion,
249 &xen_version->extra_version);
250 if ( rc < 0 )
251 return rc;
253 rc = xc_version(xc_handle, XENVER_compile_info,
254 &xen_version->compile_info);
255 if ( rc < 0 )
256 return rc;
258 rc = xc_version(xc_handle,
259 XENVER_capabilities, &xen_version->capabilities);
260 if ( rc < 0 )
261 return rc;
263 rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset);
264 if ( rc < 0 )
265 return rc;
267 rc = xc_version(xc_handle, XENVER_platform_parameters,
268 &xen_version->platform_parameters);
269 if ( rc < 0 )
270 return rc;
272 rc = xc_version(xc_handle, XENVER_pagesize, NULL);
273 if ( rc < 0 )
274 return rc;
275 xen_version->pagesize = rc;
277 return 0;
278 }
280 static int
281 elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
282 *format_version)
283 {
284 format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
285 return 0;
286 }
288 int
289 xc_domain_dumpcore_via_callback(int xc_handle,
290 uint32_t domid,
291 void *args,
292 dumpcore_rtn_t dump_rtn)
293 {
294 xc_dominfo_t info;
295 shared_info_t *live_shinfo = NULL;
297 int nr_vcpus = 0;
298 char *dump_mem, *dump_mem_start = NULL;
299 vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
300 struct xc_core_arch_context arch_ctxt;
301 char dummy[PAGE_SIZE];
302 int dummy_len;
303 int sts = -1;
305 unsigned long i;
306 unsigned long j;
307 unsigned long nr_pages;
309 xc_core_memory_map_t *memory_map = NULL;
310 unsigned int nr_memory_map;
311 unsigned int map_idx;
313 int auto_translated_physmap;
314 xen_pfn_t *p2m = NULL;
315 unsigned long max_pfn = 0;
316 struct xen_dumpcore_p2m *p2m_array = NULL;
318 uint64_t *pfn_array = NULL;
320 Elf_Ehdr ehdr;
321 unsigned long filesz;
322 unsigned long offset;
323 unsigned long fixup;
325 struct xc_core_strtab *strtab = NULL;
326 uint16_t strtab_idx;
327 struct xc_core_section_headers *sheaders = NULL;
328 Elf_Shdr *shdr;
330 /* elf notes */
331 struct xen_elfnote elfnote;
332 struct xen_dumpcore_elfnote_none_desc none;
333 struct xen_dumpcore_elfnote_header_desc header;
334 struct xen_dumpcore_elfnote_xen_version_desc xen_version;
335 struct xen_dumpcore_elfnote_format_version_desc format_version;
337 xc_core_arch_context_init(&arch_ctxt);
338 if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
339 {
340 PERROR("Could not allocate dump_mem");
341 goto out;
342 }
344 if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
345 {
346 PERROR("Could not get info for domain");
347 goto out;
348 }
349 /* Map the shared info frame */
350 live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
351 PROT_READ, info.shared_info_frame);
352 if ( !live_shinfo
353 #ifdef __ia64__
354 && !info.hvm
355 #endif
356 )
357 {
358 PERROR("Couldn't map live_shinfo");
359 goto out;
360 }
361 auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
363 if ( domid != info.domid )
364 {
365 PERROR("Domain %d does not exist", domid);
366 goto out;
367 }
369 for ( i = 0; i <= info.max_vcpu_id; i++ )
370 {
371 if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 )
372 {
373 if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
374 xc_handle, domid) )
375 continue;
376 nr_vcpus++;
377 }
378 }
379 if ( nr_vcpus == 0 )
380 {
381 PERROR("No VCPU context could be grabbed");
382 goto out;
383 }
385 /* obtain memory map */
386 sts = xc_core_arch_memory_map_get(xc_handle, &info, live_shinfo,
387 &memory_map, &nr_memory_map);
388 if ( sts != 0 )
389 goto out;
391 nr_pages = info.nr_pages;
392 if ( !auto_translated_physmap )
393 {
394 /* obtain p2m table */
395 p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
396 if ( p2m_array == NULL )
397 {
398 PERROR("Could not allocate p2m array");
399 goto out;
400 }
402 sts = xc_core_arch_map_p2m(xc_handle, &info, live_shinfo,
403 &p2m, &max_pfn);
404 if ( sts != 0 )
405 goto out;
406 }
407 else
408 {
409 pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
410 if ( pfn_array == NULL )
411 {
412 PERROR("Could not allocate pfn array");
413 goto out;
414 }
415 }
417 /* create .xen_p2m or .xen_pfn */
418 j = 0;
419 for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
420 {
421 uint64_t pfn_start;
422 uint64_t pfn_end;
424 pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
425 pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
426 for ( i = pfn_start; i < pfn_end; i++ )
427 {
428 if ( !auto_translated_physmap )
429 {
430 if ( p2m[i] == INVALID_P2M_ENTRY )
431 continue;
432 p2m_array[j].pfn = i;
433 p2m_array[j].gmfn = p2m[i];
434 }
435 else
436 {
437 /* try to map page to determin wheter it has underlying page */
438 void *vaddr = xc_map_foreign_range(xc_handle, domid,
439 PAGE_SIZE, PROT_READ, i);
440 if ( vaddr == NULL )
441 continue;
442 munmap(vaddr, PAGE_SIZE);
443 pfn_array[j] = i;
444 }
446 j++;
447 }
448 }
449 if ( j != nr_pages )
450 {
451 PERROR("j (%ld) != nr_pages (%ld)", j , nr_pages);
452 /* When live dump-mode (-L option) is specified,
453 * guest domain may change its mapping.
454 */
455 nr_pages = j;
456 }
458 memset(&ehdr, 0, sizeof(ehdr));
459 ehdr.e_ident[EI_MAG0] = ELFMAG0;
460 ehdr.e_ident[EI_MAG1] = ELFMAG1;
461 ehdr.e_ident[EI_MAG2] = ELFMAG2;
462 ehdr.e_ident[EI_MAG3] = ELFMAG3;
463 ehdr.e_ident[EI_CLASS] = ELFCLASS;
464 ehdr.e_ident[EI_DATA] = ELF_ARCH_DATA;
465 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
466 ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
467 ehdr.e_ident[EI_ABIVERSION] = EV_CURRENT;
469 ehdr.e_type = ET_CORE;
470 ehdr.e_machine = ELF_ARCH_MACHINE;
471 ehdr.e_version = EV_CURRENT;
472 ehdr.e_entry = 0;
473 ehdr.e_phoff = 0;
474 ehdr.e_shoff = sizeof(ehdr);
475 ehdr.e_flags = ELF_CORE_EFLAGS;
476 ehdr.e_ehsize = sizeof(ehdr);
477 ehdr.e_phentsize = sizeof(Elf_Phdr);
478 ehdr.e_phnum = 0;
479 ehdr.e_shentsize = sizeof(Elf_Shdr);
480 /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
482 /* create section header */
483 strtab = xc_core_strtab_init();
484 if ( strtab == NULL )
485 {
486 PERROR("Could not allocate string table");
487 goto out;
488 }
489 sheaders = xc_core_shdr_init();
490 if ( sheaders == NULL )
491 {
492 PERROR("Could not allocate section headers");
493 goto out;
494 }
495 /* null section */
496 shdr = xc_core_shdr_get(sheaders);
497 if ( shdr == NULL )
498 {
499 PERROR("Could not get section header for null section");
500 goto out;
501 }
503 /* .shstrtab */
504 shdr = xc_core_shdr_get(sheaders);
505 if ( shdr == NULL )
506 {
507 PERROR("Could not get section header for shstrtab");
508 goto out;
509 }
510 strtab_idx = shdr - sheaders->shdrs;
511 /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
512 * fill it later
513 */
514 sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0);
515 if ( sts != 0 )
516 goto out;
518 /* elf note section */
519 /* here the number of section header is unknown. fix up offset later. */
520 offset = sizeof(ehdr);
521 filesz =
522 sizeof(struct xen_dumpcore_elfnote_none) + /* none */
523 sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
524 sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
525 sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
526 shdr = xc_core_shdr_get(sheaders);
527 if ( shdr == NULL )
528 {
529 PERROR("Could not get section header for note section");
530 goto out;
531 }
532 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
533 offset, filesz, 0, 0);
534 if ( sts != 0 )
535 goto out;
536 offset += filesz;
538 /* prstatus */
539 shdr = xc_core_shdr_get(sheaders);
540 if ( shdr == NULL )
541 {
542 PERROR("Could not get section header for .xen_prstatus");
543 goto out;
544 }
545 filesz = sizeof(ctxt[0]) * nr_vcpus;
546 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
547 SHT_PROGBITS, offset, filesz,
548 __alignof__(ctxt[0]), sizeof(ctxt[0]));
549 if ( sts != 0 )
550 goto out;
551 offset += filesz;
553 /* arch context */
554 sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab,
555 &filesz, offset);
556 if ( sts != 0)
557 goto out;
558 offset += filesz;
560 /* shared_info */
561 if ( live_shinfo != NULL )
562 {
563 shdr = xc_core_shdr_get(sheaders);
564 if ( shdr == NULL )
565 {
566 PERROR("Could not get section header for .xen_shared_info");
567 goto out;
568 }
569 filesz = PAGE_SIZE;
570 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
571 SHT_PROGBITS, offset, filesz,
572 __alignof__(*live_shinfo), PAGE_SIZE);
573 if ( sts != 0 )
574 goto out;
575 offset += filesz;
576 }
578 /* p2m/pfn table */
579 shdr = xc_core_shdr_get(sheaders);
580 if ( shdr == NULL )
581 {
582 PERROR("Could not get section header for .xen_{p2m, pfn} table");
583 goto out;
584 }
585 if ( !auto_translated_physmap )
586 {
587 filesz = nr_pages * sizeof(p2m_array[0]);
588 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M,
589 SHT_PROGBITS,
590 offset, filesz, __alignof__(p2m_array[0]),
591 sizeof(p2m_array[0]));
592 if ( sts != 0 )
593 goto out;
594 }
595 else
596 {
597 filesz = nr_pages * sizeof(pfn_array[0]);
598 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN,
599 SHT_PROGBITS,
600 offset, filesz, __alignof__(pfn_array[0]),
601 sizeof(pfn_array[0]));
602 if ( sts != 0 )
603 goto out;
604 }
605 offset += filesz;
607 /* pages */
608 shdr = xc_core_shdr_get(sheaders);
609 if ( shdr == NULL )
610 {
611 PERROR("could not get section headers for .xen_pages");
612 goto out;
613 }
615 /*
616 * pages are the last section to allocate section headers
617 * so that we know the number of section headers here.
618 */
619 fixup = sheaders->num * sizeof(*shdr);
620 /* zeroth section should have zero offset */
621 for ( i = 1; i < sheaders->num; i++ )
622 sheaders->shdrs[i].sh_offset += fixup;
623 offset += fixup;
624 dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
625 offset += dummy_len;
627 filesz = nr_pages * PAGE_SIZE;
628 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
629 offset, filesz, PAGE_SIZE, PAGE_SIZE);
630 if ( sts != 0 )
631 goto out;
632 offset += filesz;
634 /* fixing up section header string table section header */
635 filesz = strtab->current;
636 sheaders->shdrs[strtab_idx].sh_offset = offset;
637 sheaders->shdrs[strtab_idx].sh_size = filesz;
639 /* write out elf header */
640 ehdr.e_shnum = sheaders->num;
641 ehdr.e_shstrndx = strtab_idx;
642 sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr));
643 if ( sts != 0 )
644 goto out;
646 /* section headers */
647 sts = dump_rtn(args, (char*)sheaders->shdrs,
648 sheaders->num * sizeof(sheaders->shdrs[0]));
649 if ( sts != 0 )
650 goto out;
652 /* elf note section */
653 memset(&elfnote, 0, sizeof(elfnote));
654 elfnote.namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
655 strncpy(elfnote.name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote.name));
657 /* elf note section:xen core header */
658 elfnote.descsz = sizeof(none);
659 elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
660 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
661 if ( sts != 0 )
662 goto out;
663 sts = dump_rtn(args, (char*)&none, sizeof(none));
664 if ( sts != 0 )
665 goto out;
667 /* elf note section:xen core header */
668 elfnote.descsz = sizeof(header);
669 elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
670 header.xch_magic = info.hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
671 header.xch_nr_vcpus = nr_vcpus;
672 header.xch_nr_pages = nr_pages;
673 header.xch_page_size = PAGE_SIZE;
674 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
675 if ( sts != 0 )
676 goto out;
677 sts = dump_rtn(args, (char*)&header, sizeof(header));
678 if ( sts != 0 )
679 goto out;
681 /* elf note section: xen version */
682 elfnote.descsz = sizeof(xen_version);
683 elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
684 elfnote_fill_xen_version(xc_handle, &xen_version);
685 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
686 if ( sts != 0 )
687 goto out;
688 sts = dump_rtn(args, (char*)&xen_version, sizeof(xen_version));
689 if ( sts != 0 )
690 goto out;
692 /* elf note section: format version */
693 elfnote.descsz = sizeof(format_version);
694 elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
695 elfnote_fill_format_version(&format_version);
696 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
697 if ( sts != 0 )
698 goto out;
699 sts = dump_rtn(args, (char*)&format_version, sizeof(format_version));
700 if ( sts != 0 )
701 goto out;
703 /* prstatus: .xen_prstatus */
704 sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus);
705 if ( sts != 0 )
706 goto out;
708 if ( live_shinfo != NULL )
709 {
710 /* shared_info: .xen_shared_info */
711 sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE);
712 if ( sts != 0 )
713 goto out;
714 }
716 /* arch specific context */
717 sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn);
718 if ( sts != 0 )
719 goto out;
721 /* p2m/pfn table: .xen_p2m/.xen_pfn */
722 if ( !auto_translated_physmap )
723 sts = dump_rtn(args, (char *)p2m_array,
724 sizeof(p2m_array[0]) * nr_pages);
725 else
726 sts = dump_rtn(args, (char *)pfn_array,
727 sizeof(pfn_array[0]) * nr_pages);
728 if ( sts != 0 )
729 goto out;
731 /* Pad the output data to page alignment. */
732 memset(dummy, 0, PAGE_SIZE);
733 sts = dump_rtn(args, dummy, dummy_len);
734 if ( sts != 0 )
735 goto out;
737 /* dump pages: .xen_pages */
738 for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ )
739 {
740 uint64_t gmfn;
741 if ( !auto_translated_physmap )
742 gmfn = p2m_array[i].gmfn;
743 else
744 gmfn = pfn_array[i];
746 copy_from_domain_page(xc_handle, domid, gmfn, dump_mem);
747 dump_mem += PAGE_SIZE;
748 if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) )
749 {
750 sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
751 if ( sts != 0 )
752 goto out;
753 dump_mem = dump_mem_start;
754 }
755 }
757 /* elf section header string table: .shstrtab */
758 sts = dump_rtn(args, strtab->strings, strtab->current);
759 if ( sts != 0 )
760 goto out;
762 sts = 0;
764 out:
765 if ( p2m != NULL )
766 munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
767 if ( p2m_array != NULL )
768 free(p2m_array);
769 if ( pfn_array != NULL )
770 free(pfn_array);
771 if ( sheaders != NULL )
772 xc_core_shdr_free(sheaders);
773 if ( strtab != NULL )
774 xc_core_strtab_free(strtab);
775 if ( dump_mem_start != NULL )
776 free(dump_mem_start);
777 if ( live_shinfo != NULL )
778 munmap(live_shinfo, PAGE_SIZE);
779 xc_core_arch_context_free(&arch_ctxt);
781 return sts;
782 }
784 /* Callback args for writing to a local dump file. */
785 struct dump_args {
786 int fd;
787 };
789 /* Callback routine for writing to a local dump file. */
790 static int local_file_dump(void *args, char *buffer, unsigned int length)
791 {
792 struct dump_args *da = args;
793 int bytes, offset;
795 for ( offset = 0; offset < length; offset += bytes )
796 {
797 bytes = write(da->fd, &buffer[offset], length-offset);
798 if ( bytes <= 0 )
799 {
800 PERROR("Failed to write buffer");
801 return -errno;
802 }
803 }
805 if (length >= DUMP_INCREMENT*PAGE_SIZE) {
806 // Now dumping pages -- make sure we discard clean pages from
807 // the cache after each write
808 discard_file_cache(da->fd, 0 /* no flush */);
809 }
811 return 0;
812 }
814 int
815 xc_domain_dumpcore(int xc_handle,
816 uint32_t domid,
817 const char *corename)
818 {
819 struct dump_args da;
820 int sts;
822 if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 )
823 {
824 PERROR("Could not open corefile %s", corename);
825 return -errno;
826 }
828 sts = xc_domain_dumpcore_via_callback(
829 xc_handle, domid, &da, &local_file_dump);
831 /* flush and discard any remaining portion of the file from cache */
832 discard_file_cache(da.fd, 1/* flush first*/);
834 close(da.fd);
836 return sts;
837 }
839 /*
840 * Local variables:
841 * mode: C
842 * c-set-style: "BSD"
843 * c-basic-offset: 4
844 * tab-width: 4
845 * indent-tabs-mode: nil
846 * End:
847 */