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

Dave Anderson anderson at redhat.com
Wed Dec 17 21:43:18 UTC 2014



----- Original Message -----
> Hi Dave,
> 
> On Wed, 17 Dec 2014 13:33:50 -0500 (EST)
> Dave Anderson <anderson at redhat.com> 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 <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, 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",
> 




More information about the Crash-utility mailing list