gdbstub.c (6547B)
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 23int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 24{ 25 RISCVCPU *cpu = RISCV_CPU(cs); 26 CPURISCVState *env = &cpu->env; 27 28 if (n < 32) { 29 return gdb_get_regl(mem_buf, env->gpr[n]); 30 } else if (n == 32) { 31 return gdb_get_regl(mem_buf, env->pc); 32 } 33 return 0; 34} 35 36int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 37{ 38 RISCVCPU *cpu = RISCV_CPU(cs); 39 CPURISCVState *env = &cpu->env; 40 41 if (n == 0) { 42 /* discard writes to x0 */ 43 return sizeof(target_ulong); 44 } else if (n < 32) { 45 env->gpr[n] = ldtul_p(mem_buf); 46 return sizeof(target_ulong); 47 } else if (n == 32) { 48 env->pc = ldtul_p(mem_buf); 49 return sizeof(target_ulong); 50 } 51 return 0; 52} 53 54static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n) 55{ 56 if (n < 32) { 57 if (env->misa & RVD) { 58 return gdb_get_reg64(buf, env->fpr[n]); 59 } 60 if (env->misa & RVF) { 61 return gdb_get_reg32(buf, env->fpr[n]); 62 } 63 /* there is hole between ft11 and fflags in fpu.xml */ 64 } else if (n < 36 && n > 32) { 65 target_ulong val = 0; 66 int result; 67 /* 68 * CSR_FFLAGS is at index 1 in csr_register, and gdb says it is FP 69 * register 33, so we recalculate the map index. 70 * This also works for CSR_FRM and CSR_FCSR. 71 */ 72 result = riscv_csrrw_debug(env, n - 32, &val, 73 0, 0); 74 if (result == RISCV_EXCP_NONE) { 75 return gdb_get_regl(buf, val); 76 } 77 } 78 return 0; 79} 80 81static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) 82{ 83 if (n < 32) { 84 env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */ 85 return sizeof(uint64_t); 86 /* there is hole between ft11 and fflags in fpu.xml */ 87 } else if (n < 36 && n > 32) { 88 target_ulong val = ldtul_p(mem_buf); 89 int result; 90 /* 91 * CSR_FFLAGS is at index 1 in csr_register, and gdb says it is FP 92 * register 33, so we recalculate the map index. 93 * This also works for CSR_FRM and CSR_FCSR. 94 */ 95 result = riscv_csrrw_debug(env, n - 32, NULL, 96 val, -1); 97 if (result == RISCV_EXCP_NONE) { 98 return sizeof(target_ulong); 99 } 100 } 101 return 0; 102} 103 104static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n) 105{ 106 if (n < CSR_TABLE_SIZE) { 107 target_ulong val = 0; 108 int result; 109 110 result = riscv_csrrw_debug(env, n, &val, 0, 0); 111 if (result == RISCV_EXCP_NONE) { 112 return gdb_get_regl(buf, val); 113 } 114 } 115 return 0; 116} 117 118static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n) 119{ 120 if (n < CSR_TABLE_SIZE) { 121 target_ulong val = ldtul_p(mem_buf); 122 int result; 123 124 result = riscv_csrrw_debug(env, n, NULL, val, -1); 125 if (result == RISCV_EXCP_NONE) { 126 return sizeof(target_ulong); 127 } 128 } 129 return 0; 130} 131 132static int riscv_gdb_get_virtual(CPURISCVState *cs, GByteArray *buf, int n) 133{ 134 if (n == 0) { 135#ifdef CONFIG_USER_ONLY 136 return gdb_get_regl(buf, 0); 137#else 138 return gdb_get_regl(buf, cs->priv); 139#endif 140 } 141 return 0; 142} 143 144static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n) 145{ 146 if (n == 0) { 147#ifndef CONFIG_USER_ONLY 148 cs->priv = ldtul_p(mem_buf) & 0x3; 149 if (cs->priv == PRV_H) { 150 cs->priv = PRV_S; 151 } 152#endif 153 return sizeof(target_ulong); 154 } 155 return 0; 156} 157 158static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) 159{ 160 RISCVCPU *cpu = RISCV_CPU(cs); 161 CPURISCVState *env = &cpu->env; 162 GString *s = g_string_new(NULL); 163 riscv_csr_predicate_fn predicate; 164 int bitsize = riscv_cpu_is_32bit(env) ? 32 : 64; 165 int i; 166 167 g_string_printf(s, "<?xml version=\"1.0\"?>"); 168 g_string_append_printf(s, "<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">"); 169 g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">"); 170 171 for (i = 0; i < CSR_TABLE_SIZE; i++) { 172 predicate = csr_ops[i].predicate; 173 if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) { 174 if (csr_ops[i].name) { 175 g_string_append_printf(s, "<reg name=\"%s\"", csr_ops[i].name); 176 } else { 177 g_string_append_printf(s, "<reg name=\"csr%03x\"", i); 178 } 179 g_string_append_printf(s, " bitsize=\"%d\"", bitsize); 180 g_string_append_printf(s, " regnum=\"%d\"/>", base_reg + i); 181 } 182 } 183 184 g_string_append_printf(s, "</feature>"); 185 186 cpu->dyn_csr_xml = g_string_free(s, false); 187 return CSR_TABLE_SIZE; 188} 189 190void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) 191{ 192 RISCVCPU *cpu = RISCV_CPU(cs); 193 CPURISCVState *env = &cpu->env; 194 if (env->misa & RVD) { 195 gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, 196 36, "riscv-64bit-fpu.xml", 0); 197 } else if (env->misa & RVF) { 198 gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, 199 36, "riscv-32bit-fpu.xml", 0); 200 } 201#if defined(TARGET_RISCV32) 202 gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, 203 1, "riscv-32bit-virtual.xml", 0); 204#elif defined(TARGET_RISCV64) 205 gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, 206 1, "riscv-64bit-virtual.xml", 0); 207#endif 208 209 gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, 210 riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs), 211 "riscv-csr.xml", 0); 212}