]>
Commit | Line | Data |
---|---|---|
9438fe7d MC |
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" | |
9438fe7d MC |
20 | #include "exec/gdbstub.h" |
21 | #include "cpu.h" | |
22 | ||
5371f5cd JW |
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 | ||
9438fe7d MC |
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); | |
9438fe7d MC |
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); | |
5371f5cd JW |
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 */ | |
9438fe7d | 328 | return sizeof(uint64_t); |
5371f5cd JW |
329 | /* there is hole between ft11 and fflags in fpu.xml */ |
330 | } else if (n < 36 && n > 32) { | |
c7b95171 | 331 | target_ulong val = ldtul_p(mem_buf); |
5371f5cd JW |
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) { | |
c7b95171 MC |
340 | return sizeof(target_ulong); |
341 | } | |
9438fe7d MC |
342 | } |
343 | return 0; | |
344 | } | |
5371f5cd JW |
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 | } |