diff options
Diffstat (limited to 'arch/blackfin')
-rw-r--r-- | arch/blackfin/kernel/pseudodbg.c | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/arch/blackfin/kernel/pseudodbg.c b/arch/blackfin/kernel/pseudodbg.c index a5a4636124aa..e57ce2f64bfe 100644 --- a/arch/blackfin/kernel/pseudodbg.c +++ b/arch/blackfin/kernel/pseudodbg.c | |||
@@ -9,16 +9,43 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/ptrace.h> | 10 | #include <linux/ptrace.h> |
11 | 11 | ||
12 | const char * const greg_names[] = { | ||
13 | "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", | ||
14 | "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP", | ||
15 | "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3", | ||
16 | "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3", | ||
17 | "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS", | ||
18 | "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", | ||
19 | "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2", | ||
20 | "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT", | ||
21 | }; | ||
22 | |||
23 | static const char *get_allreg_name(int grp, int reg) | ||
24 | { | ||
25 | return greg_names[(grp << 3) | reg]; | ||
26 | } | ||
27 | |||
12 | /* | 28 | /* |
13 | * Unfortunately, the pt_regs structure is not laid out the same way as the | 29 | * Unfortunately, the pt_regs structure is not laid out the same way as the |
14 | * hardware register file, so we need to do some fix ups. | 30 | * hardware register file, so we need to do some fix ups. |
31 | * | ||
32 | * CYCLES is not stored in the pt_regs structure - so, we just read it from | ||
33 | * the hardware. | ||
34 | * | ||
35 | * Don't support: | ||
36 | * - All reserved registers | ||
37 | * - All in group 7 are (supervisors only) | ||
15 | */ | 38 | */ |
39 | |||
16 | static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg) | 40 | static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg) |
17 | { | 41 | { |
18 | long *val = &fp->r0; | 42 | long *val = &fp->r0; |
43 | unsigned long tmp; | ||
19 | 44 | ||
20 | /* Only do Dregs and Pregs for now */ | 45 | /* Only do Dregs and Pregs for now */ |
21 | if (grp > 1) | 46 | if (grp == 5 || |
47 | (grp == 4 && (reg == 4 || reg == 5)) || | ||
48 | (grp == 7)) | ||
22 | return false; | 49 | return false; |
23 | 50 | ||
24 | if (grp == 0 || (grp == 1 && reg < 6)) | 51 | if (grp == 0 || (grp == 1 && reg < 6)) |
@@ -27,6 +54,32 @@ static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg) | |||
27 | val = &fp->usp; | 54 | val = &fp->usp; |
28 | else if (grp == 1 && reg == 7) | 55 | else if (grp == 1 && reg == 7) |
29 | val = &fp->fp; | 56 | val = &fp->fp; |
57 | else if (grp == 2) { | ||
58 | val = &fp->i0; | ||
59 | val -= reg; | ||
60 | } else if (grp == 3 && reg >= 4) { | ||
61 | val = &fp->l0; | ||
62 | val -= (reg - 4); | ||
63 | } else if (grp == 3 && reg < 4) { | ||
64 | val = &fp->b0; | ||
65 | val -= reg; | ||
66 | } else if (grp == 4 && reg < 4) { | ||
67 | val = &fp->a0x; | ||
68 | val -= reg; | ||
69 | } else if (grp == 4 && reg == 6) | ||
70 | val = &fp->astat; | ||
71 | else if (grp == 4 && reg == 7) | ||
72 | val = &fp->rets; | ||
73 | else if (grp == 6 && reg < 6) { | ||
74 | val = &fp->lc0; | ||
75 | val -= reg; | ||
76 | } else if (grp == 6 && reg == 6) { | ||
77 | __asm__ __volatile__("%0 = cycles;\n" : "=d"(tmp)); | ||
78 | val = &tmp; | ||
79 | } else if (grp == 6 && reg == 7) { | ||
80 | __asm__ __volatile__("%0 = cycles2;\n" : "=d"(tmp)); | ||
81 | val = &tmp; | ||
82 | } | ||
30 | 83 | ||
31 | *value = *val; | 84 | *value = *val; |
32 | return true; | 85 | return true; |
@@ -68,8 +121,9 @@ bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode) | |||
68 | /* DBGA ( regs_lo , uimm16 ) */ | 121 | /* DBGA ( regs_lo , uimm16 ) */ |
69 | /* DBGAL ( regs , uimm16 ) */ | 122 | /* DBGAL ( regs , uimm16 ) */ |
70 | if (expected != (value & 0xFFFF)) { | 123 | if (expected != (value & 0xFFFF)) { |
71 | pr_notice("DBGA (%s%i.L,0x%x) failure, got 0x%x\n", grp ? "P" : "R", | 124 | pr_notice("DBGA (%s.L,0x%x) failure, got 0x%x\n", |
72 | regtest, expected, (unsigned int)(value & 0xFFFF)); | 125 | get_allreg_name(grp, regtest), |
126 | expected, (unsigned int)(value & 0xFFFF)); | ||
73 | return false; | 127 | return false; |
74 | } | 128 | } |
75 | 129 | ||
@@ -77,8 +131,9 @@ bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode) | |||
77 | /* DBGA ( regs_hi , uimm16 ) */ | 131 | /* DBGA ( regs_hi , uimm16 ) */ |
78 | /* DBGAH ( regs , uimm16 ) */ | 132 | /* DBGAH ( regs , uimm16 ) */ |
79 | if (expected != ((value >> 16) & 0xFFFF)) { | 133 | if (expected != ((value >> 16) & 0xFFFF)) { |
80 | pr_notice("DBGA (%s%i.H,0x%x) failure, got 0x%x\n", grp ? "P" : "R", | 134 | pr_notice("DBGA (%s.H,0x%x) failure, got 0x%x\n", |
81 | regtest, expected, (unsigned int)((value >> 16) & 0xFFFF)); | 135 | get_allreg_name(grp, regtest), |
136 | expected, (unsigned int)((value >> 16) & 0xFFFF)); | ||
82 | return false; | 137 | return false; |
83 | } | 138 | } |
84 | } | 139 | } |
@@ -116,7 +171,7 @@ bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode) | |||
116 | if (!fix_up_reg(fp, &value, grp, reg)) | 171 | if (!fix_up_reg(fp, &value, grp, reg)) |
117 | return false; | 172 | return false; |
118 | 173 | ||
119 | pr_notice("DBG %s%d = %08lx\n", grp ? "P" : "R", reg, value); | 174 | pr_notice("DBG %s = %08lx\n", get_allreg_name(grp, reg), value); |
120 | 175 | ||
121 | fp->pc += 2; | 176 | fp->pc += 2; |
122 | return true; | 177 | return true; |