Commit 0896a9becdea36b2da21709b5e73ba47ae6481ea

Authored by Jason Wessel
1 parent 12bfa3de63

kgdb,mips: Individual register get/set for mips

Implement the ability to individually get and set registers for kdb
and kgdb for mips.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
CC: linux-mips@linux-mips.org

Showing 2 changed files with 154 additions and 68 deletions Side-by-side Diff

arch/mips/include/asm/kgdb.h
... ... @@ -8,28 +8,27 @@
8 8 #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
9 9 (_MIPS_ISA == _MIPS_ISA_MIPS32)
10 10  
11   -#define KGDB_GDB_REG_SIZE 32
  11 +#define KGDB_GDB_REG_SIZE 32
  12 +#define GDB_SIZEOF_REG sizeof(u32)
12 13  
13 14 #elif (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
14 15 (_MIPS_ISA == _MIPS_ISA_MIPS64)
15 16  
16 17 #ifdef CONFIG_32BIT
17   -#define KGDB_GDB_REG_SIZE 32
  18 +#define KGDB_GDB_REG_SIZE 32
  19 +#define GDB_SIZEOF_REG sizeof(u32)
18 20 #else /* CONFIG_CPU_32BIT */
19   -#define KGDB_GDB_REG_SIZE 64
  21 +#define KGDB_GDB_REG_SIZE 64
  22 +#define GDB_SIZEOF_REG sizeof(u64)
20 23 #endif
21 24 #else
22 25 #error "Need to set KGDB_GDB_REG_SIZE for MIPS ISA"
23 26 #endif /* _MIPS_ISA */
24 27  
25 28 #define BUFMAX 2048
26   -#if (KGDB_GDB_REG_SIZE == 32)
27   -#define NUMREGBYTES (90*sizeof(u32))
28   -#define NUMCRITREGBYTES (12*sizeof(u32))
29   -#else
30   -#define NUMREGBYTES (90*sizeof(u64))
31   -#define NUMCRITREGBYTES (12*sizeof(u64))
32   -#endif
  29 +#define DBG_MAX_REG_NUM 72
  30 +#define NUMREGBYTES (DBG_MAX_REG_NUM * sizeof(GDB_SIZEOF_REG))
  31 +#define NUMCRITREGBYTES (12 * sizeof(GDB_SIZEOF_REG))
33 32 #define BREAK_INSTR_SIZE 4
34 33 #define CACHE_FLUSH_IS_SAFE 0
35 34  
arch/mips/kernel/kgdb.c
... ... @@ -50,6 +50,151 @@
50 50 { 0, 0} /* Must be last */
51 51 };
52 52  
  53 +struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
  54 +{
  55 + { "zero", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[0]) },
  56 + { "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[1]) },
  57 + { "v0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[2]) },
  58 + { "v1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[3]) },
  59 + { "a0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[4]) },
  60 + { "a1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[5]) },
  61 + { "a2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[6]) },
  62 + { "a3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[7]) },
  63 + { "t0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[8]) },
  64 + { "t1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[9]) },
  65 + { "t2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[10]) },
  66 + { "t3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[11]) },
  67 + { "t4", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[12]) },
  68 + { "t5", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[13]) },
  69 + { "t6", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[14]) },
  70 + { "t7", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[15]) },
  71 + { "s0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[16]) },
  72 + { "s1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[17]) },
  73 + { "s2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[18]) },
  74 + { "s3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[19]) },
  75 + { "s4", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[20]) },
  76 + { "s5", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[21]) },
  77 + { "s6", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[22]) },
  78 + { "s7", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[23]) },
  79 + { "t8", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[24]) },
  80 + { "t9", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[25]) },
  81 + { "k0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[26]) },
  82 + { "k1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[27]) },
  83 + { "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[28]) },
  84 + { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[29]) },
  85 + { "s8", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[30]) },
  86 + { "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[31]) },
  87 + { "sr", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_status) },
  88 + { "lo", GDB_SIZEOF_REG, offsetof(struct pt_regs, lo) },
  89 + { "hi", GDB_SIZEOF_REG, offsetof(struct pt_regs, hi) },
  90 + { "bad", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_badvaddr) },
  91 + { "cause", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_cause) },
  92 + { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_epc) },
  93 + { "f0", GDB_SIZEOF_REG, 0 },
  94 + { "f1", GDB_SIZEOF_REG, 1 },
  95 + { "f2", GDB_SIZEOF_REG, 2 },
  96 + { "f3", GDB_SIZEOF_REG, 3 },
  97 + { "f4", GDB_SIZEOF_REG, 4 },
  98 + { "f5", GDB_SIZEOF_REG, 5 },
  99 + { "f6", GDB_SIZEOF_REG, 6 },
  100 + { "f7", GDB_SIZEOF_REG, 7 },
  101 + { "f8", GDB_SIZEOF_REG, 8 },
  102 + { "f9", GDB_SIZEOF_REG, 9 },
  103 + { "f10", GDB_SIZEOF_REG, 10 },
  104 + { "f11", GDB_SIZEOF_REG, 11 },
  105 + { "f12", GDB_SIZEOF_REG, 12 },
  106 + { "f13", GDB_SIZEOF_REG, 13 },
  107 + { "f14", GDB_SIZEOF_REG, 14 },
  108 + { "f15", GDB_SIZEOF_REG, 15 },
  109 + { "f16", GDB_SIZEOF_REG, 16 },
  110 + { "f17", GDB_SIZEOF_REG, 17 },
  111 + { "f18", GDB_SIZEOF_REG, 18 },
  112 + { "f19", GDB_SIZEOF_REG, 19 },
  113 + { "f20", GDB_SIZEOF_REG, 20 },
  114 + { "f21", GDB_SIZEOF_REG, 21 },
  115 + { "f22", GDB_SIZEOF_REG, 22 },
  116 + { "f23", GDB_SIZEOF_REG, 23 },
  117 + { "f24", GDB_SIZEOF_REG, 24 },
  118 + { "f25", GDB_SIZEOF_REG, 25 },
  119 + { "f26", GDB_SIZEOF_REG, 26 },
  120 + { "f27", GDB_SIZEOF_REG, 27 },
  121 + { "f28", GDB_SIZEOF_REG, 28 },
  122 + { "f29", GDB_SIZEOF_REG, 29 },
  123 + { "f30", GDB_SIZEOF_REG, 30 },
  124 + { "f31", GDB_SIZEOF_REG, 31 },
  125 + { "fsr", GDB_SIZEOF_REG, 0 },
  126 + { "fir", GDB_SIZEOF_REG, 0 },
  127 +};
  128 +
  129 +int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
  130 +{
  131 + int fp_reg;
  132 +
  133 + if (regno < 0 || regno >= DBG_MAX_REG_NUM)
  134 + return -EINVAL;
  135 +
  136 + if (dbg_reg_def[regno].offset != -1 && regno < 38) {
  137 + memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
  138 + dbg_reg_def[regno].size);
  139 + } else if (current && dbg_reg_def[regno].offset != -1 && regno < 72) {
  140 + /* FP registers 38 -> 69 */
  141 + if (!(regs->cp0_status & ST0_CU1))
  142 + return 0;
  143 + if (regno == 70) {
  144 + /* Process the fcr31/fsr (register 70) */
  145 + memcpy((void *)&current->thread.fpu.fcr31, mem,
  146 + dbg_reg_def[regno].size);
  147 + goto out_save;
  148 + } else if (regno == 71) {
  149 + /* Ignore the fir (register 71) */
  150 + goto out_save;
  151 + }
  152 + fp_reg = dbg_reg_def[regno].offset;
  153 + memcpy((void *)&current->thread.fpu.fpr[fp_reg], mem,
  154 + dbg_reg_def[regno].size);
  155 +out_save:
  156 + restore_fp(current);
  157 + }
  158 +
  159 + return 0;
  160 +}
  161 +
  162 +char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
  163 +{
  164 + int fp_reg;
  165 +
  166 + if (regno >= DBG_MAX_REG_NUM || regno < 0)
  167 + return NULL;
  168 +
  169 + if (dbg_reg_def[regno].offset != -1 && regno < 38) {
  170 + /* First 38 registers */
  171 + memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
  172 + dbg_reg_def[regno].size);
  173 + } else if (current && dbg_reg_def[regno].offset != -1 && regno < 72) {
  174 + /* FP registers 38 -> 69 */
  175 + if (!(regs->cp0_status & ST0_CU1))
  176 + goto out;
  177 + save_fp(current);
  178 + if (regno == 70) {
  179 + /* Process the fcr31/fsr (register 70) */
  180 + memcpy(mem, (void *)&current->thread.fpu.fcr31,
  181 + dbg_reg_def[regno].size);
  182 + goto out;
  183 + } else if (regno == 71) {
  184 + /* Ignore the fir (register 71) */
  185 + memset(mem, 0, dbg_reg_def[regno].size);
  186 + goto out;
  187 + }
  188 + fp_reg = dbg_reg_def[regno].offset;
  189 + memcpy(mem, (void *)&current->thread.fpu.fpr[fp_reg],
  190 + dbg_reg_def[regno].size);
  191 + }
  192 +
  193 +out:
  194 + return dbg_reg_def[regno].name;
  195 +
  196 +}
  197 +
53 198 void arch_kgdb_breakpoint(void)
54 199 {
55 200 __asm__ __volatile__(
... ... @@ -82,64 +227,6 @@
82 227 return ht->signo;
83 228  
84 229 return SIGHUP; /* default for things we don't know about */
85   -}
86   -
87   -void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
88   -{
89   - int reg;
90   -
91   -#if (KGDB_GDB_REG_SIZE == 32)
92   - u32 *ptr = (u32 *)gdb_regs;
93   -#else
94   - u64 *ptr = (u64 *)gdb_regs;
95   -#endif
96   -
97   - for (reg = 0; reg < 32; reg++)
98   - *(ptr++) = regs->regs[reg];
99   -
100   - *(ptr++) = regs->cp0_status;
101   - *(ptr++) = regs->lo;
102   - *(ptr++) = regs->hi;
103   - *(ptr++) = regs->cp0_badvaddr;
104   - *(ptr++) = regs->cp0_cause;
105   - *(ptr++) = regs->cp0_epc;
106   -
107   - /* FP REGS */
108   - if (!(current && (regs->cp0_status & ST0_CU1)))
109   - return;
110   -
111   - save_fp(current);
112   - for (reg = 0; reg < 32; reg++)
113   - *(ptr++) = current->thread.fpu.fpr[reg];
114   -}
115   -
116   -void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
117   -{
118   - int reg;
119   -
120   -#if (KGDB_GDB_REG_SIZE == 32)
121   - const u32 *ptr = (u32 *)gdb_regs;
122   -#else
123   - const u64 *ptr = (u64 *)gdb_regs;
124   -#endif
125   -
126   - for (reg = 0; reg < 32; reg++)
127   - regs->regs[reg] = *(ptr++);
128   -
129   - regs->cp0_status = *(ptr++);
130   - regs->lo = *(ptr++);
131   - regs->hi = *(ptr++);
132   - regs->cp0_badvaddr = *(ptr++);
133   - regs->cp0_cause = *(ptr++);
134   - regs->cp0_epc = *(ptr++);
135   -
136   - /* FP REGS from current */
137   - if (!(current && (regs->cp0_status & ST0_CU1)))
138   - return;
139   -
140   - for (reg = 0; reg < 32; reg++)
141   - current->thread.fpu.fpr[reg] = *(ptr++);
142   - restore_fp(current);
143 230 }
144 231  
145 232 /*