ia64/xen-unstable

changeset 13346:91b9c6eae6e8

[XEN] Kexec: Clean up ELF note construction to avoid multiply nested
struct/unions and the packed keyword.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Tue Jan 09 17:15:28 2007 +0000 (2007-01-09)
parents 79b5090c791f
children f653919e069a
files xen/common/kexec.c xen/include/xen/elfcore.h
line diff
     1.1 --- a/xen/common/kexec.c	Tue Jan 09 17:14:28 2007 +0000
     1.2 +++ b/xen/common/kexec.c	Tue Jan 09 17:15:28 2007 +0000
     1.3 @@ -26,7 +26,15 @@
     1.4  
     1.5  typedef long ret_t;
     1.6  
     1.7 -DEFINE_PER_CPU (crash_note_t, crash_notes);
     1.8 +#define ELFNOTE_ALIGN(_n_) (((_n_)+3)&~3)
     1.9 +#define ELFNOTE_NAME(_n_) ((void*)(_n_) + sizeof(*(_n_)))
    1.10 +#define ELFNOTE_DESC(_n_) (ELFNOTE_NAME(_n_) + ELFNOTE_ALIGN((_n_)->namesz))
    1.11 +#define ELFNOTE_NEXT(_n_) (ELFNOTE_DESC(_n_) + ELFNOTE_ALIGN((_n_)->descsz))
    1.12 +
    1.13 +DEFINE_PER_CPU(void *, crash_notes);
    1.14 +
    1.15 +Elf_Note *xen_crash_note;
    1.16 +
    1.17  cpumask_t crash_saved_cpus;
    1.18  
    1.19  xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
    1.20 @@ -70,40 +78,29 @@ static void one_cpu_only(void)
    1.21  void kexec_crash_save_cpu(void)
    1.22  {
    1.23      int cpu = smp_processor_id();
    1.24 -    crash_note_t *cntp;
    1.25 +    Elf_Note *note = per_cpu(crash_notes, cpu);
    1.26 +    ELF_Prstatus *prstatus;
    1.27 +    crash_xen_core_t *xencore;
    1.28  
    1.29      if ( cpu_test_and_set(cpu, crash_saved_cpus) )
    1.30          return;
    1.31  
    1.32 -    cntp = &per_cpu(crash_notes, cpu);
    1.33 -    elf_core_save_regs(&cntp->core.desc.desc.pr_reg,
    1.34 -                       &cntp->xen_regs.desc.desc);
    1.35 +    prstatus = ELFNOTE_DESC(note);
    1.36  
    1.37 -    /* Set up crash "CORE" note. */
    1.38 -    setup_crash_note(cntp, core, CORE_STR, CORE_STR_LEN, NT_PRSTATUS);
    1.39 +    note = ELFNOTE_NEXT(note);
    1.40 +    xencore = ELFNOTE_DESC(note);
    1.41  
    1.42 -    /* Set up crash note "Xen", XEN_ELFNOTE_CRASH_REGS. */
    1.43 -    setup_crash_note(cntp, xen_regs, XEN_STR, XEN_STR_LEN,
    1.44 -                     XEN_ELFNOTE_CRASH_REGS);
    1.45 +    elf_core_save_regs(&prstatus->pr_reg, xencore);
    1.46  }
    1.47  
    1.48  /* Set up the single Xen-specific-info crash note. */
    1.49  crash_xen_info_t *kexec_crash_save_info(void)
    1.50  {
    1.51      int cpu = smp_processor_id();
    1.52 -    crash_note_t *cntp;
    1.53 -    crash_xen_info_t *info;
    1.54 +    crash_xen_info_t *info = ELFNOTE_DESC(xen_crash_note);
    1.55  
    1.56      BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus));
    1.57  
    1.58 -    cntp = &per_cpu(crash_notes, cpu);
    1.59 -
    1.60 -    /* Set up crash note "Xen", XEN_ELFNOTE_CRASH_INFO. */
    1.61 -    setup_crash_note(cntp, xen_info, XEN_STR, XEN_STR_LEN,
    1.62 -                     XEN_ELFNOTE_CRASH_INFO);
    1.63 -
    1.64 -    info = &cntp->xen_info.desc.desc;
    1.65 -
    1.66      info->xen_major_version = xen_major_version();
    1.67      info->xen_minor_version = xen_minor_version();
    1.68      info->xen_extra_version = __pa(xen_extra_version());
    1.69 @@ -147,6 +144,14 @@ static __init int register_crashdump_tri
    1.70  }
    1.71  __initcall(register_crashdump_trigger);
    1.72  
    1.73 +static void setup_note(Elf_Note *n, const char *name, int type, int descsz)
    1.74 +{
    1.75 +    strcpy(ELFNOTE_NAME(n), name);
    1.76 +    n->namesz = strlen(name);
    1.77 +    n->descsz = descsz;
    1.78 +    n->type = type;
    1.79 +}
    1.80 +
    1.81  #define kexec_get(x)      kexec_get_##x
    1.82  
    1.83  #endif
    1.84 @@ -167,11 +172,44 @@ static int kexec_get(xen)(xen_kexec_rang
    1.85  
    1.86  static int kexec_get(cpu)(xen_kexec_range_t *range)
    1.87  {
    1.88 -    if ( range->nr < 0 || range->nr >= num_present_cpus() )
    1.89 +    int nr = range->nr;
    1.90 +    int nr_bytes = sizeof(Elf_Note) * 2
    1.91 +        + ELFNOTE_ALIGN(sizeof(ELF_Prstatus))
    1.92 +        + ELFNOTE_ALIGN(sizeof(crash_xen_core_t));
    1.93 +
    1.94 +    if ( nr < 0 || nr >= num_present_cpus() )
    1.95          return -EINVAL;
    1.96  
    1.97 -    range->start = __pa((unsigned long)&per_cpu(crash_notes, range->nr));
    1.98 -    range->size = sizeof(crash_note_t);
    1.99 +    /* The Xen info note is included in CPU0's range. */
   1.100 +    if ( nr == 0 )
   1.101 +        nr_bytes += sizeof(Elf_Note) + ELFNOTE_ALIGN(sizeof(crash_xen_info_t));
   1.102 +
   1.103 +    if ( per_cpu(crash_notes, nr) == NULL )
   1.104 +    {
   1.105 +        Elf_Note *note;
   1.106 +
   1.107 +        note = per_cpu(crash_notes, nr) = xmalloc_bytes(nr_bytes);
   1.108 +
   1.109 +        if ( note == NULL )
   1.110 +            return -ENOMEM;
   1.111 +
   1.112 +        /* Setup CORE note. */
   1.113 +        setup_note(note, "CORE", NT_PRSTATUS, sizeof(ELF_Prstatus));
   1.114 +
   1.115 +        /* Setup Xen CORE note. */
   1.116 +        note = ELFNOTE_NEXT(note);
   1.117 +        setup_note(note, "Xen", XEN_ELFNOTE_CRASH_REGS, sizeof(crash_xen_core_t));
   1.118 +
   1.119 +        if (nr == 0)
   1.120 +        {
   1.121 +            /* Setup system wide Xen info note. */
   1.122 +            xen_crash_note = note = ELFNOTE_NEXT(note);
   1.123 +            setup_note(note, "Xen", XEN_ELFNOTE_CRASH_INFO, sizeof(crash_xen_info_t));
   1.124 +        }
   1.125 +    }
   1.126 +
   1.127 +    range->start = __pa((unsigned long)per_cpu(crash_notes, nr));
   1.128 +    range->size = nr_bytes;
   1.129      return 0;
   1.130  }
   1.131  
     2.1 --- a/xen/include/xen/elfcore.h	Tue Jan 09 17:14:28 2007 +0000
     2.2 +++ b/xen/include/xen/elfcore.h	Tue Jan 09 17:15:28 2007 +0000
     2.3 @@ -56,49 +56,6 @@ typedef struct
     2.4      int pr_fpvalid;              /* True if math co-processor being used.  */
     2.5  } ELF_Prstatus;
     2.6  
     2.7 -/*
     2.8 - * The following data structures provide 64-bit ELF notes. In theory it should 
     2.9 - * be possible to support both 64-bit and 32-bit ELF files, but to keep it 
    2.10 - * simple we only do 64-bit.
    2.11 - *
    2.12 - * Please note that the current code aligns the 64-bit notes in the same
    2.13 - * way as Linux does. We are not following the 64-bit ELF spec, no one does.
    2.14 - *
    2.15 - * We are avoiding two problems by restricting us to 64-bit notes only:
    2.16 - * - Alignment of notes change with the word size. Ick.
    2.17 - * - We would need to tell kexec-tools which format we are using in the
    2.18 - *   hypervisor to make sure the right ELF format is generated.
    2.19 - *   That requires infrastructure. Let's not.
    2.20 - */
    2.21 -
    2.22 -#define NOTE_ALIGN(x, n) ((x + ((1 << n) - 1)) / (1 << n))
    2.23 -#define PAD32(x) u32 pad_data[NOTE_ALIGN(x, 2)]
    2.24 -
    2.25 -#define TYPEDEF_NOTE(type, strlen, desctype)    \
    2.26 -    typedef struct {                            \
    2.27 -        union {                                 \
    2.28 -            struct {                            \
    2.29 -                Elf_Note note;                  \
    2.30 -                unsigned char name[strlen];     \
    2.31 -            } note;                             \
    2.32 -            PAD32(sizeof(Elf_Note) + strlen);   \
    2.33 -        } note;                                 \
    2.34 -        union {                                 \
    2.35 -            desctype desc;                      \
    2.36 -            PAD32(sizeof(desctype));            \
    2.37 -        } desc;                                 \
    2.38 -    } __attribute__ ((packed)) type
    2.39 -
    2.40 -#define CORE_STR                "CORE"
    2.41 -#define CORE_STR_LEN            5 /* including terminating zero */
    2.42 -
    2.43 -TYPEDEF_NOTE(crash_note_core_t, CORE_STR_LEN, ELF_Prstatus);
    2.44 -
    2.45 -#define XEN_STR                 "Xen"
    2.46 -#define XEN_STR_LEN             4 /* including terminating zero */
    2.47 -
    2.48 -TYPEDEF_NOTE(crash_note_xen_core_t, XEN_STR_LEN, crash_xen_core_t);
    2.49 -
    2.50  typedef struct {
    2.51      unsigned long xen_major_version;
    2.52      unsigned long xen_minor_version;
    2.53 @@ -113,20 +70,6 @@ typedef struct {
    2.54  #endif
    2.55  } crash_xen_info_t;
    2.56  
    2.57 -TYPEDEF_NOTE(crash_note_xen_info_t, XEN_STR_LEN, crash_xen_info_t);
    2.58 -
    2.59 -typedef struct {
    2.60 -    crash_note_core_t core;
    2.61 -    crash_note_xen_core_t xen_regs;
    2.62 -    crash_note_xen_info_t xen_info;
    2.63 -} __attribute__ ((packed)) crash_note_t;
    2.64 -
    2.65 -#define setup_crash_note(np, member, str, str_len, id) \
    2.66 -  np->member.note.note.note.namesz = str_len; \
    2.67 -  np->member.note.note.note.descsz = sizeof(np->member.desc.desc); \
    2.68 -  np->member.note.note.note.type = id; \
    2.69 -  memcpy(np->member.note.note.name, str, str_len)
    2.70 -
    2.71  #endif /* __ELFCOREC_H__ */
    2.72  
    2.73  /*