diff -r 77476eeb8c42 tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Wed Jan 14 11:39:01 2009 +0000 +++ b/tools/libxc/xc_core.c Wed Jan 14 16:40:17 2009 -0700 @@ -57,9 +57,6 @@ /* number of pages to write at a time */ #define DUMP_INCREMENT (4 * 1024) - -/* Don't yet support cross-address-size core dump */ -#define guest_width (sizeof (unsigned long)) /* string table */ struct xc_core_strtab { @@ -240,7 +237,7 @@ xc_core_ehdr_init(Elf64_Ehdr *ehdr) ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT; ehdr->e_type = ET_CORE; - ehdr->e_machine = ELF_ARCH_MACHINE; + /* e_machine will be filled in later */ ehdr->e_version = EV_CURRENT; ehdr->e_entry = 0; ehdr->e_phoff = 0; @@ -359,7 +356,8 @@ elfnote_dump_core_header( } static int -elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle) +elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle, + unsigned int guest_width) { int sts; struct elfnote elfnote; @@ -371,6 +369,12 @@ elfnote_dump_xen_version(void *args, dum elfnote.descsz = sizeof(xen_version); elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION; elfnote_fill_xen_version(xc_handle, &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(args, (char*)&elfnote, sizeof(elfnote)); if ( sts != 0 ) return sts; @@ -396,6 +400,24 @@ elfnote_dump_format_version(void *args, return dump_rtn(args, (char*)&format_version, sizeof(format_version)); } +static int +get_guest_width(int xc_handle, + uint32_t domid, + unsigned int *guest_width) +{ + DECLARE_DOMCTL; + + memset(&domctl, 0, sizeof(domctl)); + domctl.domain = domid; + domctl.cmd = XEN_DOMCTL_get_address_size; + + if ( do_domctl(xc_handle, &domctl) != 0 ) + return 1; + + *guest_width = domctl.u.address_size.size / 8; + return 0; +} + int xc_domain_dumpcore_via_callback(int xc_handle, uint32_t domid, @@ -403,7 +425,8 @@ xc_domain_dumpcore_via_callback(int xc_h dumpcore_rtn_t dump_rtn) { xc_dominfo_t info; - shared_info_t *live_shinfo = NULL; + shared_info_any_t *live_shinfo = NULL; + unsigned int guest_width; int nr_vcpus = 0; char *dump_mem, *dump_mem_start = NULL; @@ -437,6 +460,12 @@ xc_domain_dumpcore_via_callback(int xc_h uint16_t strtab_idx; struct xc_core_section_headers *sheaders = NULL; Elf64_Shdr *shdr; + + if ( get_guest_width(xc_handle, domid, &guest_width) != 0 ) + { + PERROR("Could not get address size for domain"); + return sts; + } xc_core_arch_context_init(&arch_ctxt); if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL ) @@ -500,7 +529,7 @@ xc_domain_dumpcore_via_callback(int xc_h goto out; } - sts = xc_core_arch_map_p2m(xc_handle, &info, live_shinfo, + sts = xc_core_arch_map_p2m(xc_handle, guest_width, &info, live_shinfo, &p2m, &p2m_size); if ( sts != 0 ) goto out; @@ -676,6 +705,7 @@ xc_domain_dumpcore_via_callback(int xc_h /* write out elf header */ ehdr.e_shnum = sheaders->num; ehdr.e_shstrndx = strtab_idx; + ehdr.e_machine = ELF_ARCH_MACHINE; sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr)); if ( sts != 0 ) goto out; @@ -697,7 +727,7 @@ xc_domain_dumpcore_via_callback(int xc_h goto out; /* elf note section: xen version */ - sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle); + sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle, guest_width); if ( sts != 0 ) goto out; @@ -757,9 +787,21 @@ xc_domain_dumpcore_via_callback(int xc_h if ( !auto_translated_physmap ) { - gmfn = p2m[i]; - if ( gmfn == INVALID_P2M_ENTRY ) - continue; + if ( guest_width >= sizeof(unsigned long) ) + { + if ( guest_width == sizeof(unsigned long) ) + gmfn = p2m[i]; + else + gmfn = ((uint64_t *)p2m)[i]; + if ( gmfn == INVALID_P2M_ENTRY ) + continue; + } + else + { + gmfn = ((uint32_t *)p2m)[i]; + if ( gmfn == (uint32_t)INVALID_P2M_ENTRY ) + continue; + } p2m_array[j].pfn = i; p2m_array[j].gmfn = gmfn; @@ -802,7 +844,7 @@ copy_done: /* When live dump-mode (-L option) is specified, * guest domain may reduce memory. pad with zero pages. */ - IPRINTF("j (%ld) != nr_pages (%ld)", j , nr_pages); + IPRINTF("j (%ld) != nr_pages (%ld)", j, nr_pages); memset(dump_mem_start, 0, PAGE_SIZE); for (; j < nr_pages; j++) { sts = dump_rtn(args, dump_mem_start, PAGE_SIZE); @@ -891,7 +933,7 @@ xc_domain_dumpcore(int xc_handle, struct dump_args da; int sts; - if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 ) + 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; diff -r 77476eeb8c42 tools/libxc/xc_core.h --- a/tools/libxc/xc_core.h Wed Jan 14 11:39:01 2009 +0000 +++ b/tools/libxc/xc_core.h Wed Jan 14 16:40:17 2009 -0700 @@ -136,12 +136,12 @@ struct xc_core_arch_context; struct xc_core_arch_context; int xc_core_arch_memory_map_get(int xc_handle, struct xc_core_arch_context *arch_ctxt, - xc_dominfo_t *info, shared_info_t *live_shinfo, + 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(int xc_handle, xc_dominfo_t *info, - shared_info_t *live_shinfo, xen_pfn_t **live_p2m, - unsigned long *pfnp); +int xc_core_arch_map_p2m(int xc_handle, unsigned int guest_width, + xc_dominfo_t *info, shared_info_any_t *live_shinfo, + xen_pfn_t **live_p2m, unsigned long *pfnp); #if defined (__i386__) || defined (__x86_64__) diff -r 77476eeb8c42 tools/libxc/xc_core_ia64.c --- a/tools/libxc/xc_core_ia64.c Wed Jan 14 11:39:01 2009 +0000 +++ b/tools/libxc/xc_core_ia64.c Wed Jan 14 16:40:17 2009 -0700 @@ -235,7 +235,7 @@ old: } int -xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, +xc_core_arch_map_p2m(int xc_handle, unsigned int guest_width, xc_dominfo_t *info, shared_info_t *live_shinfo, xen_pfn_t **live_p2m, unsigned long *pfnp) { diff -r 77476eeb8c42 tools/libxc/xc_core_x86.c --- a/tools/libxc/xc_core_x86.c Wed Jan 14 11:39:01 2009 +0000 +++ b/tools/libxc/xc_core_x86.c Wed Jan 14 16:40:17 2009 -0700 @@ -20,9 +20,25 @@ #include "xg_private.h" #include "xc_core.h" +#include "xc_e820.h" -/* Don't yet support cross-address-size core dump */ -#define guest_width (sizeof (unsigned long)) +#define GET_FIELD(_p, _f) ((guest_width==8) ? ((_p)->x64._f) : ((_p)->x32._f)) + +#ifndef MAX +#define MAX(_a, _b) ((_a) >= (_b) ? (_a) : (_b)) +#endif + +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; +} + static int nr_gpfns(int xc_handle, domid_t domid) { @@ -37,7 +53,7 @@ xc_core_arch_auto_translated_physmap(con int xc_core_arch_memory_map_get(int xc_handle, struct xc_core_arch_context *unused, - xc_dominfo_t *info, shared_info_t *live_shinfo, + xc_dominfo_t *info, shared_info_any_t *live_shinfo, xc_core_memory_map_t **mapp, unsigned int *nr_entries) { @@ -60,17 +76,22 @@ xc_core_arch_memory_map_get(int xc_handl } int -xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, - shared_info_t *live_shinfo, xen_pfn_t **live_p2m, +xc_core_arch_map_p2m(int xc_handle, unsigned int guest_width, xc_dominfo_t *info, + shared_info_any_t *live_shinfo, xen_pfn_t **live_p2m, unsigned long *pfnp) { /* Double and single indirect references to the live P2M table */ xen_pfn_t *live_p2m_frame_list_list = NULL; 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 = NULL; + uint32_t dom = info->domid; unsigned long p2m_size = nr_gpfns(xc_handle, info->domid); int ret = -1; int err; + int i; if ( p2m_size < info->nr_pages ) { @@ -80,7 +101,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_d live_p2m_frame_list_list = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, - live_shinfo->arch.pfn_to_mfn_frame_list_list); + GET_FIELD(live_shinfo, arch.pfn_to_mfn_frame_list_list)); if ( !live_p2m_frame_list_list ) { @@ -88,9 +109,28 @@ xc_core_arch_map_p2m(int xc_handle, xc_d 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 ( guest_width > sizeof(unsigned long) ) + for ( i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++ ) + if ( i < PAGE_SIZE/guest_width ) + p2m_frame_list_list[i] = ((uint64_t *)p2m_frame_list_list)[i]; + else + p2m_frame_list_list[i] = 0; + else if ( 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(xc_handle, dom, PROT_READ, - live_p2m_frame_list_list, + p2m_frame_list_list, P2M_FLL_ENTRIES); if ( !live_p2m_frame_list ) @@ -99,8 +139,25 @@ xc_core_arch_map_p2m(int xc_handle, xc_d 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 ( 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 ( guest_width < sizeof(unsigned long) ) + for ( i = P2M_FL_ENTRIES - 1; i >= 0; i-- ) + p2m_frame_list[i] = ((uint32_t *)p2m_frame_list)[i]; + *live_p2m = xc_map_foreign_pages(xc_handle, dom, PROT_READ, - live_p2m_frame_list, + p2m_frame_list, P2M_FL_ENTRIES); if ( !*live_p2m ) @@ -122,6 +179,12 @@ out: if ( live_p2m_frame_list ) munmap(live_p2m_frame_list, P2M_FLL_ENTRIES * PAGE_SIZE); + if ( p2m_frame_list_list ) + free(p2m_frame_list_list); + + if ( p2m_frame_list ) + free(p2m_frame_list); + errno = err; return ret; } diff -r 77476eeb8c42 tools/libxc/xc_core_x86.h --- a/tools/libxc/xc_core_x86.h Wed Jan 14 11:39:01 2009 +0000 +++ b/tools/libxc/xc_core_x86.h Wed Jan 14 16:40:17 2009 -0700 @@ -21,15 +21,8 @@ #ifndef XC_CORE_X86_H #define XC_CORE_X86_H -#if defined(__i386__) || defined(__x86_64__) #define ELF_ARCH_DATA ELFDATA2LSB -#if defined (__i386__) -# define ELF_ARCH_MACHINE EM_386 -#else -# define ELF_ARCH_MACHINE EM_X86_64 -#endif -#endif /* __i386__ or __x86_64__ */ - +#define ELF_ARCH_MACHINE (guest_width == 8 ? EM_X86_64 : EM_386) struct xc_core_arch_context { /* nothing */ @@ -40,8 +33,10 @@ struct xc_core_arch_context { #define xc_core_arch_context_get(arch_ctxt, ctxt, xc_handle, domid) \ (0) #define xc_core_arch_context_dump(arch_ctxt, args, dump_rtn) (0) -#define xc_core_arch_gpfn_may_present(arch_ctxt, i) (1) +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(struct xc_core_arch_context *arch_ctxt, struct xc_core_section_headers *sheaders,