[Crash-utility] [PATCH] crash: s390x: Add vector register support

Dave Anderson anderson at redhat.com
Wed Dec 17 18:33:50 UTC 2014



----- Original Message -----
> 
> 
> ----- Original Message -----
> > Hello Dave,
> > 
> > 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.
> 
> Just a thought -- might this be more applicable to "help -r", which
> is where per-cpu register dumps are normally done?

But if not...

>From your example, I presume that this is only applicable to the active
tasks?  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).",

Dave


> 
> Dave
> 
> > 
> > This patch also adds a new -A option to the "bt" command. The
> > new vector registers are only shown when this option is specified.
> > This is done because for normal degugging 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 -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 <holzheu at linux.vnet.ibm.com>
> > ---
> >  defs.h    |    1
> >  help.c    |    1
> >  kernel.c  |    5 ++-
> >  netdump.c |    6 +++
> >  netdump.h |   14 ++++++++
> >  s390x.c   |  100
> >  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  6 files changed, 126 insertions(+), 1 deletion(-)
> > 
> > --- 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  displays all available CPU registers.",
> >  "   -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,12 +2003,15 @@ 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 'A':
> > +			bt->flags |= BT_SHOW_ALL_REGS;
> > +			break;
> >  
> >  		case 'F':
> >  			if (bt->flags & BT_FULL_SYM_SLAB)
> > --- 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
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
> 




More information about the Crash-utility mailing list