diff options
| author | Chris Metcalf <cmetcalf@tilera.com> | 2010-08-13 08:40:57 -0400 |
|---|---|---|
| committer | Chris Metcalf <cmetcalf@tilera.com> | 2010-08-13 08:40:57 -0400 |
| commit | 1fcbe027b5d29ec9cd0eeb753c14fb366ae852ac (patch) | |
| tree | b0d80646567ac71238cf2ffb33e29ad33d758816 | |
| parent | 32020effaf713c0c669864301bcd5dac6b9bb9e0 (diff) | |
arch/tile: support backtracing on TILE-Gx
This functionality was stubbed out until recently. Now we support our
normal backtracing API on TILE-Gx as well as on TILE64/TILEPro.
This change includes a tweak to the instruction encoding caused by
adding addxli for compat mode.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
| -rw-r--r-- | arch/tile/include/asm/backtrace.h | 4 | ||||
| -rw-r--r-- | arch/tile/kernel/backtrace.c | 137 | ||||
| -rw-r--r-- | arch/tile/kernel/stack.c | 8 | ||||
| -rw-r--r-- | arch/tile/kernel/traps.c | 4 |
4 files changed, 105 insertions, 48 deletions
diff --git a/arch/tile/include/asm/backtrace.h b/arch/tile/include/asm/backtrace.h index 6970bfcad549..758ca4619d50 100644 --- a/arch/tile/include/asm/backtrace.h +++ b/arch/tile/include/asm/backtrace.h | |||
| @@ -21,7 +21,9 @@ | |||
| 21 | 21 | ||
| 22 | #include <arch/chip.h> | 22 | #include <arch/chip.h> |
| 23 | 23 | ||
| 24 | #if CHIP_VA_WIDTH() > 32 | 24 | #if defined(__tile__) |
| 25 | typedef unsigned long VirtualAddress; | ||
| 26 | #elif CHIP_VA_WIDTH() > 32 | ||
| 25 | typedef unsigned long long VirtualAddress; | 27 | typedef unsigned long long VirtualAddress; |
| 26 | #else | 28 | #else |
| 27 | typedef unsigned int VirtualAddress; | 29 | typedef unsigned int VirtualAddress; |
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c index 77265f3b58d6..d3c41c1ff6bd 100644 --- a/arch/tile/kernel/backtrace.c +++ b/arch/tile/kernel/backtrace.c | |||
| @@ -19,9 +19,6 @@ | |||
| 19 | 19 | ||
| 20 | #include <arch/chip.h> | 20 | #include <arch/chip.h> |
| 21 | 21 | ||
| 22 | #if TILE_CHIP < 10 | ||
| 23 | |||
| 24 | |||
| 25 | #include <asm/opcode-tile.h> | 22 | #include <asm/opcode-tile.h> |
| 26 | 23 | ||
| 27 | 24 | ||
| @@ -29,6 +26,27 @@ | |||
| 29 | #define TREG_LR 55 | 26 | #define TREG_LR 55 |
| 30 | 27 | ||
| 31 | 28 | ||
| 29 | #if TILE_CHIP >= 10 | ||
| 30 | #define tile_bundle_bits tilegx_bundle_bits | ||
| 31 | #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE | ||
| 32 | #define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES | ||
| 33 | #define tile_decoded_instruction tilegx_decoded_instruction | ||
| 34 | #define tile_mnemonic tilegx_mnemonic | ||
| 35 | #define parse_insn_tile parse_insn_tilegx | ||
| 36 | #define TILE_OPC_IRET TILEGX_OPC_IRET | ||
| 37 | #define TILE_OPC_ADDI TILEGX_OPC_ADDI | ||
| 38 | #define TILE_OPC_ADDLI TILEGX_OPC_ADDLI | ||
| 39 | #define TILE_OPC_INFO TILEGX_OPC_INFO | ||
| 40 | #define TILE_OPC_INFOL TILEGX_OPC_INFOL | ||
| 41 | #define TILE_OPC_JRP TILEGX_OPC_JRP | ||
| 42 | #define TILE_OPC_MOVE TILEGX_OPC_MOVE | ||
| 43 | #define OPCODE_STORE TILEGX_OPC_ST | ||
| 44 | typedef long long bt_int_reg_t; | ||
| 45 | #else | ||
| 46 | #define OPCODE_STORE TILE_OPC_SW | ||
| 47 | typedef int bt_int_reg_t; | ||
| 48 | #endif | ||
| 49 | |||
| 32 | /** A decoded bundle used for backtracer analysis. */ | 50 | /** A decoded bundle used for backtracer analysis. */ |
| 33 | struct BacktraceBundle { | 51 | struct BacktraceBundle { |
| 34 | tile_bundle_bits bits; | 52 | tile_bundle_bits bits; |
| @@ -41,7 +59,7 @@ struct BacktraceBundle { | |||
| 41 | /* This implementation only makes sense for native tools. */ | 59 | /* This implementation only makes sense for native tools. */ |
| 42 | /** Default function to read memory. */ | 60 | /** Default function to read memory. */ |
| 43 | static bool bt_read_memory(void *result, VirtualAddress addr, | 61 | static bool bt_read_memory(void *result, VirtualAddress addr, |
| 44 | size_t size, void *extra) | 62 | unsigned int size, void *extra) |
| 45 | { | 63 | { |
| 46 | /* FIXME: this should do some horrible signal stuff to catch | 64 | /* FIXME: this should do some horrible signal stuff to catch |
| 47 | * SEGV cleanly and fail. | 65 | * SEGV cleanly and fail. |
| @@ -106,6 +124,12 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) | |||
| 106 | find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); | 124 | find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); |
| 107 | if (insn == NULL) | 125 | if (insn == NULL) |
| 108 | insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); | 126 | insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); |
| 127 | #if TILE_CHIP >= 10 | ||
| 128 | if (insn == NULL) | ||
| 129 | insn = find_matching_insn(bundle, TILEGX_OPC_ADDXLI, vals, 2); | ||
| 130 | if (insn == NULL) | ||
| 131 | insn = find_matching_insn(bundle, TILEGX_OPC_ADDXI, vals, 2); | ||
| 132 | #endif | ||
| 109 | if (insn == NULL) | 133 | if (insn == NULL) |
| 110 | return false; | 134 | return false; |
| 111 | 135 | ||
| @@ -190,13 +214,52 @@ static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle) | |||
| 190 | return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; | 214 | return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; |
| 191 | } | 215 | } |
| 192 | 216 | ||
| 193 | /** Does this bundle contain the instruction 'sw sp, lr'? */ | 217 | /** Does this bundle contain a store of lr to sp? */ |
| 194 | static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle) | 218 | static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle) |
| 195 | { | 219 | { |
| 196 | static const int vals[2] = { TREG_SP, TREG_LR }; | 220 | static const int vals[2] = { TREG_SP, TREG_LR }; |
| 197 | return find_matching_insn(bundle, TILE_OPC_SW, vals, 2) != NULL; | 221 | return find_matching_insn(bundle, OPCODE_STORE, vals, 2) != NULL; |
| 222 | } | ||
| 223 | |||
| 224 | #if TILE_CHIP >= 10 | ||
| 225 | /** Track moveli values placed into registers. */ | ||
| 226 | static inline void bt_update_moveli(const struct BacktraceBundle *bundle, | ||
| 227 | int moveli_args[]) | ||
| 228 | { | ||
| 229 | int i; | ||
| 230 | for (i = 0; i < bundle->num_insns; i++) { | ||
| 231 | const struct tile_decoded_instruction *insn = | ||
| 232 | &bundle->insns[i]; | ||
| 233 | |||
| 234 | if (insn->opcode->mnemonic == TILEGX_OPC_MOVELI) { | ||
| 235 | int reg = insn->operand_values[0]; | ||
| 236 | moveli_args[reg] = insn->operand_values[1]; | ||
| 237 | } | ||
| 238 | } | ||
| 198 | } | 239 | } |
| 199 | 240 | ||
| 241 | /** Does this bundle contain an 'add sp, sp, reg' instruction | ||
| 242 | * from a register that we saw a moveli into, and if so, what | ||
| 243 | * is the value in the register? | ||
| 244 | */ | ||
| 245 | static bool bt_has_add_sp(const struct BacktraceBundle *bundle, int *adjust, | ||
| 246 | int moveli_args[]) | ||
| 247 | { | ||
| 248 | static const int vals[2] = { TREG_SP, TREG_SP }; | ||
| 249 | |||
| 250 | const struct tile_decoded_instruction *insn = | ||
| 251 | find_matching_insn(bundle, TILEGX_OPC_ADDX, vals, 2); | ||
| 252 | if (insn) { | ||
| 253 | int reg = insn->operand_values[2]; | ||
| 254 | if (moveli_args[reg]) { | ||
| 255 | *adjust = moveli_args[reg]; | ||
| 256 | return true; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | return false; | ||
| 260 | } | ||
| 261 | #endif | ||
| 262 | |||
| 200 | /** Locates the caller's PC and SP for a program starting at the | 263 | /** Locates the caller's PC and SP for a program starting at the |
| 201 | * given address. | 264 | * given address. |
| 202 | */ | 265 | */ |
| @@ -227,6 +290,11 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
| 227 | int next_bundle = 0; | 290 | int next_bundle = 0; |
| 228 | VirtualAddress pc; | 291 | VirtualAddress pc; |
| 229 | 292 | ||
| 293 | #if TILE_CHIP >= 10 | ||
| 294 | /* Naively try to track moveli values to support addx for -m32. */ | ||
| 295 | int moveli_args[TILEGX_NUM_REGISTERS] = { 0 }; | ||
| 296 | #endif | ||
| 297 | |||
| 230 | /* Default to assuming that the caller's sp is the current sp. | 298 | /* Default to assuming that the caller's sp is the current sp. |
| 231 | * This is necessary to handle the case where we start backtracing | 299 | * This is necessary to handle the case where we start backtracing |
| 232 | * right at the end of the epilog. | 300 | * right at the end of the epilog. |
| @@ -380,7 +448,11 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
| 380 | 448 | ||
| 381 | if (!sp_determined) { | 449 | if (!sp_determined) { |
| 382 | int adjust; | 450 | int adjust; |
| 383 | if (bt_has_addi_sp(&bundle, &adjust)) { | 451 | if (bt_has_addi_sp(&bundle, &adjust) |
| 452 | #if TILE_CHIP >= 10 | ||
| 453 | || bt_has_add_sp(&bundle, &adjust, moveli_args) | ||
| 454 | #endif | ||
| 455 | ) { | ||
| 384 | location->sp_location = SP_LOC_OFFSET; | 456 | location->sp_location = SP_LOC_OFFSET; |
| 385 | 457 | ||
| 386 | if (adjust <= 0) { | 458 | if (adjust <= 0) { |
| @@ -427,6 +499,11 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
| 427 | sp_determined = true; | 499 | sp_determined = true; |
| 428 | } | 500 | } |
| 429 | } | 501 | } |
| 502 | |||
| 503 | #if TILE_CHIP >= 10 | ||
| 504 | /* Track moveli arguments for -m32 mode. */ | ||
| 505 | bt_update_moveli(&bundle, moveli_args); | ||
| 506 | #endif | ||
| 430 | } | 507 | } |
