2 * RISC-V GDB Server Stub
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
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.
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
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/>.
19 #include "qemu/osdep.h"
20 #include "exec/gdbstub.h"
21 #include "gdbstub/helpers.h"
31 static const struct TypeSize vec_lanes
[] = {
33 { "uint128", "quads", 128, 'q' },
35 { "uint64", "longs", 64, 'l' },
37 { "uint32", "words", 32, 'w' },
39 { "uint16", "shorts", 16, 's' },
41 * TODO: currently there is no reliable way of telling
42 * if the remote gdb actually understands ieee_half so
43 * we don't expose it in the target description for now.
44 * { "ieee_half", 16, 'h', 'f' },
47 { "uint8", "bytes", 8, 'b' },
50 int riscv_cpu_gdb_read_register(CPUState
*cs
, GByteArray
*mem_buf
, int n
)
52 RISCVCPU
*cpu
= RISCV_CPU(cs
);
53 CPURISCVState
*env
= &cpu
->env
;
64 switch (env
->misa_mxl_max
) {
66 return gdb_get_reg32(mem_buf
, tmp
);
69 return gdb_get_reg64(mem_buf
, tmp
);
71 g_assert_not_reached();
76 int riscv_cpu_gdb_write_register(CPUState
*cs
, uint8_t *mem_buf
, int n
)
78 RISCVCPU
*cpu
= RISCV_CPU(cs
);
79 CPURISCVState
*env
= &cpu
->env
;
83 switch (env
->misa_mxl_max
) {
85 tmp
= (int32_t)ldl_p(mem_buf
);
90 if (env
->xl
< MXL_RV64
) {
91 tmp
= (int32_t)ldq_p(mem_buf
);
98 g_assert_not_reached();
100 if (n
> 0 && n
< 32) {
102 } else if (n
== 32) {
109 static int riscv_gdb_get_fpu(CPURISCVState
*env
, GByteArray
*buf
, int n
)
112 if (env
->misa_ext
& RVD
) {
113 return gdb_get_reg64(buf
, env
->fpr
[n
]);
115 if (env
->misa_ext
& RVF
) {
116 return gdb_get_reg32(buf
, env
->fpr
[n
]);
122 static int riscv_gdb_set_fpu(CPURISCVState
*env
, uint8_t *mem_buf
, int n
)
125 env
->fpr
[n
] = ldq_p(mem_buf
); /* always 64-bit */
126 return sizeof(uint64_t);
131 static int riscv_gdb_get_vector(CPURISCVState
*env
, GByteArray
*buf
, int n
)
133 uint16_t vlenb
= riscv_cpu_cfg(env
)->vlen
>> 3;
137 for (i
= 0; i
< vlenb
; i
+= 8) {
138 cnt
+= gdb_get_reg64(buf
,
139 env
->vreg
[(n
* vlenb
+ i
) / 8]);
147 static int riscv_gdb_set_vector(CPURISCVState
*env
, uint8_t *mem_buf
, int n
)
149 uint16_t vlenb
= riscv_cpu_cfg(env
)->vlen
>> 3;
152 for (i
= 0; i
< vlenb
; i
+= 8) {
153 env
->vreg
[(n
* vlenb
+ i
) / 8] = ldq_p(mem_buf
+ i
);
161 static int riscv_gdb_get_csr(CPURISCVState
*env
, GByteArray
*buf
, int n
)
163 if (n
< CSR_TABLE_SIZE
) {
164 target_ulong val
= 0;
167 result
= riscv_csrrw_debug(env
, n
, &val
, 0, 0);
168 if (result
== RISCV_EXCP_NONE
) {
169 return gdb_get_regl(buf
, val
);
175 static int riscv_gdb_set_csr(CPURISCVState
*env
, uint8_t *mem_buf
, int n
)
177 if (n
< CSR_TABLE_SIZE
) {
178 target_ulong val
= ldtul_p(mem_buf
);
181 result
= riscv_csrrw_debug(env
, n
, NULL
, val
, -1);
182 if (result
== RISCV_EXCP_NONE
) {
183 return sizeof(target_ulong
);
189 static int riscv_gdb_get_virtual(CPURISCVState
*cs
, GByteArray
*buf
, int n
)
192 #ifdef CONFIG_USER_ONLY
193 return gdb_get_regl(buf
, 0);
195 return gdb_get_regl(buf
, cs
->priv
);
201 static int riscv_gdb_set_virtual(CPURISCVState
*cs
, uint8_t *mem_buf
, int n
)
204 #ifndef CONFIG_USER_ONLY
205 cs
->priv
= ldtul_p(mem_buf
) & 0x3;
206 if (cs
->priv
== PRV_RESERVED
) {
210 return sizeof(target_ulong
);
215 static int riscv_gen_dynamic_csr_xml(CPUState
*cs
, int base_reg
)
217 RISCVCPU
*cpu
= RISCV_CPU(cs
);
218 CPURISCVState
*env
= &cpu
->env
;
219 GString
*s
= g_string_new(NULL
);
220 riscv_csr_predicate_fn predicate
;
221 int bitsize
= 16 << env
->misa_mxl_max
;
224 #if !defined(CONFIG_USER_ONLY)
225 env
->debugger
= true;
228 /* Until gdb knows about 128-bit registers */
233 g_string_printf(s
, "<?xml version=\"1.0\"?>");
234 g_string_append_printf(s
, "<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">");
235 g_string_append_printf(s
, "<feature name=\"org.gnu.gdb.riscv.csr\">");
237 for (i
= 0; i
< CSR_TABLE_SIZE
; i
++) {
238 if (env
->priv_ver
< csr_ops
[i
].min_priv_ver
) {
241 predicate
= csr_ops
[i
].predicate
;
242 if (predicate
&& (predicate(env
, i
) == RISCV_EXCP_NONE
)) {
243 if (csr_ops
[i
].name
) {
244 g_string_append_printf(s
, "<reg name=\"%s\"", csr_ops
[i
].name
);
246 g_string_append_printf(s
, "<reg name=\"csr%03x\"", i
);
248 g_string_append_printf(s
, " bitsize=\"%d\"", bitsize
);
249 g_string_append_printf(s
, " regnum=\"%d\"/>", base_reg
+ i
);
253 g_string_append_printf(s
, "</feature>");
255 cpu
->dyn_csr_xml
= g_string_free(s
, false);
257 #if !defined(CONFIG_USER_ONLY)
258 env
->debugger
= false;
261 return CSR_TABLE_SIZE
;
264 static int ricsv_gen_dynamic_vector_xml(CPUState
*cs
, int base_reg
)
266 RISCVCPU
*cpu
= RISCV_CPU(cs
);
267 GString
*s
= g_string_new(NULL
);
268 g_autoptr(GString
) ts
= g_string_new("");
269 int reg_width
= cpu
->cfg
.vlen
;
273 g_string_printf(s
, "<?xml version=\"1.0\"?>");
274 g_string_append_printf(s
, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
275 g_string_append_printf(s
, "<feature name=\"org.gnu.gdb.riscv.vector\">");
277 /* First define types and totals in a whole VL */
278 for (i
= 0; i
< ARRAY_SIZE(vec_lanes
); i
++) {
279 int count
= reg_width
/ vec_lanes
[i
].size
;
280 g_string_printf(ts
, "%s", vec_lanes
[i
].id
);
281 g_string_append_printf(s
,
282 "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
283 ts
->str
, vec_lanes
[i
].gdb_type
, count
);
287 g_string_append_printf(s
, "<union id=\"riscv_vector\">");
288 for (i
= 0; i
< ARRAY_SIZE(vec_lanes
); i
++) {
289 g_string_append_printf(s
, "<field name=\"%c\" type=\"%s\"/>",
293 g_string_append(s
, "</union>");
295 /* Define vector registers */
296 for (i
= 0; i
< 32; i
++) {
297 g_string_append_printf(s
,
298 "<reg name=\"v%d\" bitsize=\"%d\""
299 " regnum=\"%d\" group=\"vector\""
300 " type=\"riscv_vector\"/>",
301 i
, reg_width
, base_reg
++);
305 g_string_append_printf(s
, "</feature>");
307 cpu
->dyn_vreg_xml
= g_string_free(s
, false);
311 void riscv_cpu_register_gdb_regs_for_features(CPUState
*cs
)
313 RISCVCPU
*cpu
= RISCV_CPU(cs
);
314 CPURISCVState
*env
= &cpu
->env
;
315 if (env
->misa_ext
& RVD
) {
316 gdb_register_coprocessor(cs
, riscv_gdb_get_fpu
, riscv_gdb_set_fpu
,
317 32, "riscv-64bit-fpu.xml", 0);
318 } else if (env
->misa_ext
& RVF
) {
319 gdb_register_coprocessor(cs
, riscv_gdb_get_fpu
, riscv_gdb_set_fpu
,
320 32, "riscv-32bit-fpu.xml", 0);
322 if (env
->misa_ext
& RVV
) {
323 int base_reg
= cs
->gdb_num_regs
;
324 gdb_register_coprocessor(cs
, riscv_gdb_get_vector
,
325 riscv_gdb_set_vector
,
326 ricsv_gen_dynamic_vector_xml(cs
, base_reg
),
327 "riscv-vector.xml", 0);
329 switch (env
->misa_mxl_max
) {
331 gdb_register_coprocessor(cs
, riscv_gdb_get_virtual
,
332 riscv_gdb_set_virtual
,
333 1, "riscv-32bit-virtual.xml", 0);
337 gdb_register_coprocessor(cs
, riscv_gdb_get_virtual
,
338 riscv_gdb_set_virtual
,
339 1, "riscv-64bit-virtual.xml", 0);
342 g_assert_not_reached();
345 if (cpu
->cfg
.ext_zicsr
) {
346 int base_reg
= cs
->gdb_num_regs
;
347 gdb_register_coprocessor(cs
, riscv_gdb_get_csr
, riscv_gdb_set_csr
,
348 riscv_gen_dynamic_csr_xml(cs
, base_reg
),