debuggers.hg

view tools/libxc/xc_core.c @ 19826:2f9e1348aa98

x86_64: allow more vCPU-s per guest

Since the shared info layout is fixed, guests are required to use
VCPUOP_register_vcpu_info prior to booting any vCPU beyond the
traditional limit of 32.

MAX_VIRT_CPUS, being an implemetation detail of the hypervisor, is no
longer being exposed in the public headers.

The tools changes are clearly incomplete (and done only so things
would
build again), and the current state of the tools (using scalar
variables all over the place to represent vCPU bitmaps) very likely
doesn't permit booting DomU-s with more than the traditional number of
vCPU-s. Testing of the extended functionality was done with Dom0 (96
vCPU-s, as well as 128 vCPU-s out of which the kernel elected - by way
of a simple kernel side patch - to use only some, resulting in a
sparse
bitmap).

ia64 changes only to make things build, and build-tested only (and the
tools part only as far as the build would go without encountering
unrelated problems in the blktap code).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:14:16 2009 +0100 (2009-06-18)
parents 1e9342bc6d6e
children cce683039b70
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_pages |
21 * | .xen_p2m or .xen_pfn |
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 pv |
36 * | mmapped_regs_t[nr_vcpus] |
37 * +--------------------------------------------------------+
38 * |.xen_shared_info if possible |
39 * +--------------------------------------------------------+
40 * |.xen_pages |
41 * | page * nr_pages |
42 * +--------------------------------------------------------+
43 * |.xen_p2m or .xen_pfn |
44 * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] |
45 * | .xen_pfn: uint64_t[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 /* string table */
62 struct xc_core_strtab {
63 char *strings;
64 uint16_t length;
65 uint16_t max;
66 };
68 static struct xc_core_strtab*
69 xc_core_strtab_init(void)
70 {
71 struct xc_core_strtab *strtab;
72 char *strings;
73 strtab = malloc(sizeof(*strtab));
74 if ( strtab == NULL )
75 return NULL;
77 strings = malloc(PAGE_SIZE);
78 if ( strings == NULL )
79 {
80 PERROR("Could not allocate string table init");
81 free(strtab);
82 return NULL;
83 }
84 strtab->strings = strings;
85 strtab->max = PAGE_SIZE;
87 /* index 0 represents none */
88 strtab->strings[0] = '\0';
89 strtab->length = 1;
91 return strtab;
92 }
94 static void
95 xc_core_strtab_free(struct xc_core_strtab *strtab)
96 {
97 free(strtab->strings);
98 free(strtab);
99 }
101 static uint16_t
102 xc_core_strtab_get(struct xc_core_strtab *strtab, const char *name)
103 {
104 uint16_t ret = 0;
105 uint16_t len = strlen(name) + 1;
107 if ( strtab->length > UINT16_MAX - len )
108 {
109 PERROR("too long string table");
110 errno = E2BIG;
111 return ret;
112 }
114 if ( strtab->length + len > strtab->max )
115 {
116 char *tmp;
117 if ( strtab->max > UINT16_MAX / 2 )
118 {
119 PERROR("too long string table");
120 errno = ENOMEM;
121 return ret;
122 }
124 tmp = realloc(strtab->strings, strtab->max * 2);
125 if ( tmp == NULL )
126 {
127 PERROR("Could not allocate string table");
128 return ret;
129 }
131 strtab->strings = tmp;
132 strtab->max *= 2;
133 }
135 ret = strtab->length;
136 strcpy(strtab->strings + strtab->length, name);
137 strtab->length += len;
138 return ret;
139 }
142 /* section headers */
143 struct xc_core_section_headers {
144 uint16_t num;
145 uint16_t num_max;
147 Elf64_Shdr *shdrs;
148 };
149 #define SHDR_INIT ((uint16_t)16)
150 #define SHDR_INC ((uint16_t)4)
152 static struct xc_core_section_headers*
153 xc_core_shdr_init(void)
154 {
155 struct xc_core_section_headers *sheaders;
156 sheaders = malloc(sizeof(*sheaders));
157 if ( sheaders == NULL )
158 return NULL;
160 sheaders->num = 0;
161 sheaders->num_max = SHDR_INIT;
162 sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
163 if ( sheaders->shdrs == NULL )
164 {
165 free(sheaders);
166 return NULL;
167 }
168 return sheaders;
169 }
171 static void
172 xc_core_shdr_free(struct xc_core_section_headers *sheaders)
173 {
174 free(sheaders->shdrs);
175 free(sheaders);
176 }
178 Elf64_Shdr*
179 xc_core_shdr_get(struct xc_core_section_headers *sheaders)
180 {
181 Elf64_Shdr *shdr;
183 if ( sheaders->num == sheaders->num_max )
184 {
185 Elf64_Shdr *shdrs;
186 if ( sheaders->num_max > UINT16_MAX - SHDR_INC )
187 {
188 errno = E2BIG;
189 return NULL;
190 }
191 sheaders->num_max += SHDR_INC;
192 shdrs = realloc(sheaders->shdrs,
193 sizeof(sheaders->shdrs[0]) * sheaders->num_max);
194 if ( shdrs == NULL )
195 return NULL;
196 sheaders->shdrs = shdrs;
197 }
199 shdr = &sheaders->shdrs[sheaders->num];
200 sheaders->num++;
201 memset(shdr, 0, sizeof(*shdr));
202 return shdr;
203 }
205 int
206 xc_core_shdr_set(Elf64_Shdr *shdr,
207 struct xc_core_strtab *strtab,
208 const char *name, uint32_t type,
209 uint64_t offset, uint64_t size,
210 uint64_t addralign, uint64_t entsize)
211 {
212 uint64_t name_idx = xc_core_strtab_get(strtab, name);
213 if ( name_idx == 0 )
214 return -1;
216 shdr->sh_name = name_idx;
217 shdr->sh_type = type;
218 shdr->sh_offset = offset;
219 shdr->sh_size = size;
220 shdr->sh_addralign = addralign;
221 shdr->sh_entsize = entsize;
222 return 0;
223 }
225 static void
226 xc_core_ehdr_init(Elf64_Ehdr *ehdr)
227 {
228 memset(ehdr, 0, sizeof(*ehdr));
229 ehdr->e_ident[EI_MAG0] = ELFMAG0;
230 ehdr->e_ident[EI_MAG1] = ELFMAG1;
231 ehdr->e_ident[EI_MAG2] = ELFMAG2;
232 ehdr->e_ident[EI_MAG3] = ELFMAG3;
233 ehdr->e_ident[EI_CLASS] = ELFCLASS64;
234 ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA;
235 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
236 ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
237 ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
239 ehdr->e_type = ET_CORE;
240 /* e_machine will be filled in later */
241 ehdr->e_version = EV_CURRENT;
242 ehdr->e_entry = 0;
243 ehdr->e_phoff = 0;
244 ehdr->e_shoff = sizeof(*ehdr);
245 ehdr->e_flags = ELF_CORE_EFLAGS;
246 ehdr->e_ehsize = sizeof(*ehdr);
247 ehdr->e_phentsize = sizeof(Elf64_Phdr);
248 ehdr->e_phnum = 0;
249 ehdr->e_shentsize = sizeof(Elf64_Shdr);
250 /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet.
251 * fill it later */
252 }
254 static int
255 elfnote_fill_xen_version(int xc_handle,
256 struct xen_dumpcore_elfnote_xen_version_desc
257 *xen_version)
258 {
259 int rc;
260 memset(xen_version, 0, sizeof(*xen_version));
262 rc = xc_version(xc_handle, XENVER_version, NULL);
263 if ( rc < 0 )
264 return rc;
265 xen_version->major_version = rc >> 16;
266 xen_version->minor_version = rc & ((1 << 16) - 1);
268 rc = xc_version(xc_handle, XENVER_extraversion,
269 &xen_version->extra_version);
270 if ( rc < 0 )
271 return rc;
273 rc = xc_version(xc_handle, XENVER_compile_info,
274 &xen_version->compile_info);
275 if ( rc < 0 )
276 return rc;
278 rc = xc_version(xc_handle,
279 XENVER_capabilities, &xen_version->capabilities);
280 if ( rc < 0 )
281 return rc;
283 rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset);
284 if ( rc < 0 )
285 return rc;
287 rc = xc_version(xc_handle, XENVER_platform_parameters,
288 &xen_version->platform_parameters);
289 if ( rc < 0 )
290 return rc;
292 rc = xc_version(xc_handle, XENVER_pagesize, NULL);
293 if ( rc < 0 )
294 return rc;
295 xen_version->pagesize = rc;
297 return 0;
298 }
300 static void
301 elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
302 *format_version)
303 {
304 format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
305 }
307 static void
308 elfnote_init(struct elfnote *elfnote)
309 {
310 /* elf note section */
311 memset(elfnote, 0, sizeof(*elfnote));
312 elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
313 strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name));
314 }
316 static int
317 elfnote_dump_none(void *args, dumpcore_rtn_t dump_rtn)
318 {
319 int sts;
320 struct elfnote elfnote;
321 struct xen_dumpcore_elfnote_none_desc none;
323 elfnote_init(&elfnote);
324 memset(&none, 0, sizeof(none));
326 elfnote.descsz = sizeof(none);
327 elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
328 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
329 if ( sts != 0 )
330 return sts;
331 return dump_rtn(args, (char*)&none, sizeof(none));
332 }
334 static int
335 elfnote_dump_core_header(
336 void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info,
337 int nr_vcpus, unsigned long nr_pages)
338 {
339 int sts;
340 struct elfnote elfnote;
341 struct xen_dumpcore_elfnote_header_desc header;
343 elfnote_init(&elfnote);
344 memset(&header, 0, sizeof(header));
346 elfnote.descsz = sizeof(header);
347 elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
348 header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
349 header.xch_nr_vcpus = nr_vcpus;
350 header.xch_nr_pages = nr_pages;
351 header.xch_page_size = PAGE_SIZE;
352 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
353 if ( sts != 0 )
354 return sts;
355 return dump_rtn(args, (char*)&header, sizeof(header));
356 }
358 static int
359 elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle,
360 unsigned int guest_width)
361 {
362 int sts;
363 struct elfnote elfnote;
364 struct xen_dumpcore_elfnote_xen_version_desc xen_version;
366 elfnote_init(&elfnote);
367 memset(&xen_version, 0, sizeof(xen_version));
369 elfnote.descsz = sizeof(xen_version);
370 elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
371 elfnote_fill_xen_version(xc_handle, &xen_version);
372 if (guest_width < sizeof(unsigned long))
373 {
374 // 32 bit elf file format differs in pagesize's alignment
375 char *p = (char *)&xen_version.pagesize;
376 memmove(p - 4, p, sizeof(xen_version.pagesize));
377 }
378 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
379 if ( sts != 0 )
380 return sts;
381 return dump_rtn(args, (char*)&xen_version, sizeof(xen_version));
382 }
384 static int
385 elfnote_dump_format_version(void *args, dumpcore_rtn_t dump_rtn)
386 {
387 int sts;
388 struct elfnote elfnote;
389 struct xen_dumpcore_elfnote_format_version_desc format_version;
391 elfnote_init(&elfnote);
392 memset(&format_version, 0, sizeof(format_version));
394 elfnote.descsz = sizeof(format_version);
395 elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
396 elfnote_fill_format_version(&format_version);
397 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
398 if ( sts != 0 )
399 return sts;
400 return dump_rtn(args, (char*)&format_version, sizeof(format_version));
401 }
403 static int
404 get_guest_width(int xc_handle,
405 uint32_t domid,
406 unsigned int *guest_width)
407 {
408 DECLARE_DOMCTL;
410 memset(&domctl, 0, sizeof(domctl));
411 domctl.domain = domid;
412 domctl.cmd = XEN_DOMCTL_get_address_size;
414 if ( do_domctl(xc_handle, &domctl) != 0 )
415 return 1;
417 *guest_width = domctl.u.address_size.size / 8;
418 return 0;
419 }
421 int
422 xc_domain_dumpcore_via_callback(int xc_handle,
423 uint32_t domid,
424 void *args,
425 dumpcore_rtn_t dump_rtn)
426 {
427 xc_dominfo_t info;
428 shared_info_any_t *live_shinfo = NULL;
429 unsigned int guest_width;
431 int nr_vcpus = 0;
432 char *dump_mem, *dump_mem_start = NULL;
433 vcpu_guest_context_any_t *ctxt = NULL;
434 struct xc_core_arch_context arch_ctxt;
435 char dummy[PAGE_SIZE];
436 int dummy_len;
437 int sts = -1;
439 unsigned long i;
440 unsigned long j;
441 unsigned long nr_pages;
443 xc_core_memory_map_t *memory_map = NULL;
444 unsigned int nr_memory_map;
445 unsigned int map_idx;
447 int auto_translated_physmap;
448 xen_pfn_t *p2m = NULL;
449 unsigned long p2m_size = 0;
450 struct xen_dumpcore_p2m *p2m_array = NULL;
452 uint64_t *pfn_array = NULL;
454 Elf64_Ehdr ehdr;
455 uint64_t filesz;
456 uint64_t offset;
457 uint64_t fixup;
459 struct xc_core_strtab *strtab = NULL;
460 uint16_t strtab_idx;
461 struct xc_core_section_headers *sheaders = NULL;
462 Elf64_Shdr *shdr;
464 if ( get_guest_width(xc_handle, domid, &guest_width) != 0 )
465 {
466 PERROR("Could not get address size for domain");
467 return sts;
468 }
470 xc_core_arch_context_init(&arch_ctxt);
471 if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
472 {
473 PERROR("Could not allocate dump_mem");
474 goto out;
475 }
477 if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
478 {
479 PERROR("Could not get info for domain");
480 goto out;
481 }
482 /* Map the shared info frame */
483 live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
484 PROT_READ, info.shared_info_frame);
485 if ( !live_shinfo && !info.hvm )
486 {
487 PERROR("Couldn't map live_shinfo");
488 goto out;
489 }
490 auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
492 if ( domid != info.domid )
493 {
494 PERROR("Domain %d does not exist", domid);
495 goto out;
496 }
498 ctxt = calloc(sizeof(*ctxt), info.max_vcpu_id + 1);
499 if ( !ctxt )
500 {
501 PERROR("Could not allocate vcpu context array", domid);
502 goto out;
503 }
505 for ( i = 0; i <= info.max_vcpu_id; i++ )
506 {
507 if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 )
508 {
509 if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
510 xc_handle, domid) )
511 continue;
512 nr_vcpus++;
513 }
514 }
515 if ( nr_vcpus == 0 )
516 {
517 PERROR("No VCPU context could be grabbed");
518 goto out;
519 }
521 /* obtain memory map */
522 sts = xc_core_arch_memory_map_get(xc_handle, &arch_ctxt, &info,
523 live_shinfo, &memory_map,
524 &nr_memory_map);
525 if ( sts != 0 )
526 goto out;
528 /*
529 * Note: this is the *current* number of pages and may change under
530 * a live dump-core. We'll just take this value, and if more pages
531 * exist, we'll skip them. If there's less, then we'll just not use
532 * all the array...
533 *
534 * We don't want to use the total potential size of the memory map
535 * since that is usually much higher than info.nr_pages.
536 */
537 nr_pages = info.nr_pages;
539 if ( !auto_translated_physmap )
540 {
541 /* obtain p2m table */
542 p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
543 if ( p2m_array == NULL )
544 {
545 PERROR("Could not allocate p2m array");
546 goto out;
547 }
549 sts = xc_core_arch_map_p2m(xc_handle, guest_width, &info, live_shinfo,
550 &p2m, &p2m_size);
551 if ( sts != 0 )
552 goto out;
553 }
554 else
555 {
556 pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
557 if ( pfn_array == NULL )
558 {
559 PERROR("Could not allocate pfn array");
560 goto out;
561 }
562 }
564 /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
565 xc_core_ehdr_init(&ehdr);
567 /* create section header */
568 strtab = xc_core_strtab_init();
569 if ( strtab == NULL )
570 {
571 PERROR("Could not allocate string table");
572 goto out;
573 }
574 sheaders = xc_core_shdr_init();
575 if ( sheaders == NULL )
576 {
577 PERROR("Could not allocate section headers");
578 goto out;
579 }
580 /* null section */
581 shdr = xc_core_shdr_get(sheaders);
582 if ( shdr == NULL )
583 {
584 PERROR("Could not get section header for null section");
585 goto out;
586 }
588 /* .shstrtab */
589 shdr = xc_core_shdr_get(sheaders);
590 if ( shdr == NULL )
591 {
592 PERROR("Could not get section header for shstrtab");
593 goto out;
594 }
595 strtab_idx = shdr - sheaders->shdrs;
596 /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
597 * fill it later
598 */
599 sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0);
600 if ( sts != 0 )
601 goto out;
603 /* elf note section */
604 /* here the number of section header is unknown. fix up offset later. */
605 offset = sizeof(ehdr);
606 filesz =
607 sizeof(struct xen_dumpcore_elfnote_none) + /* none */
608 sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
609 sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
610 sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
611 shdr = xc_core_shdr_get(sheaders);
612 if ( shdr == NULL )
613 {
614 PERROR("Could not get section header for note section");
615 goto out;
616 }
617 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
618 offset, filesz, 0, 0);
619 if ( sts != 0 )
620 goto out;
621 offset += filesz;
623 /* prstatus */
624 shdr = xc_core_shdr_get(sheaders);
625 if ( shdr == NULL )
626 {
627 PERROR("Could not get section header for .xen_prstatus");
628 goto out;
629 }
630 filesz = sizeof(ctxt[0].c) * nr_vcpus;
631 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
632 SHT_PROGBITS, offset, filesz,
633 __alignof__(ctxt[0].c), sizeof(ctxt[0].c));
634 if ( sts != 0 )
635 goto out;
636 offset += filesz;
638 /* arch context */
639 sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab,
640 &filesz, offset);
641 if ( sts != 0 )
642 goto out;
643 offset += filesz;
645 /* shared_info */
646 if ( live_shinfo != NULL )
647 {
648 shdr = xc_core_shdr_get(sheaders);
649 if ( shdr == NULL )
650 {
651 PERROR("Could not get section header for .xen_shared_info");
652 goto out;
653 }
654 filesz = PAGE_SIZE;
655 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
656 SHT_PROGBITS, offset, filesz,
657 __alignof__(*live_shinfo), PAGE_SIZE);
658 if ( sts != 0 )
659 goto out;
660 offset += filesz;
661 }
663 /*
664 * pages and p2m/pfn are the last section to allocate section headers
665 * so that we know the number of section headers here.
666 * 2 = pages section and p2m/pfn table section
667 */
668 fixup = (sheaders->num + 2) * sizeof(*shdr);
669 /* zeroth section should have zero offset */
670 for ( i = 1; i < sheaders->num; i++ )
671 sheaders->shdrs[i].sh_offset += fixup;
672 offset += fixup;
673 dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
674 offset += dummy_len;
676 /* pages */
677 shdr = xc_core_shdr_get(sheaders);
678 if ( shdr == NULL )
679 {
680 PERROR("could not get section headers for .xen_pages");
681 goto out;
682 }
683 filesz = (uint64_t)nr_pages * PAGE_SIZE;
684 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
685 offset, filesz, PAGE_SIZE, PAGE_SIZE);
686 if ( sts != 0 )
687 goto out;
688 offset += filesz;
690 /* p2m/pfn table */
691 shdr = xc_core_shdr_get(sheaders);
692 if ( shdr == NULL )
693 {
694 PERROR("Could not get section header for .xen_{p2m, pfn} table");
695 goto out;
696 }
697 if ( !auto_translated_physmap )
698 {
699 filesz = (uint64_t)nr_pages * sizeof(p2m_array[0]);
700 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M,
701 SHT_PROGBITS,
702 offset, filesz, __alignof__(p2m_array[0]),
703 sizeof(p2m_array[0]));
704 }
705 else
706 {
707 filesz = (uint64_t)nr_pages * sizeof(pfn_array[0]);
708 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN,
709 SHT_PROGBITS,
710 offset, filesz, __alignof__(pfn_array[0]),
711 sizeof(pfn_array[0]));
712 }
713 if ( sts != 0 )
714 goto out;
715 offset += filesz;
717 /* fixing up section header string table section header */
718 filesz = strtab->length;
719 sheaders->shdrs[strtab_idx].sh_offset = offset;
720 sheaders->shdrs[strtab_idx].sh_size = filesz;
722 /* write out elf header */
723 ehdr.e_shnum = sheaders->num;
724 ehdr.e_shstrndx = strtab_idx;
725 ehdr.e_machine = ELF_ARCH_MACHINE;
726 sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr));
727 if ( sts != 0 )
728 goto out;
730 /* section headers */
731 sts = dump_rtn(args, (char*)sheaders->shdrs,
732 sheaders->num * sizeof(sheaders->shdrs[0]));
733 if ( sts != 0 )
734 goto out;
736 /* elf note section: xen core header */
737 sts = elfnote_dump_none(args, dump_rtn);
738 if ( sts != 0 )
739 goto out;
741 /* elf note section: xen core header */
742 sts = elfnote_dump_core_header(args, dump_rtn, &info, nr_vcpus, nr_pages);
743 if ( sts != 0 )
744 goto out;
746 /* elf note section: xen version */
747 sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle, guest_width);
748 if ( sts != 0 )
749 goto out;
751 /* elf note section: format version */
752 sts = elfnote_dump_format_version(args, dump_rtn);
753 if ( sts != 0 )
754 goto out;
756 /* prstatus: .xen_prstatus */
757 sts = dump_rtn(args, (char *)&ctxt[0].c, sizeof(ctxt[0].c) * nr_vcpus);
758 if ( sts != 0 )
759 goto out;
761 if ( live_shinfo != NULL )
762 {
763 /* shared_info: .xen_shared_info */
764 sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE);
765 if ( sts != 0 )
766 goto out;
767 }
769 /* arch specific context */
770 sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn);
771 if ( sts != 0 )
772 goto out;
774 /* Pad the output data to page alignment. */
775 memset(dummy, 0, PAGE_SIZE);
776 sts = dump_rtn(args, dummy, dummy_len);
777 if ( sts != 0 )
778 goto out;
780 /* dump pages: .xen_pages */
781 j = 0;
782 dump_mem = dump_mem_start;
783 for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
784 {
785 uint64_t pfn_start;
786 uint64_t pfn_end;
788 pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
789 pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
790 for ( i = pfn_start; i < pfn_end; i++ )
791 {
792 uint64_t gmfn;
793 void *vaddr;
795 if ( j >= nr_pages )
796 {
797 /*
798 * When live dump-mode (-L option) is specified,
799 * guest domain may increase memory.
800 */
801 IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages);
802 goto copy_done;
803 }
805 if ( !auto_translated_physmap )
806 {
807 if ( guest_width >= sizeof(unsigned long) )
808 {
809 if ( guest_width == sizeof(unsigned long) )
810 gmfn = p2m[i];
811 else
812 gmfn = ((uint64_t *)p2m)[i];
813 if ( gmfn == INVALID_P2M_ENTRY )
814 continue;
815 }
816 else
817 {
818 gmfn = ((uint32_t *)p2m)[i];
819 if ( gmfn == (uint32_t)INVALID_P2M_ENTRY )
820 continue;
821 }
823 p2m_array[j].pfn = i;
824 p2m_array[j].gmfn = gmfn;
825 }
826 else
827 {
828 if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) )
829 continue;
831 gmfn = i;
832 pfn_array[j] = i;
833 }
835 vaddr = xc_map_foreign_range(
836 xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn);
837 if ( vaddr == NULL )
838 continue;
839 memcpy(dump_mem, vaddr, PAGE_SIZE);
840 munmap(vaddr, PAGE_SIZE);
841 dump_mem += PAGE_SIZE;
842 if ( (j + 1) % DUMP_INCREMENT == 0 )
843 {
844 sts = dump_rtn(
845 args, dump_mem_start, dump_mem - dump_mem_start);
846 if ( sts != 0 )
847 goto out;
848 dump_mem = dump_mem_start;
849 }
851 j++;
852 }
853 }
855 copy_done:
856 sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
857 if ( sts != 0 )
858 goto out;
859 if ( j < nr_pages )
860 {
861 /* When live dump-mode (-L option) is specified,
862 * guest domain may reduce memory. pad with zero pages.
863 */
864 IPRINTF("j (%ld) != nr_pages (%ld)", j, nr_pages);
865 memset(dump_mem_start, 0, PAGE_SIZE);
866 for (; j < nr_pages; j++) {
867 sts = dump_rtn(args, dump_mem_start, PAGE_SIZE);
868 if ( sts != 0 )
869 goto out;
870 if ( !auto_translated_physmap )
871 {
872 p2m_array[j].pfn = XC_CORE_INVALID_PFN;
873 p2m_array[j].gmfn = XC_CORE_INVALID_GMFN;
874 }
875 else
876 pfn_array[j] = XC_CORE_INVALID_PFN;
877 }
878 }
880 /* p2m/pfn table: .xen_p2m/.xen_pfn */
881 if ( !auto_translated_physmap )
882 sts = dump_rtn(
883 args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
884 else
885 sts = dump_rtn(
886 args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
887 if ( sts != 0 )
888 goto out;
890 /* elf section header string table: .shstrtab */
891 sts = dump_rtn(args, strtab->strings, strtab->length);
892 if ( sts != 0 )
893 goto out;
895 sts = 0;
897 out:
898 if ( memory_map != NULL )
899 free(memory_map);
900 if ( p2m != NULL )
901 munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
902 if ( p2m_array != NULL )
903 free(p2m_array);
904 if ( pfn_array != NULL )
905 free(pfn_array);
906 if ( sheaders != NULL )
907 xc_core_shdr_free(sheaders);
908 if ( strtab != NULL )
909 xc_core_strtab_free(strtab);
910 if ( ctxt != NULL )
911 free(ctxt);
912 if ( dump_mem_start != NULL )
913 free(dump_mem_start);
914 if ( live_shinfo != NULL )
915 munmap(live_shinfo, PAGE_SIZE);
916 xc_core_arch_context_free(&arch_ctxt);
918 return sts;
919 }
921 /* Callback args for writing to a local dump file. */
922 struct dump_args {
923 int fd;
924 };
926 /* Callback routine for writing to a local dump file. */
927 static int local_file_dump(void *args, char *buffer, unsigned int length)
928 {
929 struct dump_args *da = args;
931 if ( write_exact(da->fd, buffer, length) == -1 )
932 {
933 PERROR("Failed to write buffer");
934 return -errno;
935 }
937 if ( length >= (DUMP_INCREMENT * PAGE_SIZE) )
938 {
939 // Now dumping pages -- make sure we discard clean pages from
940 // the cache after each write
941 discard_file_cache(da->fd, 0 /* no flush */);
942 }
944 return 0;
945 }
947 int
948 xc_domain_dumpcore(int xc_handle,
949 uint32_t domid,
950 const char *corename)
951 {
952 struct dump_args da;
953 int sts;
955 if ( (da.fd = open(corename, O_CREAT|O_RDWR|O_TRUNC, S_IWUSR|S_IRUSR)) < 0 )
956 {
957 PERROR("Could not open corefile %s", corename);
958 return -errno;
959 }
961 sts = xc_domain_dumpcore_via_callback(
962 xc_handle, domid, &da, &local_file_dump);
964 /* flush and discard any remaining portion of the file from cache */
965 discard_file_cache(da.fd, 1/* flush first*/);
967 close(da.fd);
969 return sts;
970 }
972 /*
973 * Local variables:
974 * mode: C
975 * c-set-style: "BSD"
976 * c-basic-offset: 4
977 * tab-width: 4
978 * indent-tabs-mode: nil
979 * End:
980 */