----- 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?
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(a)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(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility