[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] Support cross-bitness guest when core-dumping



The "change" to the format is as follows:  Now the file format for a cross-bit 
configuration will be the same as would have been produced by a same-bitness 
configuration, which crash of course already handles.  So crash should be fine 
with this change. In fact that was part of how I determined that it was working 
right.
I consider that the cross-bitness format was simply not valid as there is no 
reason for there to be a different format for the file simply because the host 
was a different bitsize than the guest (and it didn't work with crash & 
gdb-xenserver as it was).

- Bruce

>>> Isaku Yamahata <yamahata@xxxxxxxxxxxxx> 01/14/09 8:17 PM >>>
[CCed to Anderson, Oda and crash-utility ml]
Hi Bruce. Nice patch.

Could you please update the documentation about its format too?
  docs/misc/dump-core-format.txt
  - Elf header section, and
  - revision history at the end of the file.

And what is the impact on the crash utility?

thanks,

On Wed, Jan 14, 2009 at 04:47:41PM -0700, Bruce Rogers wrote:
> This patch allows core-dumping to work on a cross-bit host/guest 
> configuration, whereas previously that was not supported.  It supports both 
> PV and FV guests. The core file format generated by the host, needs to match 
> that of the guest, so an alignment issue is addressed, along with the p2m 
> frame list handling being done according to the guest size.
> 
> Signed-off-by: Bruce Rogers <brogers@xxxxxxxxxx>
> 

> 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,

> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel


-- 
yamahata

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.