Skip to content

Commit 421ca41

Browse files
committed
riscv_debug: Detect Semihosting breakpoints and connect with common support code
1 parent 2daf09d commit 421ca41

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

src/target/riscv_debug.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "gdb_reg.h"
3838
#include "riscv_debug.h"
3939
#include "buffer_utils.h"
40+
#include "semihosting.h"
4041

4142
#include <assert.h>
4243

@@ -864,6 +865,31 @@ bool riscv_csr_write(riscv_hart_s *const hart, const uint16_t reg, const void *c
864865
return true;
865866
}
866867

868+
static target_addr_t riscv_pc_read(riscv_hart_s *const hart)
869+
{
870+
target_addr_t data = 0;
871+
riscv_csr_read(hart, RV_DPC, &data);
872+
//riscv32_reg_read(target, 32, &data, sizeof(data));
873+
return data;
874+
}
875+
876+
static bool riscv_hostio_request(target_s *const target)
877+
{
878+
/* Read out syscall number from a0/x10 and first argument from a1/x11 */
879+
uint32_t syscall = 0U;
880+
target_reg_read(target, 10, &syscall, sizeof(syscall));
881+
uint32_t a1 = 0U;
882+
target_reg_read(target, 11, &a1, sizeof(a1));
883+
884+
/* Hand off to the main semihosting implementation */
885+
const int32_t result = semihosting_request(target, syscall, a1);
886+
887+
/* Write the result back to the target */
888+
target_reg_write(target, 10, &result, sizeof(result));
889+
/* Return if the request was in any way interrupted */
890+
return target->tc->interrupted;
891+
}
892+
867893
uint8_t riscv_mem_access_width(const riscv_hart_s *const hart, const target_addr_t address, const size_t length)
868894
{
869895
/* Grab the Hart's most maxmimally aligned possible write width */
@@ -1103,6 +1129,21 @@ static target_halt_reason_e riscv_halt_poll(target_s *const target, target_addr6
11031129
status &= RV_DCSR_CAUSE_MASK;
11041130
/* Dispatch on the cause code */
11051131
switch (status) {
1132+
case RV_HALT_CAUSE_EBREAK: {
1133+
/* If we've hit a programmed breakpoint, check for semihosting call. */
1134+
const target_addr_t program_counter = riscv_pc_read(hart);
1135+
uint32_t instructions[3] = {0};
1136+
target_mem32_read(target, &instructions, program_counter - 4U, 12);
1137+
/* A semihosting call is three consecutive uncompressed instructions: slli zero, zero 0x1f; ebreak, srai zero, zero, 7. */
1138+
if (instructions[0] == 0x01f01013 && instructions[1] == RV_EBREAK && instructions[2] == 0x40705013) {
1139+
if (riscv_hostio_request(target))
1140+
return TARGET_HALT_REQUEST;
1141+
1142+
riscv_halt_resume(target, false);
1143+
return TARGET_HALT_RUNNING;
1144+
}
1145+
return TARGET_HALT_BREAKPOINT;
1146+
}
11061147
case RV_HALT_CAUSE_TRIGGER:
11071148
/* XXX: Need to read out the triggers to find the one causing this, and grab the watch value */
11081149
return TARGET_HALT_BREAKPOINT;

0 commit comments

Comments
 (0)