1 | /* |
2 | * RISC-V GDB Server Stub |
3 | * |
4 | * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, |
8 | * version 2 or later, as published by the Free Software Foundation. |
9 | * |
10 | * This program is distributed in the hope it will be useful, but WITHOUT |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
13 | * more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along with |
16 | * this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | #include "qemu/osdep.h" |
20 | #include "exec/gdbstub.h" |
21 | #include "cpu.h" |
22 | |
23 | /* |
24 | * The GDB CSR xml files list them in documentation order, not numerical order, |
25 | * and are missing entries for unnamed CSRs. So we need to map the gdb numbers |
26 | * to the hardware numbers. |
27 | */ |
28 | |
29 | static int csr_register_map[] = { |
30 | CSR_USTATUS, |
31 | CSR_UIE, |
32 | CSR_UTVEC, |
33 | CSR_USCRATCH, |
34 | CSR_UEPC, |
35 | CSR_UCAUSE, |
36 | CSR_UTVAL, |
37 | CSR_UIP, |
38 | CSR_FFLAGS, |
39 | CSR_FRM, |
40 | CSR_FCSR, |
41 | CSR_CYCLE, |
42 | CSR_TIME, |
43 | CSR_INSTRET, |
44 | CSR_HPMCOUNTER3, |
45 | CSR_HPMCOUNTER4, |
46 | CSR_HPMCOUNTER5, |
47 | CSR_HPMCOUNTER6, |
48 | CSR_HPMCOUNTER7, |
49 | CSR_HPMCOUNTER8, |
50 | CSR_HPMCOUNTER9, |
51 | CSR_HPMCOUNTER10, |
52 | CSR_HPMCOUNTER11, |
53 | CSR_HPMCOUNTER12, |
54 | CSR_HPMCOUNTER13, |
55 | CSR_HPMCOUNTER14, |
56 | CSR_HPMCOUNTER15, |
57 | CSR_HPMCOUNTER16, |
58 | CSR_HPMCOUNTER17, |
59 | CSR_HPMCOUNTER18, |
60 | CSR_HPMCOUNTER19, |
61 | CSR_HPMCOUNTER20, |
62 | CSR_HPMCOUNTER21, |
63 | CSR_HPMCOUNTER22, |
64 | CSR_HPMCOUNTER23, |
65 | CSR_HPMCOUNTER24, |
66 | CSR_HPMCOUNTER25, |
67 | CSR_HPMCOUNTER26, |
68 | CSR_HPMCOUNTER27, |
69 | CSR_HPMCOUNTER28, |
70 | CSR_HPMCOUNTER29, |
71 | CSR_HPMCOUNTER30, |
72 | CSR_HPMCOUNTER31, |
73 | CSR_CYCLEH, |
74 | CSR_TIMEH, |
75 | CSR_INSTRETH, |
76 | CSR_HPMCOUNTER3H, |
77 | CSR_HPMCOUNTER4H, |
78 | CSR_HPMCOUNTER5H, |
79 | CSR_HPMCOUNTER6H, |
80 | CSR_HPMCOUNTER7H, |
81 | CSR_HPMCOUNTER8H, |
82 | CSR_HPMCOUNTER9H, |
83 | CSR_HPMCOUNTER10H, |
84 | CSR_HPMCOUNTER11H, |
85 | CSR_HPMCOUNTER12H, |
86 | CSR_HPMCOUNTER13H, |
87 | CSR_HPMCOUNTER14H, |
88 | CSR_HPMCOUNTER15H, |
89 | CSR_HPMCOUNTER16H, |
90 | CSR_HPMCOUNTER17H, |
91 | CSR_HPMCOUNTER18H, |
92 | CSR_HPMCOUNTER19H, |
93 | CSR_HPMCOUNTER20H, |
94 | CSR_HPMCOUNTER21H, |
95 | CSR_HPMCOUNTER22H, |
96 | CSR_HPMCOUNTER23H, |
97 | CSR_HPMCOUNTER24H, |
98 | CSR_HPMCOUNTER25H, |
99 | CSR_HPMCOUNTER26H, |
100 | CSR_HPMCOUNTER27H, |
101 | CSR_HPMCOUNTER28H, |
102 | CSR_HPMCOUNTER29H, |
103 | CSR_HPMCOUNTER30H, |
104 | CSR_HPMCOUNTER31H, |
105 | CSR_SSTATUS, |
106 | CSR_SEDELEG, |
107 | CSR_SIDELEG, |
108 | CSR_SIE, |
109 | CSR_STVEC, |
110 | CSR_SCOUNTEREN, |
111 | CSR_SSCRATCH, |
112 | CSR_SEPC, |
113 | CSR_SCAUSE, |
114 | CSR_STVAL, |
115 | CSR_SIP, |
116 | CSR_SATP, |
117 | CSR_MVENDORID, |
118 | CSR_MARCHID, |
119 | CSR_MIMPID, |
120 | CSR_MHARTID, |
121 | CSR_MSTATUS, |
122 | CSR_MISA, |
123 | CSR_MEDELEG, |
124 | CSR_MIDELEG, |
125 | CSR_MIE, |
126 | CSR_MTVEC, |
127 | CSR_MCOUNTEREN, |
128 | CSR_MSCRATCH, |
129 | CSR_MEPC, |
130 | CSR_MCAUSE, |
131 | CSR_MTVAL, |
132 | CSR_MIP, |
133 | CSR_PMPCFG0, |
134 | CSR_PMPCFG1, |
135 | CSR_PMPCFG2, |
136 | CSR_PMPCFG3, |
137 | CSR_PMPADDR0, |
138 | CSR_PMPADDR1, |
139 | CSR_PMPADDR2, |
140 | CSR_PMPADDR3, |
141 | CSR_PMPADDR4, |
142 | CSR_PMPADDR5, |
143 | CSR_PMPADDR6, |
144 | CSR_PMPADDR7, |
145 | CSR_PMPADDR8, |
146 | CSR_PMPADDR9, |
147 | CSR_PMPADDR10, |
148 | CSR_PMPADDR11, |
149 | CSR_PMPADDR12, |
150 | CSR_PMPADDR13, |
151 | CSR_PMPADDR14, |
152 | CSR_PMPADDR15, |
153 | CSR_MCYCLE, |
154 | CSR_MINSTRET, |
155 | CSR_MHPMCOUNTER3, |
156 | CSR_MHPMCOUNTER4, |
157 | CSR_MHPMCOUNTER5, |
158 | CSR_MHPMCOUNTER6, |
159 | CSR_MHPMCOUNTER7, |
160 | CSR_MHPMCOUNTER8, |
161 | CSR_MHPMCOUNTER9, |
162 | CSR_MHPMCOUNTER10, |
163 | CSR_MHPMCOUNTER11, |
164 | CSR_MHPMCOUNTER12, |
165 | CSR_MHPMCOUNTER13, |
166 | CSR_MHPMCOUNTER14, |
167 | CSR_MHPMCOUNTER15, |
168 | CSR_MHPMCOUNTER16, |
169 | CSR_MHPMCOUNTER17, |
170 | CSR_MHPMCOUNTER18, |
171 | CSR_MHPMCOUNTER19, |
172 | CSR_MHPMCOUNTER20, |
173 | CSR_MHPMCOUNTER21, |
174 | CSR_MHPMCOUNTER22, |
175 | CSR_MHPMCOUNTER23, |
176 | CSR_MHPMCOUNTER24, |
177 | CSR_MHPMCOUNTER25, |
178 | CSR_MHPMCOUNTER26, |
179 | CSR_MHPMCOUNTER27, |
180 | CSR_MHPMCOUNTER28, |
181 | CSR_MHPMCOUNTER29, |
182 | CSR_MHPMCOUNTER30, |
183 | CSR_MHPMCOUNTER31, |
184 | CSR_MCYCLEH, |
185 | CSR_MINSTRETH, |
186 | CSR_MHPMCOUNTER3H, |
187 | CSR_MHPMCOUNTER4H, |
188 | CSR_MHPMCOUNTER5H, |
189 | CSR_MHPMCOUNTER6H, |
190 | CSR_MHPMCOUNTER7H, |
191 | CSR_MHPMCOUNTER8H, |
192 | CSR_MHPMCOUNTER9H, |
193 | CSR_MHPMCOUNTER10H, |
194 | CSR_MHPMCOUNTER11H, |
195 | CSR_MHPMCOUNTER12H, |
196 | CSR_MHPMCOUNTER13H, |
197 | CSR_MHPMCOUNTER14H, |
198 | CSR_MHPMCOUNTER15H, |
199 | CSR_MHPMCOUNTER16H, |
200 | CSR_MHPMCOUNTER17H, |
201 | CSR_MHPMCOUNTER18H, |
202 | CSR_MHPMCOUNTER19H, |
203 | CSR_MHPMCOUNTER20H, |
204 | CSR_MHPMCOUNTER21H, |
205 | CSR_MHPMCOUNTER22H, |
206 | CSR_MHPMCOUNTER23H, |
207 | CSR_MHPMCOUNTER24H, |
208 | CSR_MHPMCOUNTER25H, |
209 | CSR_MHPMCOUNTER26H, |
210 | CSR_MHPMCOUNTER27H, |
211 | CSR_MHPMCOUNTER28H, |
212 | CSR_MHPMCOUNTER29H, |
213 | CSR_MHPMCOUNTER30H, |
214 | CSR_MHPMCOUNTER31H, |
215 | CSR_MHPMEVENT3, |
216 | CSR_MHPMEVENT4, |
217 | CSR_MHPMEVENT5, |
218 | CSR_MHPMEVENT6, |
219 | CSR_MHPMEVENT7, |
220 | CSR_MHPMEVENT8, |
221 | CSR_MHPMEVENT9, |
222 | CSR_MHPMEVENT10, |
223 | CSR_MHPMEVENT11, |
224 | CSR_MHPMEVENT12, |
225 | CSR_MHPMEVENT13, |
226 | CSR_MHPMEVENT14, |
227 | CSR_MHPMEVENT15, |
228 | CSR_MHPMEVENT16, |
229 | CSR_MHPMEVENT17, |
230 | CSR_MHPMEVENT18, |
231 | CSR_MHPMEVENT19, |
232 | CSR_MHPMEVENT20, |
233 | CSR_MHPMEVENT21, |
234 | CSR_MHPMEVENT22, |
235 | CSR_MHPMEVENT23, |
236 | CSR_MHPMEVENT24, |
237 | CSR_MHPMEVENT25, |
238 | CSR_MHPMEVENT26, |
239 | CSR_MHPMEVENT27, |
240 | CSR_MHPMEVENT28, |
241 | CSR_MHPMEVENT29, |
242 | CSR_MHPMEVENT30, |
243 | CSR_MHPMEVENT31, |
244 | CSR_TSELECT, |
245 | CSR_TDATA1, |
246 | CSR_TDATA2, |
247 | CSR_TDATA3, |
248 | CSR_DCSR, |
249 | CSR_DPC, |
250 | CSR_DSCRATCH, |
251 | CSR_HSTATUS, |
252 | CSR_HEDELEG, |
253 | CSR_HIDELEG, |
254 | CSR_HIE, |
255 | CSR_HTVEC, |
256 | CSR_HSCRATCH, |
257 | CSR_HEPC, |
258 | CSR_HCAUSE, |
259 | CSR_HBADADDR, |
260 | CSR_HIP, |
261 | CSR_MBASE, |
262 | CSR_MBOUND, |
263 | CSR_MIBASE, |
264 | CSR_MIBOUND, |
265 | CSR_MDBASE, |
266 | CSR_MDBOUND, |
267 | CSR_MUCOUNTEREN, |
268 | CSR_MSCOUNTEREN, |
269 | CSR_MHCOUNTEREN, |
270 | }; |
271 | |
272 | int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) |
273 | { |
274 | RISCVCPU *cpu = RISCV_CPU(cs); |
275 | CPURISCVState *env = &cpu->env; |
276 | |
277 | if (n < 32) { |
278 | return gdb_get_regl(mem_buf, env->gpr[n]); |
279 | } else if (n == 32) { |
280 | return gdb_get_regl(mem_buf, env->pc); |
281 | } |
282 | return 0; |
283 | } |
284 | |
285 | int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) |
286 | { |
287 | RISCVCPU *cpu = RISCV_CPU(cs); |
288 | CPURISCVState *env = &cpu->env; |
289 | |
290 | if (n == 0) { |
291 | /* discard writes to x0 */ |
292 | return sizeof(target_ulong); |
293 | } else if (n < 32) { |
294 | env->gpr[n] = ldtul_p(mem_buf); |
295 | return sizeof(target_ulong); |
296 | } else if (n == 32) { |
297 | env->pc = ldtul_p(mem_buf); |
298 | return sizeof(target_ulong); |
299 | } |
300 | return 0; |
301 | } |
302 | |
303 | static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) |
304 | { |
305 | if (n < 32) { |
306 | return gdb_get_reg64(mem_buf, env->fpr[n]); |
307 | /* there is hole between ft11 and fflags in fpu.xml */ |
308 | } else if (n < 36 && n > 32) { |
309 | target_ulong val = 0; |
310 | int result; |
311 | /* |
312 | * CSR_FFLAGS is at index 8 in csr_register, and gdb says it is FP |
313 | * register 33, so we recalculate the map index. |
314 | * This also works for CSR_FRM and CSR_FCSR. |
315 | */ |
316 | result = riscv_csrrw_debug(env, n - 33 + 8, &val, 0, 0); |
317 | if (result == 0) { |
318 | return gdb_get_regl(mem_buf, val); |
319 | } |
320 | } |
321 | return 0; |
322 | } |
323 | |
324 | static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) |
325 | { |
326 | if (n < 32) { |
327 | env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */ |
328 | return sizeof(uint64_t); |
329 | /* there is hole between ft11 and fflags in fpu.xml */ |
330 | } else if (n < 36 && n > 32) { |
331 | target_ulong val = ldtul_p(mem_buf); |
332 | int result; |
333 | /* |
334 | * CSR_FFLAGS is at index 8 in csr_register, and gdb says it is FP |
335 | * register 33, so we recalculate the map index. |
336 | * This also works for CSR_FRM and CSR_FCSR. |
337 | */ |
338 | result = riscv_csrrw_debug(env, n - 33 + 8, NULL, val, -1); |
339 | if (result == 0) { |
340 | return sizeof(target_ulong); |
341 | } |
342 | } |
343 | return 0; |
344 | } |
345 | |
346 | static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n) |
347 | { |
348 | if (n < ARRAY_SIZE(csr_register_map)) { |
349 | target_ulong val = 0; |
350 | int result; |
351 | |
352 | result = riscv_csrrw_debug(env, csr_register_map[n], &val, 0, 0); |
353 | if (result == 0) { |
354 | return gdb_get_regl(mem_buf, val); |
355 | } |
356 | } |
357 | return 0; |
358 | } |
359 | |
360 | static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n) |
361 | { |
362 | if (n < ARRAY_SIZE(csr_register_map)) { |
363 | target_ulong val = ldtul_p(mem_buf); |
364 | int result; |
365 | |
366 | result = riscv_csrrw_debug(env, csr_register_map[n], NULL, val, -1); |
367 | if (result == 0) { |
368 | return sizeof(target_ulong); |
369 | } |
370 | } |
371 | return 0; |
372 | } |
373 | |
374 | void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) |
375 | { |
376 | RISCVCPU *cpu = RISCV_CPU(cs); |
377 | CPURISCVState *env = &cpu->env; |
378 | #if defined(TARGET_RISCV32) |
379 | if (env->misa & RVF) { |
380 | gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, |
381 | 36, "riscv-32bit-fpu.xml" , 0); |
382 | } |
383 | |
384 | gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, |
385 | 4096, "riscv-32bit-csr.xml" , 0); |
386 | #elif defined(TARGET_RISCV64) |
387 | if (env->misa & RVF) { |
388 | gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, |
389 | 36, "riscv-64bit-fpu.xml" , 0); |
390 | } |
391 | |
392 | gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, |
393 | 4096, "riscv-64bit-csr.xml" , 0); |
394 | #endif |
395 | } |
396 | |