|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] tools/libs: move xc_core* from libxenctrl to libxenguest
commit 455790573d3bbad6d5a1bb7e9d28b6dd71075693
Author: Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Fri Jun 4 08:02:13 2021 +0200
Commit: Julien Grall <jgrall@xxxxxxxxxx>
CommitDate: Fri Jun 4 18:56:46 2021 +0100
tools/libs: move xc_core* from libxenctrl to libxenguest
The functionality in xc_core* should be part of libxenguest instead
of libxenctrl. Users are already either in libxenguest, or in xl.
There is one single exception: xc_core_arch_auto_translated_physmap()
is being used by xc_domain_memory_mapping(), which is used by qemu.
So leave the xc_core_arch_auto_translated_physmap() functionality in
libxenctrl.
This will make it easier to merge common functionality of xc_core*
and xg_sr_save*.
Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
Acked-by: Wei Liu <wl@xxxxxxx>
---
tools/libs/ctrl/Makefile | 3 -
tools/libs/ctrl/xc_core.c | 1027 ------------------------------------
tools/libs/ctrl/xc_core.h | 176 ------
tools/libs/ctrl/xc_core_arm.c | 113 ----
tools/libs/ctrl/xc_core_arm.h | 59 ---
tools/libs/ctrl/xc_core_x86.c | 391 --------------
tools/libs/ctrl/xc_core_x86.h | 60 ---
tools/libs/ctrl/xc_domain.c | 2 -
tools/libs/ctrl/xc_private.h | 12 +
tools/libs/guest/Makefile | 3 +
tools/libs/guest/xg_core.c | 1027 ++++++++++++++++++++++++++++++++++++
tools/libs/guest/xg_core.h | 175 ++++++
tools/libs/guest/xg_core_arm.c | 107 ++++
tools/libs/guest/xg_core_arm.h | 59 +++
tools/libs/guest/xg_core_x86.c | 385 ++++++++++++++
tools/libs/guest/xg_core_x86.h | 60 +++
tools/libs/guest/xg_dom_boot.c | 2 +-
tools/libs/guest/xg_domain.c | 2 +-
tools/libs/guest/xg_offline_page.c | 2 +-
tools/libs/guest/xg_resume.c | 2 +-
20 files changed, 1832 insertions(+), 1835 deletions(-)
diff --git a/tools/libs/ctrl/Makefile b/tools/libs/ctrl/Makefile
index fbeb3a3537..519246b0d6 100644
--- a/tools/libs/ctrl/Makefile
+++ b/tools/libs/ctrl/Makefile
@@ -2,9 +2,6 @@ XEN_ROOT = $(CURDIR)/../../..
include $(XEN_ROOT)/tools/Rules.mk
SRCS-y += xc_altp2m.c
-SRCS-y += xc_core.c
-SRCS-$(CONFIG_X86) += xc_core_x86.c
-SRCS-$(CONFIG_ARM) += xc_core_arm.c
SRCS-y += xc_cpupool.c
SRCS-y += xc_domain.c
SRCS-y += xc_evtchn.c
diff --git a/tools/libs/ctrl/xc_core.c b/tools/libs/ctrl/xc_core.c
deleted file mode 100644
index 9576bec5a3..0000000000
--- a/tools/libs/ctrl/xc_core.c
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*
- * Elf format, (pfn, gmfn) table, IA64 support.
- * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * xen dump-core file format follows ELF format specification.
- * Analisys tools shouldn't depends on the order of sections.
- * They should follow elf header and check section names.
- *
- * +--------------------------------------------------------+
- * |ELF header |
- * +--------------------------------------------------------+
- * |section headers |
- * | null section header |
- * | .shstrtab |
- * | .note.Xen |
- * | .xen_prstatus |
- * | .xen_shared_info if present |
- * | .xen_pages |
- * | .xen_p2m or .xen_pfn |
- * +--------------------------------------------------------+
- * |.note.Xen:note section |
- * | "Xen" is used as note name, |
- * | types are defined in xen/include/public/elfnote.h |
- * | and descriptors are defined in xc_core.h. |
- * | dumpcore none |
- * | dumpcore header |
- * | dumpcore xen version |
- * | dumpcore format version |
- * +--------------------------------------------------------+
- * |.xen_prstatus |
- * | vcpu_guest_context_t[nr_vcpus] |
- * +--------------------------------------------------------+
- * |.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] |
- * +--------------------------------------------------------+
- * |.shstrtab: section header string table |
- * +--------------------------------------------------------+
- *
- */
-
-#include "xc_private.h"
-#include "xc_core.h"
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <xen/libelf/libelf.h>
-
-/* number of pages to write at a time */
-#define DUMP_INCREMENT (4 * 1024)
-
-/* string table */
-struct xc_core_strtab {
- char *strings;
- uint16_t length;
- uint16_t max;
-};
-
-static struct xc_core_strtab*
-xc_core_strtab_init(xc_interface *xch)
-{
- struct xc_core_strtab *strtab;
- char *strings;
- strtab = malloc(sizeof(*strtab));
- if ( strtab == NULL )
- return NULL;
-
- strings = malloc(PAGE_SIZE);
- if ( strings == NULL )
- {
- PERROR("Could not allocate string table init");
- free(strtab);
- return NULL;
- }
- strtab->strings = strings;
- strtab->max = PAGE_SIZE;
-
- /* index 0 represents none */
- strtab->strings[0] = '\0';
- strtab->length = 1;
-
- return strtab;
-}
-
-static void
-xc_core_strtab_free(struct xc_core_strtab *strtab)
-{
- free(strtab->strings);
- free(strtab);
-}
-
-static uint16_t
-xc_core_strtab_get(xc_interface *xch, struct xc_core_strtab *strtab, const
char *name)
-{
- uint16_t ret = 0;
- uint16_t len = strlen(name) + 1;
-
- if ( strtab->length > UINT16_MAX - len )
- {
- PERROR("too long string table");
- errno = E2BIG;
- return ret;
- }
-
- if ( strtab->length + len > strtab->max )
- {
- char *tmp;
- if ( strtab->max > UINT16_MAX / 2 )
- {
- PERROR("too long string table");
- errno = ENOMEM;
- return ret;
- }
-
- tmp = realloc(strtab->strings, strtab->max * 2);
- if ( tmp == NULL )
- {
- PERROR("Could not allocate string table");
- return ret;
- }
-
- strtab->strings = tmp;
- strtab->max *= 2;
- }
-
- ret = strtab->length;
- strcpy(strtab->strings + strtab->length, name);
- strtab->length += len;
- return ret;
-}
-
-
-/* section headers */
-struct xc_core_section_headers {
- uint16_t num;
- uint16_t num_max;
-
- Elf64_Shdr *shdrs;
-};
-#define SHDR_INIT ((uint16_t)16)
-#define SHDR_INC ((uint16_t)4)
-
-static struct xc_core_section_headers*
-xc_core_shdr_init(xc_interface *xch)
-{
- struct xc_core_section_headers *sheaders;
- sheaders = malloc(sizeof(*sheaders));
- if ( sheaders == NULL )
- return NULL;
-
- sheaders->num = 0;
- sheaders->num_max = SHDR_INIT;
- sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
- if ( sheaders->shdrs == NULL )
- {
- free(sheaders);
- return NULL;
- }
- return sheaders;
-}
-
-static void
-xc_core_shdr_free(struct xc_core_section_headers *sheaders)
-{
- free(sheaders->shdrs);
- free(sheaders);
-}
-
-Elf64_Shdr*
-xc_core_shdr_get(xc_interface *xch,
- struct xc_core_section_headers *sheaders)
-{
- Elf64_Shdr *shdr;
-
- if ( sheaders->num == sheaders->num_max )
- {
- Elf64_Shdr *shdrs;
- if ( sheaders->num_max > UINT16_MAX - SHDR_INC )
- {
- errno = E2BIG;
- return NULL;
- }
- sheaders->num_max += SHDR_INC;
- shdrs = realloc(sheaders->shdrs,
- sizeof(sheaders->shdrs[0]) * sheaders->num_max);
- if ( shdrs == NULL )
- return NULL;
- sheaders->shdrs = shdrs;
- }
-
- shdr = &sheaders->shdrs[sheaders->num];
- sheaders->num++;
- memset(shdr, 0, sizeof(*shdr));
- return shdr;
-}
-
-int
-xc_core_shdr_set(xc_interface *xch,
- Elf64_Shdr *shdr,
- struct xc_core_strtab *strtab,
- const char *name, uint32_t type,
- uint64_t offset, uint64_t size,
- uint64_t addralign, uint64_t entsize)
-{
- uint64_t name_idx = xc_core_strtab_get(xch, strtab, name);
- if ( name_idx == 0 )
- return -1;
-
- shdr->sh_name = name_idx;
- shdr->sh_type = type;
- shdr->sh_offset = offset;
- shdr->sh_size = size;
- shdr->sh_addralign = addralign;
- shdr->sh_entsize = entsize;
- return 0;
-}
-
-static void
-xc_core_ehdr_init(Elf64_Ehdr *ehdr)
-{
- memset(ehdr, 0, sizeof(*ehdr));
- ehdr->e_ident[EI_MAG0] = ELFMAG0;
- ehdr->e_ident[EI_MAG1] = ELFMAG1;
- ehdr->e_ident[EI_MAG2] = ELFMAG2;
- ehdr->e_ident[EI_MAG3] = ELFMAG3;
- ehdr->e_ident[EI_CLASS] = ELFCLASS64;
- ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA;
- ehdr->e_ident[EI_VERSION] = EV_CURRENT;
- ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
- ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
-
- ehdr->e_type = ET_CORE;
- /* e_machine will be filled in later */
- ehdr->e_version = EV_CURRENT;
- ehdr->e_entry = 0;
- ehdr->e_phoff = 0;
- ehdr->e_shoff = sizeof(*ehdr);
- ehdr->e_flags = ELF_CORE_EFLAGS;
- ehdr->e_ehsize = sizeof(*ehdr);
- ehdr->e_phentsize = sizeof(Elf64_Phdr);
- ehdr->e_phnum = 0;
- ehdr->e_shentsize = sizeof(Elf64_Shdr);
- /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet.
- * fill it later */
-}
-
-static int
-elfnote_fill_xen_version(xc_interface *xch,
- struct xen_dumpcore_elfnote_xen_version_desc
- *xen_version)
-{
- int rc;
- memset(xen_version, 0, sizeof(*xen_version));
-
- rc = xc_version(xch, XENVER_version, NULL);
- if ( rc < 0 )
- return rc;
- xen_version->major_version = rc >> 16;
- xen_version->minor_version = rc & ((1 << 16) - 1);
-
- rc = xc_version(xch, XENVER_extraversion,
- &xen_version->extra_version);
- if ( rc < 0 )
- return rc;
-
- rc = xc_version(xch, XENVER_compile_info,
- &xen_version->compile_info);
- if ( rc < 0 )
- return rc;
-
- rc = xc_version(xch,
- XENVER_capabilities, &xen_version->capabilities);
- if ( rc < 0 )
- return rc;
-
- rc = xc_version(xch, XENVER_changeset, &xen_version->changeset);
- if ( rc < 0 )
- return rc;
-
- rc = xc_version(xch, XENVER_platform_parameters,
- &xen_version->platform_parameters);
- if ( rc < 0 )
- return rc;
-
- rc = xc_version(xch, XENVER_pagesize, NULL);
- if ( rc < 0 )
- return rc;
- xen_version->pagesize = rc;
-
- return 0;
-}
-
-static void
-elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
- *format_version)
-{
- format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
-}
-
-static void
-elfnote_init(struct elfnote *elfnote)
-{
- /* elf note section */
- memset(elfnote, 0, sizeof(*elfnote));
- elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
- strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name));
-}
-
-static int
-elfnote_dump_none(xc_interface *xch, void *args, dumpcore_rtn_t dump_rtn)
-{
- int sts;
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_none_desc none;
-
- elfnote_init(&elfnote);
- /* Avoid compile warning about constant-zero-sized memset(). */
- /*memset(&none, 0, sizeof(none));*/
-
- elfnote.descsz = sizeof(none);
- elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
- sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
- if ( sts != 0 )
- return sts;
- return dump_rtn(xch, args, (char*)&none, sizeof(none));
-}
-
-static int
-elfnote_dump_core_header(
- xc_interface *xch,
- void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info,
- int nr_vcpus, unsigned long nr_pages)
-{
- int sts;
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_header_desc header;
-
- elfnote_init(&elfnote);
- memset(&header, 0, sizeof(header));
-
- elfnote.descsz = sizeof(header);
- elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
- header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
- header.xch_nr_vcpus = nr_vcpus;
- header.xch_nr_pages = nr_pages;
- header.xch_page_size = PAGE_SIZE;
- sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
- if ( sts != 0 )
- return sts;
- return dump_rtn(xch, args, (char*)&header, sizeof(header));
-}
-
-static int
-elfnote_dump_xen_version(xc_interface *xch, void *args,
- dumpcore_rtn_t dump_rtn, unsigned int guest_width)
-{
- int sts;
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_xen_version_desc xen_version;
-
- elfnote_init(&elfnote);
- memset(&xen_version, 0, sizeof(xen_version));
-
- elfnote.descsz = sizeof(xen_version);
- elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
- elfnote_fill_xen_version(xch, &xen_version);
- if (guest_width < sizeof(unsigned long))
- {
- // 32 bit elf file format differs in pagesize's alignment
- char *p = (char *)&xen_version.pagesize;
- memmove(p - 4, p, sizeof(xen_version.pagesize));
- }
- sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
- if ( sts != 0 )
- return sts;
- return dump_rtn(xch, args, (char*)&xen_version, sizeof(xen_version));
-}
-
-static int
-elfnote_dump_format_version(xc_interface *xch,
- void *args, dumpcore_rtn_t dump_rtn)
-{
- int sts;
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_format_version_desc format_version;
-
- elfnote_init(&elfnote);
- memset(&format_version, 0, sizeof(format_version));
-
- elfnote.descsz = sizeof(format_version);
- elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
- elfnote_fill_format_version(&format_version);
- sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
- if ( sts != 0 )
- return sts;
- return dump_rtn(xch, args, (char*)&format_version, sizeof(format_version));
-}
-
-int
-xc_domain_dumpcore_via_callback(xc_interface *xch,
- uint32_t domid,
- void *args,
- dumpcore_rtn_t dump_rtn)
-{
- xc_dominfo_t info;
- shared_info_any_t *live_shinfo = NULL;
- struct domain_info_context _dinfo = {};
- struct domain_info_context *dinfo = &_dinfo;
-
- int nr_vcpus = 0;
- char *dump_mem, *dump_mem_start = NULL;
- vcpu_guest_context_any_t *ctxt = NULL;
- struct xc_core_arch_context arch_ctxt;
- char dummy[PAGE_SIZE];
- int dummy_len;
- int sts = -1;
-
- unsigned long i;
- unsigned long j;
- unsigned long nr_pages;
- unsigned long max_mfn;
-
- xc_core_memory_map_t *memory_map = NULL;
- unsigned int nr_memory_map;
- unsigned int map_idx;
-
- int auto_translated_physmap;
- xen_pfn_t *p2m = NULL;
- struct xen_dumpcore_p2m *p2m_array = NULL;
-
- uint64_t *pfn_array = NULL;
-
- Elf64_Ehdr ehdr;
- uint64_t filesz;
- uint64_t offset;
- uint64_t fixup;
-
- struct xc_core_strtab *strtab = NULL;
- uint16_t strtab_idx;
- struct xc_core_section_headers *sheaders = NULL;
- Elf64_Shdr *shdr;
-
- xc_core_arch_context_init(&arch_ctxt);
- if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
- {
- PERROR("Could not allocate dump_mem");
- goto out;
- }
-
- if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
- {
- PERROR("Could not get info for domain");
- goto out;
- }
- /* Map the shared info frame */
- live_shinfo = xc_map_foreign_range(xch, domid, PAGE_SIZE,
- PROT_READ, info.shared_info_frame);
- if ( !live_shinfo && !info.hvm )
- {
- PERROR("Couldn't map live_shinfo");
- goto out;
- }
- auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
-
- if ( !auto_translated_physmap )
-
- {
- if ( xc_domain_get_guest_width(xch, domid, &dinfo->guest_width) != 0 )
- {
- PERROR("Could not get address size for domain");
- goto out;
- }
- }
- else
- {
- /*
- * Autotranslated guest never sets guest width in the first
- * place. Force guest_width to be sizeof(unsigned long) so
- * code below functions properly.
- *
- * Here is why this is correct.
- *
- * 1. Before f969bc9fc, xc_domain_get_guest_width for HVM (x86
- * and ARM) always returned hypervisor's idea of
- * sizeof(unsigned long).
- *
- * 2. There has never been a situation in which hypervisor's
- * word width is smaller than toolstack domain's (i.e. no
- * 32bit hypervisor + 64bit toolstack).
- *
- * Predicates in code test guest_width against toolstack
- * domain's sizeof(unsigned long), so setting guest_width to
- * toolstack domain's idea of sizeof(unsigned long) matches
- * the original behaviour for HVM guests.
- */
- dinfo->guest_width = sizeof(unsigned long);
- }
-
- if ( domid != info.domid )
- {
- PERROR("Domain %d does not exist", domid);
- goto out;
- }
-
- ctxt = calloc(sizeof(*ctxt), info.max_vcpu_id + 1);
- if ( !ctxt )
- {
- PERROR("Could not allocate vcpu context array");
- goto out;
- }
-
- for ( i = 0; i <= info.max_vcpu_id; i++ )
- {
- if ( xc_vcpu_getcontext(xch, domid, i, &ctxt[nr_vcpus]) == 0 )
- {
- if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
- xch, domid) )
- continue;
- nr_vcpus++;
- }
- }
- if ( nr_vcpus == 0 )
- {
- PERROR("No VCPU context could be grabbed");
- goto out;
- }
-
- /* obtain memory map */
- sts = xc_core_arch_memory_map_get(xch, &arch_ctxt, &info,
- live_shinfo, &memory_map,
- &nr_memory_map);
- if ( sts != 0 )
- goto out;
-
- /*
- * Note: this is the *current* number of pages and may change under
- * a live dump-core. We'll just take this value, and if more pages
- * exist, we'll skip them. If there's less, then we'll just not use
- * all the array...
- *
- * We don't want to use the total potential size of the memory map
- * since that is usually much higher than info.nr_pages.
- */
- nr_pages = info.nr_pages;
-
- if ( !auto_translated_physmap )
- {
- /* obtain p2m table */
- p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
- if ( p2m_array == NULL )
- {
- PERROR("Could not allocate p2m array");
- goto out;
- }
-
- sts = xc_core_arch_map_p2m(xch, dinfo, &info, live_shinfo, &p2m);
- if ( sts != 0 )
- goto out;
-
- sts = xc_maximum_ram_page(xch, &max_mfn);
- if ( sts != 0 )
- goto out;
- }
- else
- {
- pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
- if ( pfn_array == NULL )
- {
- PERROR("Could not allocate pfn array");
- goto out;
- }
- }
-
- /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
- xc_core_ehdr_init(&ehdr);
-
- /* create section header */
- strtab = xc_core_strtab_init(xch);
- if ( strtab == NULL )
- {
- PERROR("Could not allocate string table");
- goto out;
- }
- sheaders = xc_core_shdr_init(xch);
- if ( sheaders == NULL )
- {
- PERROR("Could not allocate section headers");
- goto out;
- }
- /* null section */
- shdr = xc_core_shdr_get(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("Could not get section header for null section");
- goto out;
- }
-
- /* .shstrtab */
- shdr = xc_core_shdr_get(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("Could not get section header for shstrtab");
- goto out;
- }
- strtab_idx = shdr - sheaders->shdrs;
- /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
- * fill it later
- */
- sts = xc_core_shdr_set(xch, shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0,
0, 0);
- if ( sts != 0 )
- goto out;
-
- /* elf note section */
- /* here the number of section header is unknown. fix up offset later. */
- offset = sizeof(ehdr);
- filesz =
- sizeof(struct xen_dumpcore_elfnote_none) + /* none */
- sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
- sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
- sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
- shdr = xc_core_shdr_get(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("Could not get section header for note section");
- goto out;
- }
- sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
- offset, filesz, 0, 0);
- if ( sts != 0 )
- goto out;
- offset += filesz;
-
- /* prstatus */
- shdr = xc_core_shdr_get(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("Could not get section header for .xen_prstatus");
- goto out;
- }
- filesz = sizeof(*ctxt) * nr_vcpus;
- sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
- SHT_PROGBITS, offset, filesz,
- __alignof__(*ctxt), sizeof(*ctxt));
- if ( sts != 0 )
- goto out;
- offset += filesz;
-
- /* arch context */
- sts = xc_core_arch_context_get_shdr(xch, &arch_ctxt, sheaders, strtab,
- &filesz, offset);
- if ( sts != 0 )
- goto out;
- offset += filesz;
-
- /* shared_info */
- if ( live_shinfo != NULL )
- {
- shdr = xc_core_shdr_get(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("Could not get section header for .xen_shared_info");
- goto out;
- }
- filesz = PAGE_SIZE;
- sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
- SHT_PROGBITS, offset, filesz,
- __alignof__(*live_shinfo), PAGE_SIZE);
- if ( sts != 0 )
- goto out;
- offset += filesz;
- }
-
- /*
- * 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 + 2) * sizeof(*shdr);
- /* zeroth section should have zero offset */
- for ( i = 1; i < sheaders->num; i++ )
- sheaders->shdrs[i].sh_offset += fixup;
- offset += fixup;
- dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
- offset += dummy_len;
-
- /* pages */
- shdr = xc_core_shdr_get(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("could not get section headers for .xen_pages");
- goto out;
- }
- filesz = (uint64_t)nr_pages * PAGE_SIZE;
- sts = xc_core_shdr_set(xch, 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(xch,sheaders);
- if ( shdr == NULL )
- {
- PERROR("Could not get section header for .xen_{p2m, pfn} table");
- goto out;
- }
- if ( !auto_translated_physmap )
- {
- filesz = (uint64_t)nr_pages * sizeof(p2m_array[0]);
- sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_P2M,
- SHT_PROGBITS,
- offset, filesz, __alignof__(p2m_array[0]),
- sizeof(p2m_array[0]));
- }
- else
- {
- filesz = (uint64_t)nr_pages * sizeof(pfn_array[0]);
- sts = xc_core_shdr_set(xch, 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;
-
- /* fixing up section header string table section header */
- filesz = strtab->length;
- sheaders->shdrs[strtab_idx].sh_offset = offset;
- sheaders->shdrs[strtab_idx].sh_size = filesz;
-
- /* write out elf header */
- ehdr.e_shnum = sheaders->num;
- ehdr.e_shstrndx = strtab_idx;
- ehdr.e_machine = ELF_ARCH_MACHINE;
- sts = dump_rtn(xch, args, (char*)&ehdr, sizeof(ehdr));
- if ( sts != 0 )
- goto out;
-
- /* section headers */
- sts = dump_rtn(xch, args, (char*)sheaders->shdrs,
- sheaders->num * sizeof(sheaders->shdrs[0]));
- if ( sts != 0 )
- goto out;
-
- /* elf note section: xen core header */
- sts = elfnote_dump_none(xch, args, dump_rtn);
- if ( sts != 0 )
- goto out;
-
- /* elf note section: xen core header */
- sts = elfnote_dump_core_header(xch, args, dump_rtn, &info, nr_vcpus,
nr_pages);
- if ( sts != 0 )
- goto out;
-
- /* elf note section: xen version */
- sts = elfnote_dump_xen_version(xch, args, dump_rtn, dinfo->guest_width);
- if ( sts != 0 )
- goto out;
-
- /* elf note section: format version */
- sts = elfnote_dump_format_version(xch, args, dump_rtn);
- if ( sts != 0 )
- goto out;
-
- /* prstatus: .xen_prstatus */
- sts = dump_rtn(xch, args, (char *)ctxt, sizeof(*ctxt) * nr_vcpus);
- if ( sts != 0 )
- goto out;
-
- if ( live_shinfo != NULL )
- {
- /* shared_info: .xen_shared_info */
- sts = dump_rtn(xch, args, (char*)live_shinfo, PAGE_SIZE);
- if ( sts != 0 )
- goto out;
- }
-
- /* arch specific context */
- sts = xc_core_arch_context_dump(xch, &arch_ctxt, args, dump_rtn);
- if ( sts != 0 )
- goto out;
-
- /* Pad the output data to page alignment. */
- memset(dummy, 0, PAGE_SIZE);
- sts = dump_rtn(xch, args, dummy, dummy_len);
- if ( sts != 0 )
- goto out;
-
- /* dump pages: .xen_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++ )
- {
- uint64_t gmfn;
- void *vaddr;
-
- if ( !auto_translated_physmap )
- {
- if ( i >= dinfo->p2m_size )
- break;
-
- if ( dinfo->guest_width >= sizeof(unsigned long) )
- {
- if ( dinfo->guest_width == sizeof(unsigned long) )
- gmfn = p2m[i];
- else
- gmfn = ((uint64_t *)p2m)[i];
- if ( gmfn == INVALID_PFN )
- continue;
- }
- else
- {
- gmfn = ((uint32_t *)p2m)[i];
- if ( gmfn == (uint32_t)INVALID_PFN )
- continue;
- }
- if ( gmfn > max_mfn )
- continue;
-
- if ( j >= nr_pages )
- {
- j++;
- continue;
- }
-
- p2m_array[j].pfn = i;
- p2m_array[j].gmfn = gmfn;
- }
- else
- {
- if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) )
- continue;
-
- if ( j >= nr_pages )
- {
- j++;
- continue;
- }
-
- gmfn = i;
- pfn_array[j] = i;
- }
-
- vaddr = xc_map_foreign_range(
- xch, 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(
- xch, args, dump_mem_start, dump_mem - dump_mem_start);
- if ( sts != 0 )
- goto out;
- dump_mem = dump_mem_start;
- }
-
- j++;
- }
- }
-
- if ( j > nr_pages )
- {
- /*
- * When live dump-mode (-L option) is specified,
- * guest domain may increase memory.
- */
- IPRINTF("exceeded nr_pages (%ld) losing %ld pages", nr_pages, j -
nr_pages);
- }
-
- sts = dump_rtn(xch, 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.
- */
- DPRINTF("j (%ld) != nr_pages (%ld)", j, nr_pages);
- memset(dump_mem_start, 0, PAGE_SIZE);
- for (; j < nr_pages; j++) {
- sts = dump_rtn(xch, args, dump_mem_start, PAGE_SIZE);
- if ( sts != 0 )
- goto out;
- 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(
- xch, args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
- else
- sts = dump_rtn(
- xch, args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
- if ( sts != 0 )
- goto out;
-
- /* elf section header string table: .shstrtab */
- sts = dump_rtn(xch, args, strtab->strings, strtab->length);
- if ( sts != 0 )
- goto out;
-
- sts = 0;
-
-out:
- if ( memory_map != NULL )
- free(memory_map);
- if ( p2m != NULL )
- munmap(p2m, PAGE_SIZE * dinfo->p2m_frames);
- if ( p2m_array != NULL )
- free(p2m_array);
- if ( pfn_array != NULL )
- free(pfn_array);
- if ( sheaders != NULL )
- xc_core_shdr_free(sheaders);
- if ( strtab != NULL )
- xc_core_strtab_free(strtab);
- if ( ctxt != NULL )
- free(ctxt);
- if ( dump_mem_start != NULL )
- free(dump_mem_start);
- if ( live_shinfo != NULL )
- munmap(live_shinfo, PAGE_SIZE);
- xc_core_arch_context_free(&arch_ctxt);
-
- return sts;
-}
-
-/* Callback args for writing to a local dump file. */
-struct dump_args {
- int fd;
-};
-
-/* Callback routine for writing to a local dump file. */
-static int local_file_dump(xc_interface *xch,
- void *args, char *buffer, unsigned int length)
-{
- struct dump_args *da = args;
-
- if ( write_exact(da->fd, buffer, length) == -1 )
- {
- PERROR("Failed to write buffer");
- return -errno;
- }
-
- if ( length >= (DUMP_INCREMENT * PAGE_SIZE) )
- {
- // Now dumping pages -- make sure we discard clean pages from
- // the cache after each write
- discard_file_cache(xch, da->fd, 0 /* no flush */);
- }
-
- return 0;
-}
-
-int
-xc_domain_dumpcore(xc_interface *xch,
- uint32_t domid,
- const char *corename)
-{
- struct dump_args da;
- int sts;
-
- if ( (da.fd = open(corename, O_CREAT|O_RDWR|O_TRUNC, S_IWUSR|S_IRUSR)) < 0
)
- {
- PERROR("Could not open corefile %s", corename);
- return -errno;
- }
-
- sts = xc_domain_dumpcore_via_callback(
- xch, domid, &da, &local_file_dump);
-
- /* flush and discard any remaining portion of the file from cache */
- discard_file_cache(xch, da.fd, 1/* flush first*/);
-
- close(da.fd);
-
- return sts;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libs/ctrl/xc_core.h b/tools/libs/ctrl/xc_core.h
deleted file mode 100644
index 8ea1f93a10..0000000000
--- a/tools/libs/ctrl/xc_core.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef XC_CORE_H
-#define XC_CORE_H
-
-#include "xen/version.h"
-#include "xc_private.h"
-#include "xen/libelf/elfstructs.h"
-
-/* section names */
-#define XEN_DUMPCORE_SEC_NOTE ".note.Xen"
-#define XEN_DUMPCORE_SEC_PRSTATUS ".xen_prstatus"
-#define XEN_DUMPCORE_SEC_SHARED_INFO ".xen_shared_info"
-#define XEN_DUMPCORE_SEC_P2M ".xen_p2m"
-#define XEN_DUMPCORE_SEC_PFN ".xen_pfn"
-#define XEN_DUMPCORE_SEC_PAGES ".xen_pages"
-
-/* elf note name */
-#define XEN_DUMPCORE_ELFNOTE_NAME "Xen"
-/* note numbers are defined in xen/elfnote.h */
-
-struct elfnote {
- uint32_t namesz; /* Elf_Note note; */
- uint32_t descsz;
- uint32_t type;
- char name[4]; /* sizeof("Xen") = 4
- * Fotunately this is 64bit aligned so that
- * we can use same structore for both 32/64bit
- */
-};
-
-struct xen_dumpcore_elfnote_none_desc {
- /* nothing */
-};
-
-struct xen_dumpcore_elfnote_header_desc {
- uint64_t xch_magic;
- uint64_t xch_nr_vcpus;
- uint64_t xch_nr_pages;
- uint64_t xch_page_size;
-};
-
-struct xen_dumpcore_elfnote_xen_version_desc {
- uint64_t major_version;
- uint64_t minor_version;
- xen_extraversion_t extra_version;
- xen_compile_info_t compile_info;
- xen_capabilities_info_t capabilities;
- xen_changeset_info_t changeset;
- xen_platform_parameters_t platform_parameters;
- uint64_t pagesize;
-};
-
-#define XEN_DUMPCORE_FORMAT_VERSION(major, minor) \
- ((major) << 32) | ((minor) & 0xffffffff)
-#define XEN_DUMPCORE_FORMAT_MAJOR(version) ((major) >> 32)
-#define XEN_DUMPCORE_FORMAT_MINOR(version) ((minor) & 0xffffffff)
-
-#define XEN_DUMPCORE_FORMAT_MAJOR_CURRENT ((uint64_t)0)
-#define XEN_DUMPCORE_FORMAT_MINOR_CURRENT ((uint64_t)1)
-#define XEN_DUMPCORE_FORMAT_VERSION_CURRENT \
- XEN_DUMPCORE_FORMAT_VERSION(XEN_DUMPCORE_FORMAT_MAJOR_CURRENT, \
- XEN_DUMPCORE_FORMAT_MINOR_CURRENT)
-
-struct xen_dumpcore_elfnote_format_version_desc {
- uint64_t version;
-};
-
-
-struct xen_dumpcore_elfnote_none {
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_none_desc none;
-};
-
-struct xen_dumpcore_elfnote_header {
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_header_desc header;
-};
-
-struct xen_dumpcore_elfnote_xen_version {
- struct elfnote elfnote;
- struct xen_dumpcore_elfnote_xen_version_desc xen_version;
-};
-
-struct xen_dumpcore_elfnote_format_version {
- struct elfnote elfnote;
- 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;
-};
-
-
-struct xc_core_strtab;
-struct xc_core_section_headers;
-
-Elf64_Shdr*
-xc_core_shdr_get(xc_interface *xch,
- struct xc_core_section_headers *sheaders);
-int
-xc_core_shdr_set(xc_interface *xch,
- Elf64_Shdr *shdr,
- struct xc_core_strtab *strtab,
- const char *name, uint32_t type,
- uint64_t offset, uint64_t size,
- uint64_t addralign, uint64_t entsize);
-
-struct xc_core_memory_map {
- uint64_t addr;
- uint64_t size;
-};
-typedef struct xc_core_memory_map xc_core_memory_map_t;
-int xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info);
-struct xc_core_arch_context;
-int xc_core_arch_memory_map_get(xc_interface *xch,
- struct xc_core_arch_context *arch_ctxt,
- xc_dominfo_t *info, shared_info_any_t
*live_shinfo,
- xc_core_memory_map_t **mapp,
- unsigned int *nr_entries);
-int xc_core_arch_map_p2m(xc_interface *xch, struct domain_info_context *dinfo,
- xc_dominfo_t *info, shared_info_any_t *live_shinfo,
- xen_pfn_t **live_p2m);
-
-int xc_core_arch_map_p2m_writable(xc_interface *xch, struct
domain_info_context *dinfo,
- xc_dominfo_t *info,
- shared_info_any_t *live_shinfo,
- xen_pfn_t **live_p2m);
-
-int xc_core_arch_get_scratch_gpfn(xc_interface *xch, uint32_t domid,
- xen_pfn_t *gpfn);
-
-
-#if defined (__i386__) || defined (__x86_64__)
-# include "xc_core_x86.h"
-#elif defined (__arm__) || defined(__aarch64__)
-# include "xc_core_arm.h"
-#else
-# error "unsupported architecture"
-#endif
-
-#ifndef ELF_CORE_EFLAGS
-# define ELF_CORE_EFLAGS 0
-#endif
-
-#endif /* XC_CORE_H */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libs/ctrl/xc_core_arm.c b/tools/libs/ctrl/xc_core_arm.c
deleted file mode 100644
index 93765a565f..0000000000
--- a/tools/libs/ctrl/xc_core_arm.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (c) 2011 Citrix Systems
- *
- */
-
-#include "xc_private.h"
-#include "xc_core.h"
-
-#include <xen-tools/libs.h>
-
-int
-xc_core_arch_gpfn_may_present(struct xc_core_arch_context *arch_ctxt,
- unsigned long pfn)
-{
- /* TODO: memory from DT */
- if (pfn >= 0x80000 && pfn < 0x88000)
- return 1;
- return 0;
-}
-
-int
-xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
-{
- return 1;
-}
-
-int
-xc_core_arch_memory_map_get(xc_interface *xch, struct xc_core_arch_context
*unused,
- xc_dominfo_t *info, shared_info_any_t *live_shinfo,
- xc_core_memory_map_t **mapp,
- unsigned int *nr_entries)
-{
- xen_pfn_t p2m_size = 0;
- xc_core_memory_map_t *map;
-
- if ( xc_domain_nr_gpfns(xch, info->domid, &p2m_size) < 0 )
- return -1;
-
- map = malloc(sizeof(*map));
- if ( map == NULL )
- {
- PERROR("Could not allocate memory");
- return -1;
- }
-
- map->addr = 0;
- map->size = ((uint64_t)p2m_size) << PAGE_SHIFT;
-
- *mapp = map;
- *nr_entries = 1;
- return 0;
-}
-
-static int
-xc_core_arch_map_p2m_rw(xc_interface *xch, struct domain_info_context *dinfo,
xc_dominfo_t *info,
- shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m,
int rw)
-{
- errno = ENOSYS;
- return -1;
-}
-
-int
-xc_core_arch_map_p2m(xc_interface *xch, struct domain_info_context *dinfo,
xc_dominfo_t *info,
- shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m)
-{
- return xc_core_arch_map_p2m_rw(xch, dinfo, info, live_shinfo, live_p2m, 0);
-}
-
-int
-xc_core_arch_map_p2m_writable(xc_interface *xch, struct domain_info_context
*dinfo, xc_dominfo_t *info,
- shared_info_any_t *live_shinfo, xen_pfn_t
**live_p2m)
-{
- return xc_core_arch_map_p2m_rw(xch, dinfo, info, live_shinfo, live_p2m, 1);
-}
-
-int
-xc_core_arch_get_scratch_gpfn(xc_interface *xch, uint32_t domid,
- xen_pfn_t *gpfn)
-{
- /*
- * The Grant Table region space is not used until the guest is
- * booting. Use the first page for the scratch pfn.
- */
- BUILD_BUG_ON(GUEST_GNTTAB_SIZE < XC_PAGE_SIZE);
-
- *gpfn = GUEST_GNTTAB_BASE >> XC_PAGE_SHIFT;
-
- return 0;
-}
-
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libs/ctrl/xc_core_arm.h b/tools/libs/ctrl/xc_core_arm.h
deleted file mode 100644
index 162f7a7569..0000000000
--- a/tools/libs/ctrl/xc_core_arm.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (c) 2012 Citrix Systems
- *
- */
-
-#ifndef XC_CORE_ARM_H
-#define XC_CORE_ARM_H
-
-#define ELF_ARCH_DATA ELFDATA2LSB
-#define ELF_ARCH_MACHINE EM_ARM
-
-struct xc_core_arch_context {
- /* nothing */
-};
-
-#define xc_core_arch_context_init(arch_ctxt) do {} while (0)
-#define xc_core_arch_context_free(arch_ctxt) do {} while (0)
-#define xc_core_arch_context_get(arch_ctxt, ctxt, xch, domid) \
- (0)
-#define xc_core_arch_context_dump(xch, arch_ctxt, args, dump_rtn) (0)
-
-int
-xc_core_arch_gpfn_may_present(struct xc_core_arch_context *arch_ctxt,
- unsigned long pfn);
-static inline int
-xc_core_arch_context_get_shdr(xc_interface *xch,
- struct xc_core_arch_context *arch_ctxt,
- struct xc_core_section_headers *sheaders,
- struct xc_core_strtab *strtab,
- uint64_t *filesz, uint64_t offset)
-{
- *filesz = 0;
- return 0;
-}
-
-#endif /* XC_CORE_ARM_H */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libs/ctrl/xc_core_x86.c b/tools/libs/ctrl/xc_core_x86.c
deleted file mode 100644
index c8f71d4b75..0000000000
--- a/tools/libs/ctrl/xc_core_x86.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- *
- */
-
-#include <inttypes.h>
-#include "xc_private.h"
-#include "xc_core.h"
-#include <xen/hvm/e820.h>
-
-int
-xc_core_arch_gpfn_may_present(struct xc_core_arch_context *arch_ctxt,
- unsigned long pfn)
-{
- if ((pfn >= 0xa0 && pfn < 0xc0) /* VGA hole */
- || (pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
- && pfn < (1ULL<<32) >> PAGE_SHIFT)) /* MMIO */
- return 0;
- return 1;
-}
-
-int
-xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
-{
- return info->hvm;
-}
-
-int
-xc_core_arch_memory_map_get(xc_interface *xch, struct xc_core_arch_context
*unused,
- xc_dominfo_t *info, shared_info_any_t *live_shinfo,
- xc_core_memory_map_t **mapp,
- unsigned int *nr_entries)
-{
- xen_pfn_t p2m_size = 0;
- xc_core_memory_map_t *map;
-
- if ( xc_domain_nr_gpfns(xch, info->domid, &p2m_size) < 0 )
- return -1;
-
- map = malloc(sizeof(*map));
- if ( map == NULL )
- {
- PERROR("Could not allocate memory");
- return -1;
- }
-
- map->addr = 0;
- map->size = ((uint64_t)p2m_size) << PAGE_SHIFT;
-
- *mapp = map;
- *nr_entries = 1;
- return 0;
-}
-
-static inline bool is_canonical_address(uint64_t vaddr)
-{
- return ((int64_t)vaddr >> 47) == ((int64_t)vaddr >> 63);
-}
-
-/* Virtual address ranges reserved for hypervisor. */
-#define HYPERVISOR_VIRT_START_X86_64 0xFFFF800000000000ULL
-#define HYPERVISOR_VIRT_END_X86_64 0xFFFF87FFFFFFFFFFULL
-
-#define HYPERVISOR_VIRT_START_X86_32 0x00000000F5800000ULL
-#define HYPERVISOR_VIRT_END_X86_32 0x00000000FFFFFFFFULL
-
-static xen_pfn_t *
-xc_core_arch_map_p2m_list_rw(xc_interface *xch, struct domain_info_context
*dinfo,
- uint32_t dom, shared_info_any_t *live_shinfo,
- uint64_t p2m_cr3)
-{
- uint64_t p2m_vaddr, p2m_end, mask, off;
- xen_pfn_t p2m_mfn, mfn, saved_mfn, max_pfn;
- uint64_t *ptes = NULL;
- xen_pfn_t *mfns = NULL;
- unsigned int fpp, n_pages, level, n_levels, shift,
- idx_start, idx_end, idx, saved_idx;
-
- p2m_vaddr = GET_FIELD(live_shinfo, arch.p2m_vaddr, dinfo->guest_width);
- fpp = PAGE_SIZE / dinfo->guest_width;
- dinfo->p2m_frames = (dinfo->p2m_size - 1) / fpp + 1;
- p2m_end = p2m_vaddr + dinfo->p2m_frames * PAGE_SIZE - 1;
-
- if ( dinfo->guest_width == 8 )
- {
- mask = 0x0000ffffffffffffULL;
- n_levels = 4;
- p2m_mfn = p2m_cr3 >> 12;
- if ( !is_canonical_address(p2m_vaddr) ||
- !is_canonical_address(p2m_end) ||
- p2m_end < p2m_vaddr ||
- (p2m_vaddr <= HYPERVISOR_VIRT_END_X86_64 &&
- p2m_end > HYPERVISOR_VIRT_START_X86_64) )
- {
- ERROR("Bad virtual p2m address range %#" PRIx64 "-%#" PRIx64,
- p2m_vaddr, p2m_end);
- errno = ERANGE;
- goto out;
- }
- }
- else
- {
- mask = 0x00000000ffffffffULL;
- n_levels = 3;
- if ( p2m_cr3 & ~mask )
- p2m_mfn = ~0UL;
- else
- p2m_mfn = (uint32_t)((p2m_cr3 >> 12) | (p2m_cr3 << 20));
- if ( p2m_vaddr > mask || p2m_end > mask || p2m_end < p2m_vaddr ||
- (p2m_vaddr <= HYPERVISOR_VIRT_END_X86_32 &&
- p2m_end > HYPERVISOR_VIRT_START_X86_32) )
- {
- ERROR("Bad virtual p2m address range %#" PRIx64 "-%#" PRIx64,
- p2m_vaddr, p2m_end);
- errno = ERANGE;
- goto out;
- }
- }
-
- mfns = malloc(sizeof(*mfns));
- if ( !mfns )
- {
- ERROR("Cannot allocate memory for array of %u mfns", 1);
- goto out;
- }
- mfns[0] = p2m_mfn;
- off = 0;
- saved_mfn = 0;
- idx_start = idx_end = saved_idx = 0;
-
- for ( level = n_levels; level > 0; level-- )
- {
- n_pages = idx_end - idx_start + 1;
- ptes = xc_map_foreign_pages(xch, dom, PROT_READ, mfns, n_pages);
- if ( !ptes )
- {
- PERROR("Failed to map %u page table pages for p2m list", n_pages);
- goto out;
- }
- free(mfns);
-
- shift = level * 9 + 3;
- idx_start = ((p2m_vaddr - off) & mask) >> shift;
- idx_end = ((p2m_end - off) & mask) >> shift;
- idx = idx_end - idx_start + 1;
- mfns = malloc(sizeof(*mfns) * idx);
- if ( !mfns )
- {
- ERROR("Cannot allocate memory for array of %u mfns", idx);
- goto out;
- }
-
- for ( idx = idx_start; idx <= idx_end; idx++ )
- {
- mfn = (ptes[idx] & 0x000ffffffffff000ULL) >> PAGE_SHIFT;
- if ( mfn == 0 )
- {
- ERROR("Bad mfn %#lx during page table walk for vaddr %#"
PRIx64 " at level %d of p2m list",
- mfn, off + ((uint64_t)idx << shift), level);
- errno = ERANGE;
- goto out;
- }
- mfns[idx - idx_start] = mfn;
-
- /* Maximum pfn check at level 2. Same reasoning as for p2m tree. */
- if ( level == 2 )
- {
- if ( mfn != saved_mfn )
- {
- saved_mfn = mfn;
- saved_idx = idx - idx_start;
- }
- }
- }
-
- if ( level == 2 )
- {
- if ( saved_idx == idx_end )
- saved_idx++;
- max_pfn = ((xen_pfn_t)saved_idx << 9) * fpp;
- if ( max_pfn < dinfo->p2m_size )
- {
- dinfo->p2m_size = max_pfn;
- dinfo->p2m_frames = (dinfo->p2m_size + fpp - 1) / fpp;
- p2m_end = p2m_vaddr + dinfo->p2m_frames * PAGE_SIZE - 1;
- idx_end = idx_start + saved_idx;
- }
- }
-
- munmap(ptes, n_pages * PAGE_SIZE);
- ptes = NULL;
- off = p2m_vaddr & ((mask >> shift) << shift);
- }
-
- return mfns;
-
- out:
- free(mfns);
- if ( ptes )
- munmap(ptes, n_pages * PAGE_SIZE);
-
- return NULL;
-}
-
-static xen_pfn_t *
-xc_core_arch_map_p2m_tree_rw(xc_interface *xch, struct domain_info_context
*dinfo,
- uint32_t dom, shared_info_any_t *live_shinfo)
-{
- /* Double and single indirect references to the live P2M table */
- xen_pfn_t *live_p2m_frame_list_list;
- xen_pfn_t *live_p2m_frame_list = NULL;
- /* Copies of the above. */
- xen_pfn_t *p2m_frame_list_list = NULL;
- xen_pfn_t *p2m_frame_list;
-
- int err;
- int i;
-
- live_p2m_frame_list_list =
- xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_READ,
- GET_FIELD(live_shinfo,
arch.pfn_to_mfn_frame_list_list, dinfo->guest_width));
-
- if ( !live_p2m_frame_list_list )
- {
- PERROR("Couldn't map p2m_frame_list_list (errno %d)", errno);
- goto out;
- }
-
- /* Get a local copy of the live_P2M_frame_list_list */
- if ( !(p2m_frame_list_list = malloc(PAGE_SIZE)) )
- {
- ERROR("Couldn't allocate p2m_frame_list_list array");
- goto out;
- }
- memcpy(p2m_frame_list_list, live_p2m_frame_list_list, PAGE_SIZE);
-
- /* Canonicalize guest's unsigned long vs ours */
- if ( dinfo->guest_width > sizeof(unsigned long) )
- for ( i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++ )
- if ( i < PAGE_SIZE/dinfo->guest_width )
- p2m_frame_list_list[i] = ((uint64_t *)p2m_frame_list_list)[i];
- else
- p2m_frame_list_list[i] = 0;
- else if ( dinfo->guest_width < sizeof(unsigned long) )
- for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i-- )
- p2m_frame_list_list[i] = ((uint32_t *)p2m_frame_list_list)[i];
-
- live_p2m_frame_list =
- xc_map_foreign_pages(xch, dom, PROT_READ,
- p2m_frame_list_list,
- P2M_FLL_ENTRIES);
-
- if ( !live_p2m_frame_list )
- {
- PERROR("Couldn't map p2m_frame_list");
- goto out;
- }
-
- /* Get a local copy of the live_P2M_frame_list */
- if ( !(p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) )
- {
- ERROR("Couldn't allocate p2m_frame_list array");
- goto out;
- }
- memset(p2m_frame_list, 0, P2M_TOOLS_FL_SIZE);
- memcpy(p2m_frame_list, live_p2m_frame_list, P2M_GUEST_FL_SIZE);
-
- /* Canonicalize guest's unsigned long vs ours */
- if ( dinfo->guest_width > sizeof(unsigned long) )
- for ( i = 0; i < P2M_FL_ENTRIES; i++ )
- p2m_frame_list[i] = ((uint64_t *)p2m_frame_list)[i];
- else if ( dinfo->guest_width < sizeof(unsigned long) )
- for ( i = P2M_FL_ENTRIES - 1; i >= 0; i-- )
- p2m_frame_list[i] = ((uint32_t *)p2m_frame_list)[i];
-
- dinfo->p2m_frames = P2M_FL_ENTRIES;
-
- return p2m_frame_list;
-
- out:
- err = errno;
-
- if ( live_p2m_frame_list_list )
- munmap(live_p2m_frame_list_list, PAGE_SIZE);
-
- if ( live_p2m_frame_list )
- munmap(live_p2m_frame_list, P2M_FLL_ENTRIES * PAGE_SIZE);
-
- free(p2m_frame_list_list);
-
- errno = err;
-
- return NULL;
-}
-
-static int
-xc_core_arch_map_p2m_rw(xc_interface *xch, struct domain_info_context *dinfo,
xc_dominfo_t *info,
- shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m,
int rw)
-{
- xen_pfn_t *p2m_frame_list = NULL;
- uint64_t p2m_cr3;
- uint32_t dom = info->domid;
- int ret = -1;
- int err;
-
- if ( xc_domain_nr_gpfns(xch, info->domid, &dinfo->p2m_size) < 0 )
- {
- ERROR("Could not get maximum GPFN!");
- goto out;
- }
-
- if ( dinfo->p2m_size < info->nr_pages )
- {
- ERROR("p2m_size < nr_pages -1 (%lx < %lx", dinfo->p2m_size,
info->nr_pages - 1);
- goto out;
- }
-
- p2m_cr3 = GET_FIELD(live_shinfo, arch.p2m_cr3, dinfo->guest_width);
-
- p2m_frame_list = p2m_cr3 ? xc_core_arch_map_p2m_list_rw(xch, dinfo, dom,
live_shinfo, p2m_cr3)
- : xc_core_arch_map_p2m_tree_rw(xch, dinfo, dom,
live_shinfo);
-
- if ( !p2m_frame_list )
- goto out;
-
- *live_p2m = xc_map_foreign_pages(xch, dom,
- rw ? (PROT_READ | PROT_WRITE) : PROT_READ,
- p2m_frame_list,
- dinfo->p2m_frames);
-
- if ( !*live_p2m )
- {
- PERROR("Couldn't map p2m table");
- goto out;
- }
-
- ret = 0;
-
-out:
- err = errno;
-
- free(p2m_frame_list);
-
- errno = err;
- return ret;
-}
-
-int
-xc_core_arch_map_p2m(xc_interface *xch, struct domain_info_context *dinfo,
xc_dominfo_t *info,
- shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m)
-{
- return xc_core_arch_map_p2m_rw(xch, dinfo, info, live_shinfo, live_p2m, 0);
-}
-
-int
-xc_core_arch_map_p2m_writable(xc_interface *xch, struct domain_info_context
*dinfo, xc_dominfo_t *info,
- shared_info_any_t *live_shinfo, xen_pfn_t
**live_p2m)
-{
- return xc_core_arch_map_p2m_rw(xch, dinfo, info, live_shinfo, live_p2m, 1);
-}
-
-int
-xc_core_arch_get_scratch_gpfn(xc_interface *xch, uint32_t domid,
- xen_pfn_t *gpfn)
-{
- return xc_domain_nr_gpfns(xch, domid, gpfn);
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libs/ctrl/xc_core_x86.h b/tools/libs/ctrl/xc_core_x86.h
deleted file mode 100644
index 867146b1d9..0000000000
--- a/tools/libs/ctrl/xc_core_x86.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
- * VA Linux Systems Japan K.K.
- *
- */
-
-#ifndef XC_CORE_X86_H
-#define XC_CORE_X86_H
-
-#define ELF_ARCH_DATA ELFDATA2LSB
-#define ELF_ARCH_MACHINE (dinfo->guest_width == 8 ? EM_X86_64 : EM_386)
-
-struct xc_core_arch_context {
- /* nothing */
-};
-
-#define xc_core_arch_context_init(arch_ctxt) do {} while (0)
-#define xc_core_arch_context_free(arch_ctxt) do {} while (0)
-#define xc_core_arch_context_get(arch_ctxt, ctxt, xch, domid) \
- (0)
-#define xc_core_arch_context_dump(xch, arch_ctxt, args, dump_rtn) (0)
-
-int
-xc_core_arch_gpfn_may_present(struct xc_core_arch_context *arch_ctxt,
- unsigned long pfn);
-static inline int
-xc_core_arch_context_get_shdr(xc_interface *xch,
- struct xc_core_arch_context *arch_ctxt,
- struct xc_core_section_headers *sheaders,
- struct xc_core_strtab *strtab,
- uint64_t *filesz, uint64_t offset)
-{
- *filesz = 0;
- return 0;
-}
-
-#endif /* XC_CORE_X86_H */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c
index e7cea4a17d..7d118848f1 100644
--- a/tools/libs/ctrl/xc_domain.c
+++ b/tools/libs/ctrl/xc_domain.c
@@ -19,8 +19,6 @@
* Copyright (c) 2003, K A Fraser.
*/
-#include "xc_private.h"
-#include "xc_core.h"
#include "xc_private.h"
#include <xen/memory.h>
#include <xen/hvm/hvm_op.h>
diff --git a/tools/libs/ctrl/xc_private.h b/tools/libs/ctrl/xc_private.h
index 8ebc0b59da..dff0f0289b 100644
--- a/tools/libs/ctrl/xc_private.h
+++ b/tools/libs/ctrl/xc_private.h
@@ -467,6 +467,18 @@ void *xc_vm_event_enable(xc_interface *xch, uint32_t
domain_id, int param,
int do_dm_op(xc_interface *xch, uint32_t domid, unsigned int nr_bufs, ...);
+#if defined (__i386__) || defined (__x86_64__)
+static inline int xc_core_arch_auto_translated_physmap(const xc_dominfo_t
*info)
+{
+ return info->hvm;
+}
+#elif defined (__arm__) || defined(__aarch64__)
+static inline int xc_core_arch_auto_translated_physmap(const xc_dominfo_t
*info)
+{
+ return 1;
+}
+#endif
+
#endif /* __XC_PRIVATE_H__ */
/*
diff --git a/tools/libs/guest/Makefile b/tools/libs/guest/Makefile
index 2a2323ff09..2ce92d247e 100644
--- a/tools/libs/guest/Makefile
+++ b/tools/libs/guest/Makefile
@@ -24,6 +24,9 @@ SRCS-y += xg_offline_page.c
else
SRCS-y += xg_nomigrate.c
endif
+SRCS-y += xg_core.c
+SRCS-$(CONFIG_X86) += xg_core_x86.c
+SRCS-$(CONFIG_ARM) += xg_core_arm.c
CFLAGS += -I$(XEN_libxenctrl)
diff --git a/tools/libs/guest/xg_core.c b/tools/libs/guest/xg_core.c
new file mode 100644
index 0000000000..c52f1161c1
--- /dev/null
+++ b/tools/libs/guest/xg_core.c
@@ -0,0 +1,1027 @@
+/*
+ * Elf format, (pfn, gmfn) table, IA64 support.
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * xen dump-core file format follows ELF format specification.
+ * Analisys tools shouldn't depends on the order of sections.
+ * They should follow elf header and check section names.
+ *
+ * +--------------------------------------------------------+
+ * |ELF header |
+ * +--------------------------------------------------------+
+ * |section headers |
+ * | null section header |
+ * | .shstrtab |
+ * | .note.Xen |
+ * | .xen_prstatus |
+ * | .xen_shared_info if present |
+ * | .xen_pages |
+ * | .xen_p2m or .xen_pfn |
+ * +--------------------------------------------------------+
+ * |.note.Xen:note section |
+ * | "Xen" is used as note name, |
+ * | types are defined in xen/include/public/elfnote.h |
+ * | and descriptors are defined in xc_core.h. |
+ * | dumpcore none |
+ * | dumpcore header |
+ * | dumpcore xen version |
+ * | dumpcore format version |
+ * +--------------------------------------------------------+
+ * |.xen_prstatus |
+ * | vcpu_guest_context_t[nr_vcpus] |
+ * +--------------------------------------------------------+
+ * |.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] |
+ * +--------------------------------------------------------+
+ * |.shstrtab: section header string table |
+ * +--------------------------------------------------------+
+ *
+ */
+
+#include "xc_private.h"
+#include "xg_core.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <xen/libelf/libelf.h>
+
+/* number of pages to write at a time */
+#define DUMP_INCREMENT (4 * 1024)
+
+/* string table */
+struct xc_core_strtab {
+ char *strings;
+ uint16_t length;
+ uint16_t max;
+};
+
+static struct xc_core_strtab*
+xc_core_strtab_init(xc_interface *xch)
+{
+ struct xc_core_strtab *strtab;
+ char *strings;
+ strtab = malloc(sizeof(*strtab));
+ if ( strtab == NULL )
+ return NULL;
+
+ strings = malloc(PAGE_SIZE);
+ if ( strings == NULL )
+ {
+ PERROR("Could not allocate string table init");
+ free(strtab);
+ return NULL;
+ }
+ strtab->strings = strings;
+ strtab->max = PAGE_SIZE;
+
+ /* index 0 represents none */
+ strtab->strings[0] = '\0';
+ strtab->length = 1;
+
+ return strtab;
+}
+
+static void
+xc_core_strtab_free(struct xc_core_strtab *strtab)
+{
+ free(strtab->strings);
+ free(strtab);
+}
+
+static uint16_t
+xc_core_strtab_get(xc_interface *xch, struct xc_core_strtab *strtab, const
char *name)
+{
+ uint16_t ret = 0;
+ uint16_t len = strlen(name) + 1;
+
+ if ( strtab->length > UINT16_MAX - len )
+ {
+ PERROR("too long string table");
+ errno = E2BIG;
+ return ret;
+ }
+
+ if ( strtab->length + len > strtab->max )
+ {
+ char *tmp;
+ if ( strtab->max > UINT16_MAX / 2 )
+ {
+ PERROR("too long string table");
+ errno = ENOMEM;
+ return ret;
+ }
+
+ tmp = realloc(strtab->strings, strtab->max * 2);
+ if ( tmp == NULL )
+ {
+ PERROR("Could not allocate string table");
+ return ret;
+ }
+
+ strtab->strings = tmp;
+ strtab->max *= 2;
+ }
+
+ ret = strtab->length;
+ strcpy(strtab->strings + strtab->length, name);
+ strtab->length += len;
+ return ret;
+}
+
+
+/* section headers */
+struct xc_core_section_headers {
+ uint16_t num;
+ uint16_t num_max;
+
+ Elf64_Shdr *shdrs;
+};
+#define SHDR_INIT ((uint16_t)16)
+#define SHDR_INC ((uint16_t)4)
+
+static struct xc_core_section_headers*
+xc_core_shdr_init(xc_interface *xch)
+{
+ struct xc_core_section_headers *sheaders;
+ sheaders = malloc(sizeof(*sheaders));
+ if ( sheaders == NULL )
+ return NULL;
+
+ sheaders->num = 0;
+ sheaders->num_max = SHDR_INIT;
+ sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
+ if ( sheaders->shdrs == NULL )
+ {
+ free(sheaders);
+ return NULL;
+ }
+ return sheaders;
+}
+
+static void
+xc_core_shdr_free(struct xc_core_section_headers *sheaders)
+{
+ free(sheaders->shdrs);
+ free(sheaders);
+}
+
+Elf64_Shdr*
+xc_core_shdr_get(xc_interface *xch,
+ struct xc_core_section_headers *sheaders)
+{
+ Elf64_Shdr *shdr;
+
+ if ( sheaders->num == sheaders->num_max )
+ {
+ Elf64_Shdr *shdrs;
+ if ( sheaders->num_max > UINT16_MAX - SHDR_INC )
+ {
+ errno = E2BIG;
+ return NULL;
+ }
+ sheaders->num_max += SHDR_INC;
+ shdrs = realloc(sheaders->shdrs,
+ sizeof(sheaders->shdrs[0]) * sheaders->num_max);
+ if ( shdrs == NULL )
+ return NULL;
+ sheaders->shdrs = shdrs;
+ }
+
+ shdr = &sheaders->shdrs[sheaders->num];
+ sheaders->num++;
+ memset(shdr, 0, sizeof(*shdr));
+ return shdr;
+}
+
+int
+xc_core_shdr_set(xc_interface *xch,
+ Elf64_Shdr *shdr,
+ struct xc_core_strtab *strtab,
+ const char *name, uint32_t type,
+ uint64_t offset, uint64_t size,
+ uint64_t addralign, uint64_t entsize)
+{
+ uint64_t name_idx = xc_core_strtab_get(xch, strtab, name);
+ if ( name_idx == 0 )
+ return -1;
+
+ shdr->sh_name = name_idx;
+ shdr->sh_type = type;
+ shdr->sh_offset = offset;
+ shdr->sh_size = size;
+ shdr->sh_addralign = addralign;
+ shdr->sh_entsize = entsize;
+ return 0;
+}
+
+static void
+xc_core_ehdr_init(Elf64_Ehdr *ehdr)
+{
+ memset(ehdr, 0, sizeof(*ehdr));
+ ehdr->e_ident[EI_MAG0] = ELFMAG0;
+ ehdr->e_ident[EI_MAG1] = ELFMAG1;
+ ehdr->e_ident[EI_MAG2] = ELFMAG2;
+ ehdr->e_ident[EI_MAG3] = ELFMAG3;
+ ehdr->e_ident[EI_CLASS] = ELFCLASS64;
+ ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
+ ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
+
+ ehdr->e_type = ET_CORE;
+ /* e_machine will be filled in later */
+ ehdr->e_version = EV_CURRENT;
+ ehdr->e_entry = 0;
+ ehdr->e_phoff = 0;
+ ehdr->e_shoff = sizeof(*ehdr);
+ ehdr->e_flags = ELF_CORE_EFLAGS;
+ ehdr->e_ehsize = sizeof(*ehdr);
+ ehdr->e_phentsize = sizeof(Elf64_Phdr);
+ ehdr->e_phnum = 0;
+ ehdr->e_shentsize = sizeof(Elf64_Shdr);
+ /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet.
+ * fill it later */
+}
+
+static int
+elfnote_fill_xen_version(xc_interface *xch,
+ struct xen_dumpcore_elfnote_xen_version_desc
+ *xen_version)
+{
+ int rc;
+ memset(xen_version, 0, sizeof(*xen_version));
+
+ rc = xc_version(xch, XENVER_version, NULL);
+ if ( rc < 0 )
+ return rc;
+ xen_version->major_version = rc >> 16;
+ xen_version->minor_version = rc & ((1 << 16) - 1);
+
+ rc = xc_version(xch, XENVER_extraversion,
+ &xen_version->extra_version);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xch, XENVER_compile_info,
+ &xen_version->compile_info);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xch,
+ XENVER_capabilities, &xen_version->capabilities);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xch, XENVER_changeset, &xen_version->changeset);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xch, XENVER_platform_parameters,
+ &xen_version->platform_parameters);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xch, XENVER_pagesize, NULL);
+ if ( rc < 0 )
+ return rc;
+ xen_version->pagesize = rc;
+
+ return 0;
+}
+
+static void
+elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
+ *format_version)
+{
+ format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
+}
+
+static void
+elfnote_init(struct elfnote *elfnote)
+{
+ /* elf note section */
+ memset(elfnote, 0, sizeof(*elfnote));
+ elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
+ strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name));
+}
+
+static int
+elfnote_dump_none(xc_interface *xch, void *args, dumpcore_rtn_t dump_rtn)
+{
+ int sts;
+ struct elfnote elfnote;
+ struct xen_dumpcore_elfnote_none_desc none;
+
+ elfnote_init(&elfnote);
+ /* Avoid compile warning about constant-zero-sized memset(). */
+ /*memset(&none, 0, sizeof(none));*/
+
+ elfnote.descsz = sizeof(none);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
+ sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ return sts;
+ return dump_rtn(xch, args, (char*)&none, sizeof(none));
+}
+
+static int
+elfnote_dump_core_header(
+ xc_interface *xch,
+ void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info,
+ int nr_vcpus, unsigned long nr_pages)
+{
+ int sts;
+ struct elfnote elfnote;
+ struct xen_dumpcore_elfnote_header_desc header;
+
+ elfnote_init(&elfnote);
+ memset(&header, 0, sizeof(header));
+
+ elfnote.descsz = sizeof(header);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
+ header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
+ header.xch_nr_vcpus = nr_vcpus;
+ header.xch_nr_pages = nr_pages;
+ header.xch_page_size = PAGE_SIZE;
+ sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ return sts;
+ return dump_rtn(xch, args, (char*)&header, sizeof(header));
+}
+
+static int
+elfnote_dump_xen_version(xc_interface *xch, void *args,
+ dumpcore_rtn_t dump_rtn, unsigned int guest_width)
+{
+ int sts;
+ struct elfnote elfnote;
+ struct xen_dumpcore_elfnote_xen_version_desc xen_version;
+
+ elfnote_init(&elfnote);
+ memset(&xen_version, 0, sizeof(xen_version));
+
+ elfnote.descsz = sizeof(xen_version);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
+ elfnote_fill_xen_version(xch, &xen_version);
+ if (guest_width < sizeof(unsigned long))
+ {
+ // 32 bit elf file format differs in pagesize's alignment
+ char *p = (char *)&xen_version.pagesize;
+ memmove(p - 4, p, sizeof(xen_version.pagesize));
+ }
+ sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ return sts;
+ return dump_rtn(xch, args, (char*)&xen_version, sizeof(xen_version));
+}
+
+static int
+elfnote_dump_format_version(xc_interface *xch,
+ void *args, dumpcore_rtn_t dump_rtn)
+{
+ int sts;
+ struct elfnote elfnote;
+ struct xen_dumpcore_elfnote_format_version_desc format_version;
+
+ elfnote_init(&elfnote);
+ memset(&format_version, 0, sizeof(format_version));
+
+ elfnote.descsz = sizeof(format_version);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
+ elfnote_fill_format_version(&format_version);
+ sts = dump_rtn(xch, args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ return sts;
+ return dump_rtn(xch, args, (char*)&format_version, sizeof(format_version));
+}
+
+int
+xc_domain_dumpcore_via_callback(xc_interface *xch,
+ uint32_t domid,
+ void *args,
+ dumpcore_rtn_t dump_rtn)
+{
+ xc_dominfo_t info;
+ shared_info_any_t *live_shinfo = NULL;
+ struct domain_info_context _dinfo = {};
+ struct domain_info_context *dinfo = &_dinfo;
+
+ int nr_vcpus = 0;
+ char *dump_mem, *dump_mem_start = NULL;
+ vcpu_guest_context_any_t *ctxt = NULL;
+ struct xc_core_arch_context arch_ctxt;
+ char dummy[PAGE_SIZE];
+ int dummy_len;
+ int sts = -1;
+
+ unsigned long i;
+ unsigned long j;
+ unsigned long nr_pages;
+ unsigned long max_mfn;
+
+ xc_core_memory_map_t *memory_map = NULL;
+ unsigned int nr_memory_map;
+ unsigned int map_idx;
+
+ int auto_translated_physmap;
+ xen_pfn_t *p2m = NULL;
+ struct xen_dumpcore_p2m *p2m_array = NULL;
+
+ uint64_t *pfn_array = NULL;
+
+ Elf64_Ehdr ehdr;
+ uint64_t filesz;
+ uint64_t offset;
+ uint64_t fixup;
+
+ struct xc_core_strtab *strtab = NULL;
+ uint16_t strtab_idx;
+ struct xc_core_section_headers *sheaders = NULL;
+ Elf64_Shdr *shdr;
+
+ xc_core_arch_context_init(&arch_ctxt);
+ if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
+ {
+ PERROR("Could not allocate dump_mem");
+ goto out;
+ }
+
+ if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
+ {
+ PERROR("Could not get info for domain");
+ goto out;
+ }
+ /* Map the shared info frame */
+ live_shinfo = xc_map_foreign_range(xch, domid, PAGE_SIZE,
+ PROT_READ, info.shared_info_frame);
+ if ( !live_shinfo && !info.hvm )
+ {
+ PERROR("Couldn't map live_shinfo");
+ goto out;
+ }
+ auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
+
+ if ( !auto_translated_physmap )
+
+ {
+ if ( xc_domain_get_guest_width(xch, domid, &dinfo->guest_width) != 0 )
+ {
+ PERROR("Could not get address size for domain");
+ goto out;
+ }
+ }
+ else
+ {
+ /*
+ * Autotranslated guest never sets guest width in the first
+ * place. Force guest_width to be sizeof(unsigned long) so
+ * code below functions properly.
+ *
+ * Here is why this is correct.
+ *
+ * 1. Before f969bc9fc, xc_domain_get_guest_width for HVM (x86
+ * and ARM) always returned hypervisor's idea of
+ * sizeof(unsigned long).
+ *
+ * 2. There has never been a situation in which hypervisor's
+ * word width is smaller than toolstack domain's (i.e. no
+ * 32bit hypervisor + 64bit toolstack).
+ *
+ * Predicates in code test guest_width against toolstack
+ * domain's sizeof(unsigned long), so setting guest_width to
+ * toolstack domain's idea of sizeof(unsigned long) matches
+ * the original behaviour for HVM guests.
+ */
+ dinfo->guest_width = sizeof(unsigned long);
+ }
+
+ if ( domid != info.domid )
+ {
+ PERROR("Domain %d does not exist", domid);
+ goto out;
+ }
+
+ ctxt = calloc(sizeof(*ctxt), info.max_vcpu_id + 1);
+ if ( !ctxt )
+ {
+ PERROR("Could not allocate vcpu context array");
+ goto out;
+ }
+
+ for ( i = 0; i <= info.max_vcpu_id; i++ )
+ {
+ if ( xc_vcpu_getcontext(xch, domid, i, &ctxt[nr_vcpus]) == 0 )
+ {
+ if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
+ xch, domid) )
+ continue;
+ nr_vcpus++;
+ }
+ }
+ if ( nr_vcpus == 0 )
+ {
+ PERROR("No VCPU context could be grabbed");
+ goto out;
+ }
+
+ /* obtain memory map */
+ sts = xc_core_arch_memory_map_get(xch, &arch_ctxt, &info,
+ live_shinfo, &memory_map,
+ &nr_memory_map);
+ if ( sts != 0 )
+ goto out;
+
+ /*
+ * Note: this is the *current* number of pages and may change under
+ * a live dump-core. We'll just take this value, and if more pages
+ * exist, we'll skip them. If there's less, then we'll just not use
+ * all the array...
+ *
+ * We don't want to use the total potential size of the memory map
+ * since that is usually much higher than info.nr_pages.
+ */
+ nr_pages = info.nr_pages;
+
+ if ( !auto_translated_physmap )
+ {
+ /* obtain p2m table */
+ p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
+ if ( p2m_array == NULL )
+ {
+ PERROR("Could not allocate p2m array");
+ goto out;
+ }
+
+ sts = xc_core_arch_map_p2m(xch, dinfo, &info, live_shinfo, &p2m);
+ if ( sts != 0 )
+ goto out;
+
+ sts = xc_maximum_ram_page(xch, &max_mfn);
+ if ( sts != 0 )
+ goto out;
+ }
+ else
+ {
+ pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
+ if ( pfn_array == NULL )
+ {
+ PERROR("Could not allocate pfn array");
+ goto out;
+ }
+ }
+
+ /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
+ xc_core_ehdr_init(&ehdr);
+
+ /* create section header */
+ strtab = xc_core_strtab_init(xch);
+ if ( strtab == NULL )
+ {
+ PERROR("Could not allocate string table");
+ goto out;
+ }
+ sheaders = xc_core_shdr_init(xch);
+ if ( sheaders == NULL )
+ {
+ PERROR("Could not allocate section headers");
+ goto out;
+ }
+ /* null section */
+ shdr = xc_core_shdr_get(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for null section");
+ goto out;
+ }
+
+ /* .shstrtab */
+ shdr = xc_core_shdr_get(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for shstrtab");
+ goto out;
+ }
+ strtab_idx = shdr - sheaders->shdrs;
+ /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
+ * fill it later
+ */
+ sts = xc_core_shdr_set(xch, shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0,
0, 0);
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section */
+ /* here the number of section header is unknown. fix up offset later. */
+ offset = sizeof(ehdr);
+ filesz =
+ sizeof(struct xen_dumpcore_elfnote_none) + /* none */
+ sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
+ sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
+ sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
+ shdr = xc_core_shdr_get(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for note section");
+ goto out;
+ }
+ sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
+ offset, filesz, 0, 0);
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+
+ /* prstatus */
+ shdr = xc_core_shdr_get(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for .xen_prstatus");
+ goto out;
+ }
+ filesz = sizeof(*ctxt) * nr_vcpus;
+ sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
+ SHT_PROGBITS, offset, filesz,
+ __alignof__(*ctxt), sizeof(*ctxt));
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+
+ /* arch context */
+ sts = xc_core_arch_context_get_shdr(xch, &arch_ctxt, sheaders, strtab,
+ &filesz, offset);
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+
+ /* shared_info */
+ if ( live_shinfo != NULL )
+ {
+ shdr = xc_core_shdr_get(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for .xen_shared_info");
+ goto out;
+ }
+ filesz = PAGE_SIZE;
+ sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
+ SHT_PROGBITS, offset, filesz,
+ __alignof__(*live_shinfo), PAGE_SIZE);
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+ }
+
+ /*
+ * 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 + 2) * sizeof(*shdr);
+ /* zeroth section should have zero offset */
+ for ( i = 1; i < sheaders->num; i++ )
+ sheaders->shdrs[i].sh_offset += fixup;
+ offset += fixup;
+ dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
+ offset += dummy_len;
+
+ /* pages */
+ shdr = xc_core_shdr_get(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("could not get section headers for .xen_pages");
+ goto out;
+ }
+ filesz = (uint64_t)nr_pages * PAGE_SIZE;
+ sts = xc_core_shdr_set(xch, 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(xch,sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for .xen_{p2m, pfn} table");
+ goto out;
+ }
+ if ( !auto_translated_physmap )
+ {
+ filesz = (uint64_t)nr_pages * sizeof(p2m_array[0]);
+ sts = xc_core_shdr_set(xch, shdr, strtab, XEN_DUMPCORE_SEC_P2M,
+ SHT_PROGBITS,
+ offset, filesz, __alignof__(p2m_array[0]),
+ sizeof(p2m_array[0]));
+ }
+ else
+ {
+ filesz = (uint64_t)nr_pages * sizeof(pfn_array[0]);
+ sts = xc_core_shdr_set(xch, 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;
+
+ /* fixing up section header string table section header */
+ filesz = strtab->length;
+ sheaders->shdrs[strtab_idx].sh_offset = offset;
+ sheaders->shdrs[strtab_idx].sh_size = filesz;
+
+ /* write out elf header */
+ ehdr.e_shnum = sheaders->num;
+ ehdr.e_shstrndx = strtab_idx;
+ ehdr.e_machine = ELF_ARCH_MACHINE;
+ sts = dump_rtn(xch, args, (char*)&ehdr, sizeof(ehdr));
+ if ( sts != 0 )
+ goto out;
+
+ /* section headers */
+ sts = dump_rtn(xch, args, (char*)sheaders->shdrs,
+ sheaders->num * sizeof(sheaders->shdrs[0]));
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section: xen core header */
+ sts = elfnote_dump_none(xch, args, dump_rtn);
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section: xen core header */
+ sts = elfnote_dump_core_header(xch, args, dump_rtn, &info, nr_vcpus,
nr_pages);
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section: xen version */
+ sts = elfnote_dump_xen_version(xch, args, dump_rtn, dinfo->guest_width);
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section: format version */
+ sts = elfnote_dump_format_version(xch, args, dump_rtn);
+ if ( sts != 0 )
+ goto out;
+
+ /* prstatus: .xen_prstatus */
+ sts = dump_rtn(xch, args, (char *)ctxt, sizeof(*ctxt) * nr_vcpus);
+ if ( sts != 0 )
+ goto out;
+
+ if ( live_shinfo != NULL )
+ {
+ /* shared_info: .xen_shared_info */
+ sts = dump_rtn(xch, args, (char*)live_shinfo, PAGE_SIZE);
+ if ( sts != 0 )
+ goto out;
+ }
+
+ /* arch specific context */
+ sts = xc_core_arch_context_dump(xch, &arch_ctxt, args, dump_rtn);
+ if ( sts != 0 )
+ goto out;
+
+ /* Pad the output data to page alignment. */
+ memset(dummy, 0, PAGE_SIZE);
+ sts = dump_rtn(xch, args, dummy, dummy_len);
+ if ( sts != 0 )
+ goto out;
+
+ /* dump pages: .xen_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++ )
+ {
+ uint64_t gmfn;
+ void *vaddr;
+
+ if ( !auto_translated_physmap )
+ {
+ if ( i >= dinfo->p2m_size )
+ break;
+
+ if ( dinfo->guest_width >= sizeof(unsigned long) )
+ {
+ if ( dinfo->guest_width == sizeof(unsigned long) )
+ gmfn = p2m[i];
+ else
+ gmfn = ((uint64_t *)p2m)[i];
+ if ( gmfn == INVALID_PFN )
+ continue;
+ }
+ else
+ {
+ gmfn = ((uint32_t *)p2m)[i];
+ if ( gmfn == (uint32_t)INVALID_PFN )
+ continue;
+ }
+ if ( gmfn > max_mfn )
+ continue;
+
+ if ( j >= nr_pages )
+ {
+ j++;
+ continue;
+ }
+
+ p2m_array[j].pfn = i;
+ p2m_array[j].gmfn = gmfn;
+ }
+ else
+ {
+ if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) )
+ continue;
+
+ if ( j >= nr_pages )
+ {
+ j++;
+ continue;
+ }
+
+ gmfn = i;
+ pfn_array[j] = i;
+ }
+
+ vaddr = xc_map_foreign_range(
+ xch, 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(
+ xch, args, dump_mem_start, dump_mem - dump_mem_start);
+ if ( sts != 0 )
+ goto out;
+ dump_mem = dump_mem_start;
+ }
+
+ j++;
+ }
+ }
+
+ if ( j > nr_pages )
+ {
+ /*
+ * When live dump-mode (-L option) is specified,
+ * guest domain may increase memory.
+ */
+ IPRINTF("exceeded nr_pages (%ld) losing %ld pages", nr_pages, j -
nr_pages);
+ }
+
+ sts = dump_rtn(xch, 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.
+ */
+ DPRINTF("j (%ld) != nr_pages (%ld)", j, nr_pages);
+ memset(dump_mem_start, 0, PAGE_SIZE);
+ for (; j < nr_pages; j++) {
+ sts = dump_rtn(xch, args, dump_mem_start, PAGE_SIZE);
+ if ( sts != 0 )
+ goto out;
+ 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(
+ xch, args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
+ else
+ sts = dump_rtn(
+ xch, args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
+ if ( sts != 0 )
+ goto out;
+
+ /* elf section header string table: .shstrtab */
+ sts = dump_rtn(xch, args, strtab->strings, strtab->length);
+ if ( sts != 0 )
+ goto out;
+
+ sts = 0;
+
+out:
+ if ( memory_map != NULL )
+ free(memory_map);
+ if ( p2m != NULL )
+ munmap(p2m, PAGE_SIZE * dinfo->p2m_frames);
+ if ( p2m_array != NULL )
+ free(p2m_array);
+ if ( pfn_array != NULL )
+ free(pfn_array);
+ if ( sheaders != NULL )
+ xc_core_shdr_free(sheaders);
+ if ( strtab != NULL )
+ xc_core_strtab_free(strtab);
+ if ( ctxt != NULL )
+ free(ctxt);
+ if ( dump_mem_start != NULL )
+ free(dump_mem_start);
+ if ( live_shinfo != NULL )
+ munmap(live_shinfo, PAGE_SIZE);
+ xc_core_arch_context_free(&arch_ctxt);
+
+ return sts;
+}
+
+/* Callback args for writing to a local dump file. */
+struct dump_args {
+ int fd;
+};
+
+/* Callback routine for writing to a local dump file. */
+static int local_file_dump(xc_interface *xch,
+ void *args, char *buffer, unsigned int length)
+{
+ struct dump_args *da = args;
+
+ if ( write_exact(da->fd, buffer, length) == -1 )
+ {
+ PERROR("Failed to write buffer");
+ return -errno;
+ }
+
+ if ( length >= (DUMP_INCREMENT * PAGE_SIZE) )
+ {
+ // Now dumping pages -- make sure we discard clean pages from
+ // the cache after each write
+ discard_file_cache(xch, da->fd, 0 /* no flush */);
+ }
+
+ return 0;
+}
+
+int
+xc_domain_dumpcore(xc_interface *xch,
+ uint32_t domid,
+ const char *corename)
+{
+ struct dump_args da;
+ int sts;
+
+ if ( (da.fd = open(corename, O_CREAT|O_RDWR|O_TRUNC, S_IWUSR|S_IRUSR)) < 0
)
+ {
+ PERROR("Could not open corefile %s", corename);
+ return -errno;
+ }
+
+ sts = xc_domain_dumpcore_via_callback(
+ xch, domid, &da, &local_file_dump);
+
+ /* flush and discard any remaining portion of the file from cache */
+ discard_file_cache(xch, da.fd, 1/* flush first*/);
+
+ close(da.fd);
+
+ return sts;
+}
+
+/*
+ * Local variables:
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |