[Crash-utility] [PATCH] s390: Fix backtrace code

Dave Anderson anderson at redhat.com
Fri Feb 26 14:50:12 UTC 2010


----- "Michael Holzheu" <holzheu at linux.vnet.ibm.com> wrote:

> Hi Dave,
> 
> This patch fixes several bugs in the s390 stack backtrace code
> * Add panic stack as second interrupt stack
> * Fix printing of access registers (4 bytes instead of 8 bytes)
> * Use u64 for s390x register 14
> * Fix interrupt stack handling for s390x (use 160 byte overhead
> instead of 96)

The patch looks OK upon first glance -- can you verify that it's
absolutely backwards-compatible to earlier kernel versions?

Thanks,
  Dave


> ---
>  s390.c  |   46 ++++++++++++++++++-------------
>  s390x.c |   94
> +++++++++++++++++++++++++++++++++++-----------------------------
>  2 files changed, 79 insertions(+), 61 deletions(-)
> 
> --- a/s390.c
> +++ b/s390.c
> @@ -37,7 +37,7 @@
>  #define S390_PTE_INVALID_MASK   0x80000900
>  #define S390_PTE_INVALID(x) ((x) & S390_PTE_INVALID_MASK)
>  
> -#define ASYNC_STACK_SIZE  STACKSIZE() // can be 4096 or 8192
> +#define INT_STACK_SIZE    STACKSIZE() // can be 4096 or 8192
>  #define KERNEL_STACK_SIZE STACKSIZE() // can be 4096 or 8192
>  
>  #define LOWCORE_SIZE 4096
> @@ -570,20 +570,21 @@ s390_get_lowcore(int cpu, char* lowcore)
>  		FAULT_ON_ERROR);
>  }
>  
> -/* 
> - * read in the async stack
> +/*
> + * Read interrupt stack (either "async_stack" or "panic_stack");
>   */
> -static void
> -s390_get_async_stack(char* lowcore, char* async_stack, unsigned long*
> start, unsigned long* end)
> +static void s390_get_int_stack(char *stack_name, char* lc, char*
> int_stack,
> +			       unsigned long* start, unsigned long* end)
>  {
> -	unsigned long async_stack_ptr;
> +	unsigned long stack_addr;
>  
> -	async_stack_ptr = ULONG(lowcore + 
> -				MEMBER_OFFSET("_lowcore","async_stack"));
> -	readmem(async_stack_ptr-ASYNC_STACK_SIZE,KVADDR, async_stack, 
> -		ASYNC_STACK_SIZE, "async_stack", FAULT_ON_ERROR);
> -	*start=async_stack_ptr-ASYNC_STACK_SIZE;
> -	*end=async_stack_ptr;
> +	if (!MEMBER_EXISTS("_lowcore", stack_name))
> +		return;
> +	stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
> +	readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack,
> +		INT_STACK_SIZE, stack_name, FAULT_ON_ERROR);
> +	*start = stack_addr - INT_STACK_SIZE;
> +	*end = stack_addr;
>  }
>  
>  /*
> @@ -593,16 +594,18 @@ static void
>  s390_back_trace_cmd(struct bt_info *bt)
>  {
>  	char* stack;
> -	char async_stack[ASYNC_STACK_SIZE];
> +	char async_stack[INT_STACK_SIZE];
> +	char panic_stack[INT_STACK_SIZE];
>  	long ksp,backchain,old_backchain;
>  	int i=0, r14_offset,bc_offset,r14, skip_first_frame=0;
> -	unsigned long async_start,async_end, stack_end, stack_start,
> stack_base;
> +	unsigned long async_start = 0, async_end = 0;
> +	unsigned long panic_start = 0, panic_end = 0;
> +	unsigned long stack_end, stack_start, stack_base;
>  
>  	if (bt->hp && bt->hp->eip) {
>  		error(WARNING,
>  		"instruction pointer argument ignored on this architecture!\n");
>  	}
> -	async_end = async_start = 0;
>  	ksp = bt->stkptr;
>  
>  	/* print lowcore and get async stack when task has cpu */
> @@ -622,9 +625,10 @@ s390_back_trace_cmd(struct bt_info *bt)
>  				s390_print_lowcore(lowcore,bt,0);
>  				return;
>  		}
> -
> -		s390_get_async_stack(lowcore,async_stack,&async_start,
> -				     &async_end);
> +		s390_get_int_stack("async_stack", lowcore, async_stack,
> +				   &async_start, &async_end);
> +		s390_get_int_stack("panic_stack", lowcore, panic_stack,
> +				   &panic_start, &panic_end);
>  		s390_print_lowcore(lowcore,bt,1);
>  		fprintf(fp,"\n");
>  		skip_first_frame=1;
> @@ -653,7 +657,7 @@ s390_back_trace_cmd(struct bt_info *bt)
>  		unsigned long r14_stack_off;
>  		int j;
>  
> -		/* Find stack: Either async stack or task stack */
> +		/* Find stack: Either async, panic stack or task stack */
>  		if((backchain > stack_start) && (backchain < stack_end)){
>  			stack = bt->stackbuf;
>  			stack_base = stack_start;
> @@ -661,6 +665,10 @@ s390_back_trace_cmd(struct bt_info *bt)
>  			  && s390_has_cpu(bt)){
>  			stack = async_stack;
>  			stack_base = async_start;
> +		} else if((backchain > panic_start) && (backchain < panic_end)
> +			  && s390_has_cpu(bt)){
> +			stack = panic_stack;
> +			stack_base = panic_start;
>  		} else {
>  			/* invalid stackframe */
>  			break;
> --- a/s390x.c
> +++ b/s390x.c
> @@ -36,7 +36,7 @@
>  #define S390X_PTE_INVALID_MASK  0x900ULL
>  #define S390X_PTE_INVALID(x) ((x) & S390X_PTE_INVALID_MASK)
>  
> -#define ASYNC_STACK_SIZE  STACKSIZE() // can be 8192 or 16384
> +#define INT_STACK_SIZE    STACKSIZE() // can be 8192 or 16384
>  #define KERNEL_STACK_SIZE STACKSIZE() // can be 8192 or 16384
>  
>  #define LOWCORE_SIZE 8192
> @@ -803,19 +803,20 @@ s390x_get_lowcore(struct bt_info *bt, ch
>  }
>  
>  /*
> - * read in the async stack
> + * Read interrupt stack (either "async_stack" or "panic_stack");
>   */
> -static void
> -s390x_get_async_stack(char* lowcore, char* async_stack, unsigned
> long* start, unsigned long* end)
> +static void s390x_get_int_stack(char *stack_name, char* lc, char*
> int_stack,
> +				unsigned long* start, unsigned long* end)
>  {
> -	unsigned long async_stack_ptr;
> +	unsigned long stack_addr;
>  
> -	async_stack_ptr = ULONG(lowcore + 
> -				MEMBER_OFFSET("_lowcore","async_stack"));
> -	readmem(async_stack_ptr-ASYNC_STACK_SIZE,KVADDR, async_stack, 
> -		ASYNC_STACK_SIZE, "async_stack", FAULT_ON_ERROR);
> -	*start=async_stack_ptr-ASYNC_STACK_SIZE;
> -	*end=async_stack_ptr;
> +	if (!MEMBER_EXISTS("_lowcore", stack_name))
> +		return;
> +	stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
> +	readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack,
> +		INT_STACK_SIZE, stack_name, FAULT_ON_ERROR);
> +	*start = stack_addr - INT_STACK_SIZE;
> +	*end = stack_addr;
>  }
>  
>  /*
> @@ -825,11 +826,14 @@ static void
>  s390x_back_trace_cmd(struct bt_info *bt)
>  {
>  	char* stack;
> -	char async_stack[ASYNC_STACK_SIZE];
> +	char async_stack[INT_STACK_SIZE];
> +	char panic_stack[INT_STACK_SIZE];
>  	long ksp,backchain,old_backchain;
> -	int i=0, r14_offset,bc_offset,r14, skip_first_frame=0;
> +	int i=0, r14_offset,bc_offset, skip_first_frame=0;
>  	unsigned long async_start = 0, async_end = 0;
> +	unsigned long panic_start = 0, panic_end = 0;
>  	unsigned long stack_end, stack_start, stack_base;
> +	unsigned long r14;
>  
>  	if (bt->hp && bt->hp->eip) {
>  		error(WARNING,
> @@ -854,9 +858,10 @@ s390x_back_trace_cmd(struct bt_info *bt)
>  			s390x_print_lowcore(lowcore,bt,0);
>  			return;
>  		}
> -
> -		s390x_get_async_stack(lowcore,async_stack,&async_start,
> -				     &async_end);
> +		s390x_get_int_stack("async_stack", lowcore, async_stack,
> +				    &async_start, &async_end);
> +		s390x_get_int_stack("panic_stack", lowcore, panic_stack,
> +				    &panic_start, &panic_end);
>  		s390x_print_lowcore(lowcore,bt,1);
>  		fprintf(fp,"\n");
>  		skip_first_frame=1;
> @@ -885,7 +890,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
>  		unsigned long r14_stack_off;
>  		int j;
>  
> -		/* Find stack: Either async stack or task stack */
> +		/* Find stack: Either async, panic stack or task stack */
>  		if((backchain > stack_start) && (backchain < stack_end)){
>  			stack = bt->stackbuf;
>  			stack_base = stack_start;
> @@ -893,6 +898,10 @@ s390x_back_trace_cmd(struct bt_info *bt)
>  			  && s390x_has_cpu(bt)){
>  			stack = async_stack;
>  			stack_base = async_start;
> +		} else if((backchain > panic_start) && (backchain < panic_end)
> +			  && s390x_has_cpu(bt)){
> +			stack = panic_stack;
> +			stack_base = panic_start;
>  		} else {
>  			/* invalid stackframe */
>  			break;
> @@ -913,7 +922,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
>  			skip_first_frame=0;
>  		} else {
>  			fprintf(fp," #%i [%08lx] ",i,backchain);
> -			fprintf(fp,"%s at %x\n", closest_symbol(r14), r14);
> +			fprintf(fp,"%s at %lx\n", closest_symbol(r14), r14);
>  			if (bt->flags & BT_LINE_NUMBERS)
>  				s390x_dump_line_number(r14);
>  			i++;
> @@ -944,19 +953,20 @@ s390x_back_trace_cmd(struct bt_info *bt)
>  		}
>  
>  		/* Check for interrupt stackframe */
> -		if((backchain == 0) && (stack == async_stack)){
> -			unsigned long psw_flags,r15;
> +		if((backchain == 0) &&
> +		   (stack == async_stack || stack == panic_stack)) {
> +			int pt_regs_off = old_backchain - stack_base + 160;
> +			unsigned long psw_flags;
>  
> -			psw_flags = ULONG(&stack[old_backchain - stack_base 
> -					  +96 +MEMBER_OFFSET("pt_regs","psw")]);
> +			psw_flags = ULONG(&stack[pt_regs_off +
> +					  MEMBER_OFFSET("pt_regs", "psw")]);
>  			if(psw_flags & 0x1000000000000ULL){
>  				/* User psw: should not happen */
>  				break;
>  			}
> -			r15 = ULONG(&stack[old_backchain - stack_base +
> -				    96 + MEMBER_OFFSET("pt_regs",
> -				    "gprs") + 15 * S390X_WORD_SIZE]);
> -			backchain=r15;
> +			backchain = ULONG(&stack[pt_regs_off +
> +					  MEMBER_OFFSET("pt_regs", "gprs") +
> +					  15 * S390X_WORD_SIZE]);
>  			fprintf(fp," - Interrupt -\n");
>  		}
>        } while(backchain != 0);
> @@ -1036,28 +1046,28 @@ s390x_print_lowcore(char* lc, struct bt_
>  
>  	fprintf(fp,"  -access registers:\n");
>  	ptr = lc + MEMBER_OFFSET("_lowcore","access_regs_save_area");
> -	tmp[0]=ULONG(ptr);
> -	tmp[1]=ULONG(ptr + 4);
> -	tmp[2]=ULONG(ptr + 2 * 4);
> -	tmp[3]=ULONG(ptr + 3 * 4);
> +	tmp[0]=UINT(ptr);
> +	tmp[1]=UINT(ptr + 4);
> +	tmp[2]=UINT(ptr + 2 * 4);
> +	tmp[3]=UINT(ptr + 3 * 4);
>  	fprintf(fp,"     %#010lx %#010lx %#010lx %#010lx\n", 
>  		tmp[0], tmp[1], tmp[2], tmp[3]);
> -	tmp[0]=ULONG(ptr + 4 * 4);
> -	tmp[1]=ULONG(ptr + 5 * 4);
> -	tmp[2]=ULONG(ptr + 6 * 4);
> -	tmp[3]=ULONG(ptr + 7 * 4);
> +	tmp[0]=UINT(ptr + 4 * 4);
> +	tmp[1]=UINT(ptr + 5 * 4);
> +	tmp[2]=UINT(ptr + 6 * 4);
> +	tmp[3]=UINT(ptr + 7 * 4);
>  	fprintf(fp,"     %#010lx %#010lx %#010lx %#010lx\n", 
>  		tmp[0], tmp[1], tmp[2], tmp[3]);
> -	tmp[0]=ULONG(ptr + 8 * 4);
> -	tmp[1]=ULONG(ptr + 9 * 4);
> -	tmp[2]=ULONG(ptr + 10* 4);
> -	tmp[3]=ULONG(ptr + 11* 4);
> +	tmp[0]=UINT(ptr + 8 * 4);
> +	tmp[1]=UINT(ptr + 9 * 4);
> +	tmp[2]=UINT(ptr + 10 * 4);
> +	tmp[3]=UINT(ptr + 11 * 4);
>  	fprintf(fp,"     %#010lx %#010lx %#010lx %#010lx\n", 
>  		tmp[0], tmp[1], tmp[2], tmp[3]);
> -	tmp[0]=ULONG(ptr + 12* 4);
> -	tmp[1]=ULONG(ptr + 13* 4);
> -	tmp[2]=ULONG(ptr + 14* 4);
> -	tmp[3]=ULONG(ptr + 15* 4);
> +	tmp[0]=UINT(ptr + 12 * 4);
> +	tmp[1]=UINT(ptr + 13 * 4);
> +	tmp[2]=UINT(ptr + 14 * 4);
> +	tmp[3]=UINT(ptr + 15 * 4);
>  	fprintf(fp,"     %#010lx %#010lx %#010lx %#010lx\n", 
>  		tmp[0], tmp[1], tmp[2], tmp[3]);
>  
> 
> 
> --
> 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