----- Original Message -----
> Hi Dave,
> 
> On Wed, 17 Dec 2014 13:33:50 -0500 (EST)
> Dave Anderson <[email protected]> wrote:
> 
> [snip]
> 
> > From your example, I presume that this is only applicable to the active
> > tasks?
> 
> Correct.
> 
> > So instead of using the somewhat-strange "bt -a -A" construct,
> > maybe you could just enter "bt -A" to accomplish the same result?
> > 
> > So cmd_bt() would have:
> > 
> >                 case 'A':
> >                         bt->flags |= BT_SHOW_ALL_REGS;   /* FALLTHROUGH */
> >                 case 'a':
> >                         active++;
> >                         break;
> > 
> > and the help page would have something like:
> > 
> >        -a  displays the stack traces of the active task on each CPU.",
> >           (only applicable to crash dumps)",
> >        -A  same as -a, but also displays vector registers (S390X only).",
> > 
> 
> Yes, this makes sense. Here the updated patch:

Hi Mike.  

OK this looks good.  In cmd_bt() I made the option s390x-only, and touched up 
the
error message if it's attempted on a live system.  

Queued for crash-7.1.0:

  
https://github.com/crash-utility/crash/commit/e30594ebeacd4a8e0d6c416123f204adf873bf9f

Thanks,
  Dave



> ---
> [PATCH] crash: s390x: Add vector register support
> 
> This patch adds support for the new s390x vector registers.
> For ELF dumps the registers are taken from the VX ELF notes, for
> s390 dumps the registers are taken from memory. The kernel stores
> a pointer the save area in the CPU lowcores at offset 0x11b0.
> 
> This patch also adds the new -A option to the "bt" command. This
> option produces almost the same output as the -a option, but in
> addition also the new vector registers for all active tasks
> are shown. This is done because for normal debugging using "bt -a"
> we do not want to pollute the bt output with the large vector register
> output (512 byte).
> 
> The following shows an output example:
> 
> crash> bt -A
> PID: 2387   TASK: 1785a5e8          CPU: 0   COMMAND: "bash"
>  LOWCORE INFO:
>   -psw      : 0x0400d00180000000 0x0000000000112aa0
>   -function : store_status at 112aa0
>   -prefix   : 0x1fffc000
>   -cpu timer: 0x7ffffff3 0x0066ef81
>   -clock cmp: 0x0066ef81 0000000000
>   -general registers:
>      000000000000000000 0x0400c00180000000
>    ....
>   - vector registers:
>      0x404b000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x404b000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
>      0x0000000000000000 0x0000000000000000
> 
> Signed-off-by: Michael Holzheu <[email protected]>
> ---
>  defs.h    |    1
>  help.c    |    1
>  kernel.c  |    5 +--
>  netdump.c |    6 +++
>  netdump.h |   14 ++++++++
>  s390x.c   |  100
>  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 125 insertions(+), 2 deletions(-)
> 
> --- a/defs.h
> +++ b/defs.h
> @@ -4966,6 +4966,7 @@ ulong cpu_map_addr(const char *type);
>  #define BT_FULL_SYM_SLAB2  (0x400000000000ULL)
>  #define BT_EFRAME_TARGET   (0x800000000000ULL)
>  #define BT_CPUMASK        (0x1000000000000ULL)
> +#define BT_SHOW_ALL_REGS  (0x2000000000000ULL)
>  #define BT_SYMBOL_OFFSET   (BT_SYMBOLIC_ARGS)
>  
>  #define BT_REF_HEXVAL         (0x1)
> --- a/help.c
> +++ b/help.c
> @@ -1742,6 +1742,7 @@ char *help_bt[] = {
>  "  trace of the current context will be displayed.\n",
>  "       -a  displays the stack traces of the active task on each CPU.",
>  "           (only applicable to crash dumps)",
> +"       -A  same as -a, but also displays vector registers (S390X only).",
>  "   -c cpu  display the stack trace of the active task on one or more
>  CPUs,",
>  "           which can be specified using the format \"3\", \"1,8,9\",
>  \"1-23\",",
>  "           or \"1,8,9-14\". (only applicable to crash dumps)",
> --- a/kernel.c
> +++ b/kernel.c
> @@ -2003,13 +2003,12 @@ cmd_bt(void)
>       if (kt->flags & USE_OLD_BT)
>               bt->flags |= BT_OLD_BACK_TRACE;
>  
> -        while ((c = getopt(argcnt, args, "D:fFI:S:c:aloreEgstTdxR:O")) !=
> EOF) {
> +     while ((c = getopt(argcnt, args, "D:fFI:S:c:aAloreEgstTdxR:O")) != EOF) 
> {
>                  switch (c)
>               {
>               case 'f':
>                       bt->flags |= BT_FULL;
>                       break;
> -
>               case 'F':
>                       if (bt->flags & BT_FULL_SYM_SLAB)
>                               bt->flags |= BT_FULL_SYM_SLAB2;
> @@ -2158,6 +2157,8 @@ cmd_bt(void)
>                       }
>                       break;
>  
> +             case 'A':
> +                     bt->flags |= BT_SHOW_ALL_REGS; /* FALLTHROUGH */
>               case 'a':
>                       active++;
>                       break;
> --- a/netdump.c
> +++ b/netdump.c
> @@ -2086,6 +2086,12 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st
>       case NT_S390_PREFIX:
>               netdump_print("(NT_S390_PREFIX)\n");
>               break;
> +     case NT_S390_VXRS_LOW:
> +             netdump_print("(NT_S390_VXRS_LOW)\n");
> +             break;
> +     case NT_S390_VXRS_HIGH:
> +             netdump_print("(NT_S390_VXRS_HIGH)\n");
> +             break;
>       case NT_TASKSTRUCT:
>               netdump_print("(NT_TASKSTRUCT)\n");
>               if (STRNEQ(buf, "SNAP"))
> --- a/netdump.h
> +++ b/netdump.h
> @@ -169,6 +169,20 @@ struct xen_kdump_data {
>  #define NT_S390_PREFIX 0x305
>  #endif
>  
> +/*
> + * S390 vector registers 0-15 upper half note (16 * u64)
> + */
> +#ifndef NT_S390_VXRS_LOW
> +#define NT_S390_VXRS_LOW 0x309
> +#endif
> +
> +/*
> + * S390 vector registers 16-31 note (16 * u128)
> + */
> +#ifndef NT_S390_VXRS_HIGH
> +#define NT_S390_VXRS_HIGH 0x30a
> +#endif
> +
>  #define MAX_KCORE_ELF_HEADER_SIZE (32768)
>  
>  struct proc_kcore_data {
> --- a/s390x.c
> +++ b/s390x.c
> @@ -41,6 +41,7 @@
>  #define KERNEL_STACK_SIZE STACKSIZE() // can be 8192 or 16384
>  
>  #define LOWCORE_SIZE 8192
> +#define VX_SA_SIZE (32 * 16)
>  
>  #define S390X_PSW_MASK_PSTATE        0x0001000000000000UL
>  
> @@ -72,6 +73,11 @@ struct s390x_nt_fpregset {
>       uint64_t        fprs[16];
>  } __attribute__ ((packed));
>  
> +struct s390x_vxrs {
> +     uint64_t        low;
> +     uint64_t        high;
> +} __attribute__ ((packed));
> +
>  /*
>   * s390x CPU info
>   */
> @@ -87,6 +93,8 @@ struct s390x_cpu
>       uint64_t        timer;
>       uint64_t        todcmp;
>       uint32_t        todpreg;
> +     uint64_t                vxrs_low[16];
> +     struct s390x_vxrs       vxrs_high[16];
>  };
>  
>  /*
> @@ -133,6 +141,27 @@ static unsigned long readmem_ul(unsigned
>  }
>  
>  /*
> + * Print hex data
> + */
> +static void print_hex_buf(void *buf, int len, int cols, char *tag)
> +{
> +     int j, first = 1;
> +
> +     for (j = 0; j < len; j += 8) {
> +             if (j % (cols * 8) == 0) {
> +                     if (first)
> +                             first = 0;
> +                     else
> +                             fprintf(fp, "\n");
> +                     fprintf(fp, "%s", tag);
> +             }
> +             fprintf(fp, "%#018lx ", *((unsigned long *)(buf + j)));
> +     }
> +     if (len)
> +             fprintf(fp, "\n");
> +}
> +
> +/*
>   * Initialize member offsets
>   */
>  static void s390x_offsets_init(void)
> @@ -271,6 +300,16 @@ static void s390x_elf_nt_prefix_add(stru
>       memcpy(&cpu->prefix, desc, sizeof(cpu->prefix));
>  }
>  
> +static void s390x_elf_nt_vxrs_low_add(struct s390x_cpu *cpu, void *desc)
> +{
> +     memcpy(&cpu->vxrs_low, desc, sizeof(cpu->vxrs_low));
> +}
> +
> +static void s390x_elf_nt_vxrs_high_add(struct s390x_cpu *cpu, void *desc)
> +{
> +     memcpy(&cpu->vxrs_high, desc, sizeof(cpu->vxrs_high));
> +}
> +
>  static void *get_elf_note_desc(Elf64_Nhdr *note)
>  {
>       void *ptr = note;
> @@ -315,6 +354,12 @@ static void s390x_elf_note_add(int elf_c
>       case NT_S390_PREFIX:
>               s390x_elf_nt_prefix_add(cpu, desc);
>               break;
> +     case NT_S390_VXRS_LOW:
> +             s390x_elf_nt_vxrs_low_add(cpu, desc);
> +             break;
> +     case NT_S390_VXRS_HIGH:
> +             s390x_elf_nt_vxrs_high_add(cpu, desc);
> +             break;
>       }
>  }
>  
> @@ -916,6 +961,59 @@ s390x_get_lowcore(struct bt_info *bt, ch
>  }
>  
>  /*
> + * Copy VX registers out of s390x cpu
> + */
> +static void vx_copy(void *buf, struct s390x_cpu *s390x_cpu)
> +{
> +     char *_buf = buf;
> +     int i;
> +
> +     for (i = 0; i < 16; i++) {
> +             memcpy(&_buf[i * 16], &s390x_cpu->fprs[i], 8);
> +             memcpy(&_buf[i * 16 + 8], &s390x_cpu->vxrs_low[i], 8);
> +     }
> +     memcpy(&_buf[16 * 16], &s390x_cpu->vxrs_high[0], 16 * 16);
> +}
> +
> +/*
> + * Check if VX registers are available
> + */
> +static int has_vx_regs(char *lowcore)
> +{
> +     unsigned long addr = *((uint64_t *)(lowcore + 0x11b0));
> +
> +     if (addr == 0 || addr % 1024)
> +             return 0;
> +     return 1;
> +}
> +
> +/*
> + * Print vector registers for cpu
> + */
> +static void
> +s390x_print_vx_sa(struct bt_info *bt, char *lc)
> +{
> +     char vx_sa[VX_SA_SIZE];
> +     uint64_t addr;
> +
> +     if (!(bt->flags & BT_SHOW_ALL_REGS))
> +             return;
> +     if (!has_vx_regs(lc))
> +             return;
> +     if (!s390x_cpu_vec) {
> +             /* Pointer to save area */
> +             addr = *((uint64_t *)(lc + 0x11b0));
> +             readmem(addr, KVADDR, vx_sa, sizeof(vx_sa), "vx_sa",
> +                     FAULT_ON_ERROR);
> +     } else {
> +             /* Get data from s390x cpu */
> +             vx_copy(vx_sa, s390x_cpu_get(bt));
> +     }
> +     fprintf(fp, "  -vector registers:\n");
> +     print_hex_buf(vx_sa, sizeof(vx_sa), 2, "     ");
> +}
> +
> +/*
>   * Get stack address for interrupt stack using the pcpu array
>   */
>  static unsigned long get_int_stack_pcpu(char *stack_name, int cpu)
> @@ -1180,9 +1278,11 @@ static void s390x_back_trace_cmd(struct
>               if (psw_flags & S390X_PSW_MASK_PSTATE) {
>                       fprintf(fp,"Task runs in userspace\n");
>                       s390x_print_lowcore(lowcore,bt,0);
> +                     s390x_print_vx_sa(bt, lowcore);
>                       return;
>               }
>               s390x_print_lowcore(lowcore,bt,1);
> +             s390x_print_vx_sa(bt, lowcore);
>               fprintf(fp,"\n");
>               if (symbol_exists("restart_stack")) {
>                       get_int_stack("restart_stack",
> 

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to