diff options
Diffstat (limited to 'arch/tile/kernel/backtrace.c')
| -rw-r--r-- | arch/tile/kernel/backtrace.c | 103 | 
1 files changed, 43 insertions, 60 deletions
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c index 55a6a74974b..1dc71eabfc5 100644 --- a/arch/tile/kernel/backtrace.c +++ b/arch/tile/kernel/backtrace.c @@ -14,19 +14,11 @@  #include <linux/kernel.h>  #include <linux/string.h> -  #include <asm/backtrace.h> - -#include <arch/chip.h> -  #include <asm/opcode-tile.h> +#include <arch/abi.h> - -#define TREG_SP 54 -#define TREG_LR 55 - - -#if TILE_CHIP >= 10 +#ifdef __tilegx__  #define tile_bundle_bits tilegx_bundle_bits  #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE  #define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES @@ -47,7 +39,7 @@ typedef long long bt_int_reg_t;  typedef int bt_int_reg_t;  #endif -/** A decoded bundle used for backtracer analysis. */ +/* A decoded bundle used for backtracer analysis. */  struct BacktraceBundle {  	tile_bundle_bits bits;  	int num_insns; @@ -56,23 +48,7 @@ struct BacktraceBundle {  }; -/* This implementation only makes sense for native tools. */ -/** Default function to read memory. */ -static bool bt_read_memory(void *result, VirtualAddress addr, -			   unsigned int size, void *extra) -{ -	/* FIXME: this should do some horrible signal stuff to catch -	 * SEGV cleanly and fail. -	 * -	 * Or else the caller should do the setjmp for efficiency. -	 */ - -	memcpy(result, (const void *)addr, size); -	return true; -} - - -/** Locates an instruction inside the given bundle that +/* Locates an instruction inside the given bundle that   * has the specified mnemonic, and whose first 'num_operands_to_match'   * operands exactly match those in 'operand_values'.   */ @@ -107,13 +83,13 @@ static const struct tile_decoded_instruction *find_matching_insn(  	return NULL;  } -/** Does this bundle contain an 'iret' instruction? */ +/* Does this bundle contain an 'iret' instruction? */  static inline bool bt_has_iret(const struct BacktraceBundle *bundle)  {  	return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL;  } -/** Does this bundle contain an 'addi sp, sp, OFFSET' or +/* Does this bundle contain an 'addi sp, sp, OFFSET' or   * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET?   */  static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) @@ -124,7 +100,7 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust)  		find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2);  	if (insn == NULL)  		insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); -#if TILE_CHIP >= 10 +#ifdef __tilegx__  	if (insn == NULL)  		insn = find_matching_insn(bundle, TILEGX_OPC_ADDXLI, vals, 2);  	if (insn == NULL) @@ -137,7 +113,7 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust)  	return true;  } -/** Does this bundle contain any 'info OP' or 'infol OP' +/* Does this bundle contain any 'info OP' or 'infol OP'   * instruction, and if so, what are their OP?  Note that OP is interpreted   * as an unsigned value by this code since that's what the caller wants.   * Returns the number of info ops found. @@ -161,7 +137,7 @@ static int bt_get_info_ops(const struct BacktraceBundle *bundle,  	return num_ops;  } -/** Does this bundle contain a jrp instruction, and if so, to which +/* Does this bundle contain a jrp instruction, and if so, to which   * register is it jumping?   */  static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg) @@ -175,7 +151,7 @@ static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg)  	return true;  } -/** Does this bundle modify the specified register in any way? */ +/* Does this bundle modify the specified register in any way? */  static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg)  {  	int i, j; @@ -195,34 +171,34 @@ static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg)  	return false;  } -/** Does this bundle modify sp? */ +/* Does this bundle modify sp? */  static inline bool bt_modifies_sp(const struct BacktraceBundle *bundle)  {  	return bt_modifies_reg(bundle, TREG_SP);  } -/** Does this bundle modify lr? */ +/* Does this bundle modify lr? */  static inline bool bt_modifies_lr(const struct BacktraceBundle *bundle)  {  	return bt_modifies_reg(bundle, TREG_LR);  } -/** Does this bundle contain the instruction 'move fp, sp'? */ +/* Does this bundle contain the instruction 'move fp, sp'? */  static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle)  {  	static const int vals[2] = { 52, TREG_SP };  	return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL;  } -/** Does this bundle contain a store of lr to sp? */ +/* Does this bundle contain a store of lr to sp? */  static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle)  {  	static const int vals[2] = { TREG_SP, TREG_LR };  	return find_matching_insn(bundle, OPCODE_STORE, vals, 2) != NULL;  } -#if TILE_CHIP >= 10 -/** Track moveli values placed into registers. */ +#ifdef __tilegx__ +/* Track moveli values placed into registers. */  static inline void bt_update_moveli(const struct BacktraceBundle *bundle,  				    int moveli_args[])  { @@ -238,7 +214,7 @@ static inline void bt_update_moveli(const struct BacktraceBundle *bundle,  	}  } -/** Does this bundle contain an 'add sp, sp, reg' instruction +/* Does this bundle contain an 'add sp, sp, reg' instruction   * from a register that we saw a moveli into, and if so, what   * is the value in the register?   */ @@ -260,11 +236,11 @@ static bool bt_has_add_sp(const struct BacktraceBundle *bundle, int *adjust,  }  #endif -/** Locates the caller's PC and SP for a program starting at the +/* Locates the caller's PC and SP for a program starting at the   * given address.   */  static void find_caller_pc_and_caller_sp(CallerLocation *location, -					 const VirtualAddress start_pc, +					 const unsigned long start_pc,  					 BacktraceMemoryReader read_memory_func,  					 void *read_memory_func_extra)  { @@ -288,9 +264,9 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,  	tile_bundle_bits prefetched_bundles[32];  	int num_bundles_prefetched = 0;  	int next_bundle = 0; -	VirtualAddress pc; +	unsigned long pc; -#if TILE_CHIP >= 10 +#ifdef __tilegx__  	/* Naively try to track moveli values to support addx for -m32. */  	int moveli_args[TILEGX_NUM_REGISTERS] = { 0 };  #endif @@ -369,10 +345,6 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,  					/* Weird; reserved value, ignore it. */  					continue;  				} -				if (info_operand & ENTRY_POINT_INFO_OP)	{ -					/* This info op is ignored by the backtracer. */ -					continue; -				}  				/* Skip info ops which are not in the  				 * "one_ago" mode we want right now. @@ -453,7 +425,7 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,  		if (!sp_determined) {  			int adjust;  			if (bt_has_addi_sp(&bundle, &adjust) -#if TILE_CHIP >= 10 +#ifdef __tilegx__  			    || bt_has_add_sp(&bundle, &adjust, moveli_args)  #endif  				) { @@ -504,7 +476,7 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,  				}  			} -#if TILE_CHIP >= 10 +#ifdef __tilegx__  			/* Track moveli arguments for -m32 mode. */  			bt_update_moveli(&bundle, moveli_args);  #endif @@ -546,18 +518,26 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,  	}  } +/* Initializes a backtracer to start from the given location. + * + * If the frame pointer cannot be determined it is set to -1. + * + * state: The state to be filled in. + * read_memory_func: A callback that reads memory. + * read_memory_func_extra: An arbitrary argument to read_memory_func. + * pc: The current PC. + * lr: The current value of the 'lr' register. + * sp: The current value of the 'sp' register. + * r52: The current value of the 'r52' register. + */  void backtrace_init(BacktraceIterator *state,  		    BacktraceMemoryReader read_memory_func,  		    void *read_memory_func_extra, -		    VirtualAddress pc, VirtualAddress lr, -		    VirtualAddress sp, VirtualAddress r52) +		    unsigned long pc, unsigned long lr, +		    unsigned long sp, unsigned long r52)  {  	CallerLocation location; -	VirtualAddress fp, initial_frame_caller_pc; - -	if (read_memory_func == NULL) { -		read_memory_func = bt_read_memory; -	} +	unsigned long fp, initial_frame_caller_pc;  	/* Find out where we are in the initial frame. */  	find_caller_pc_and_caller_sp(&location, pc, @@ -630,12 +610,15 @@ void backtrace_init(BacktraceIterator *state,  /* Handle the case where the register holds more bits than the VA. */  static bool valid_addr_reg(bt_int_reg_t reg)  { -	return ((VirtualAddress)reg == reg); +	return ((unsigned long)reg == reg);  } +/* Advances the backtracing state to the calling frame, returning + * true iff successful. + */  bool backtrace_next(BacktraceIterator *state)  { -	VirtualAddress next_fp, next_pc; +	unsigned long next_fp, next_pc;  	bt_int_reg_t next_frame[2];  	if (state->fp == -1) {  |