Skip to content

Commit 94cd98a

Browse files
meandragonmux
authored andcommitted
riscv: add single register access, add csr access with an offset, expose some CSRs register in the xml description
1 parent fe5a528 commit 94cd98a

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

src/target/riscv32.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ typedef struct riscv32_regs {
6767
#define RV32_MATCH_BEFORE 0x00000000U
6868
#define RV32_MATCH_AFTER 0x00040000U
6969

70+
static ssize_t riscv32_reg_read(target_s *target, uint32_t c, void *data, size_t max);
71+
static ssize_t riscv32_reg_write(target_s *target, uint32_t c, const void *data, size_t max);
7072
static void riscv32_regs_read(target_s *target, void *data);
7173
static void riscv32_regs_write(target_s *target, const void *data);
7274
static void riscv32_mem_read(target_s *target, void *dest, target_addr_t src, size_t len);
@@ -83,6 +85,8 @@ bool riscv32_probe(target_s *const target)
8385
target->regs_size = sizeof(riscv32_regs_s);
8486
target->regs_read = riscv32_regs_read;
8587
target->regs_write = riscv32_regs_write;
88+
target->reg_write = riscv32_reg_write;
89+
target->reg_read = riscv32_reg_read;
8690
target->mem_read = riscv32_mem_read;
8791
target->mem_write = riscv32_mem_write;
8892

@@ -133,6 +137,41 @@ static void riscv32_regs_write(target_s *const target, const void *const data)
133137
riscv_csr_write(hart, RV_DPC, &regs->pc);
134138
}
135139

140+
static inline ssize_t riscv32_bool_to_4(const bool ret)
141+
{
142+
return ret ? 4 : -1;
143+
}
144+
145+
static ssize_t riscv32_reg_read(target_s *target, const uint32_t reg, void *data, const size_t max)
146+
{
147+
if (max != 4)
148+
return -1;
149+
/* Grab the hart structure */
150+
riscv_hart_s *const hart = riscv_hart_struct(target);
151+
if (reg < 32)
152+
return riscv32_bool_to_4(riscv_csr_read(hart, RV_GPR_BASE + reg, data));
153+
if (reg == 32)
154+
return riscv32_bool_to_4(riscv_csr_read(hart, RV_DPC, data));
155+
if (reg >= RV_CSR_GDB_OFFSET)
156+
return riscv32_bool_to_4(riscv_csr_read(hart, reg - RV_CSR_GDB_OFFSET, data));
157+
return -1;
158+
}
159+
160+
static ssize_t riscv32_reg_write(target_s *const target, const uint32_t reg, const void *data, const size_t max)
161+
{
162+
if (max != 4)
163+
return -1;
164+
/* Grab the hart structure */
165+
riscv_hart_s *const hart = riscv_hart_struct(target);
166+
if (reg < 32)
167+
return riscv32_bool_to_4(riscv_csr_write(hart, RV_GPR_BASE + reg, data));
168+
if (reg == 32)
169+
return riscv32_bool_to_4(riscv_csr_write(hart, RV_DPC, data));
170+
if (reg >= RV_CSR_GDB_OFFSET)
171+
return riscv32_bool_to_4(riscv_csr_write(hart, reg - RV_CSR_GDB_OFFSET, data));
172+
return -1;
173+
}
174+
136175
/* Takes in data from abstract command arg0 and, based on the access width, unpacks it to dest */
137176
void riscv32_unpack_data(void *const dest, const uint32_t data, const uint8_t access_width)
138177
{

src/target/riscv_debug.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,24 @@ static const char *const riscv_gpr_names[RV_GPRS_COUNT] = {
137137
"s8", "s9", "s10", "s11",
138138
"t3", "t4", "t5", "t6",
139139
};
140+
141+
typedef struct riscv_csr_descriptor {
142+
const char *name;
143+
const uint32_t csr_number; // fits in 16 bits actually (?)
144+
} riscv_csr_descriptor_s;
145+
146+
static const riscv_csr_descriptor_s riscv_csrs[]={
147+
{"mstatus",RV_CSR_STATUS},
148+
{"misa",RV_CSR_MISA},
149+
{"mie", RV_CSR_MIE},
150+
{"mtvec", RV_CSR_MTVEC},
151+
{"tscratch",RV_CSR_MSCRATCH},
152+
{"mepc", RV_CSR_MEPC},
153+
{"mcause",RV_CSR_MCAUSE},
154+
{"mtval", RV_CSR_MTVAL},
155+
{"mip", RV_CSR_MIP},
156+
};
157+
140158
// clang-format on
141159

142160
/* General-purpose register types */
@@ -946,6 +964,17 @@ static size_t riscv_build_target_description(
946964

947965
/* XXX: TODO - implement generation of the FPU feature and registers */
948966

967+
/* Add main CSR registers*/
968+
if (max_length != 0)
969+
print_size = max_length - (size_t)offset;
970+
offset += snprintf(buffer + offset, print_size, "</feature><feature name=\"org.gnu.gdb.riscv.csr\">");
971+
for (size_t i = 0; i < ARRAY_LENGTH(riscv_csrs); i++) {
972+
if (max_length != 0)
973+
print_size = max_length - (size_t)offset;
974+
offset += snprintf(buffer + offset, print_size, " <reg name=\"%s\" bitsize=\"%u\" regnum=\"%" PRIu32 "\" %s/>",
975+
riscv_csrs[i].name, address_width, riscv_csrs[i].csr_number + RV_CSR_GDB_OFFSET,
976+
gdb_reg_save_restore_strings[GDB_SAVE_RESTORE_NO]);
977+
}
949978
/* Add the closing tags required */
950979
if (max_length != 0)
951980
print_size = max_length - (size_t)offset;

src/target/riscv_debug.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,20 @@ typedef struct riscv_hart {
178178
#define RV_TRIGGER_MODE_MASK 0xffff0000U
179179
#define RV_TRIGGER_SUPPORT_BREAKWATCH 0x00000004U
180180

181+
// The CSR id when reported by GDB is shifted by RV_CSR_GDB_OFFSET
182+
// so they cannot collide with GPR registers, so you have to substract
183+
// RV_CSR_GDB_OFFSET from the value received from gdb
184+
#define RV_CSR_GDB_OFFSET 128
185+
#define RV_CSR_STATUS 0x300
186+
#define RV_CSR_MISA 0x301
187+
#define RV_CSR_MIE 0x304
188+
#define RV_CSR_MTVEC 0x305
189+
#define RV_CSR_MSCRATCH 0x340
190+
#define RV_CSR_MEPC 0x341
191+
#define RV_CSR_MCAUSE 0x342
192+
#define RV_CSR_MTVAL 0x343
193+
#define RV_CSR_MIP 0x344
194+
181195
#define RV_TOPT_INHIBIT_NRST 0x00000001U
182196

183197
void riscv_jtag_dtm_handler(uint8_t dev_index);

0 commit comments

Comments
 (0)