aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Matyas <50193733+JanMatCodasip@users.noreply.github.com>2023-02-15 18:53:03 +0100
committerGitHub <noreply@github.com>2023-02-15 09:53:03 -0800
commit872ebb14ca160eff364bf61844c3a6098e9f8ecc (patch)
tree9ea3c6872c2c14c50e78c752068f932f1ca84059
parent9cafc75678b96d77797f1ca635192eee4522389a (diff)
downloadriscv-openocd-872ebb14ca160eff364bf61844c3a6098e9f8ecc.zip
riscv-openocd-872ebb14ca160eff364bf61844c3a6098e9f8ecc.tar.gz
riscv-openocd-872ebb14ca160eff364bf61844c3a6098e9f8ecc.tar.bz2
Add command "exec_progbuf" (#795)
* Add command "exec_progbuf" Command "exec_progbuf" allows to execute a user-specified sequence of instructions using the program buffer. Change-Id: If3b9614129d0b6fcbc33fade29d3d60b35e52f98 Signed-off-by: Jan Matyas <jan.matyas@codasip.com> * Updated the doc: - Minor reword and reorder of the sentences. - Added information about C-instructions in progbuf. - Fixed a typo (per the review). - Added examples. Change-Id: I88c9a3ff3c6b60614be7eafd3a6f21be722a77b7 Signed-off-by: Jan Matyas <jan.matyas@codasip.com> * Cosmetic changes Change-Id: I7135c9f435f640e189c7d7922a2702814dfd595f Signed-off-by: Jan Matyas <jan.matyas@codasip.com> --------- Signed-off-by: Jan Matyas <jan.matyas@codasip.com> Co-authored-by: Jan Matyas <jan.matyas@codasip.com>
-rw-r--r--doc/openocd.texi33
-rw-r--r--src/target/riscv/program.c17
-rw-r--r--src/target/riscv/riscv-013.c2
-rw-r--r--src/target/riscv/riscv.c55
4 files changed, 98 insertions, 9 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index ab9dcaf..76e697c 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -10753,6 +10753,39 @@ For details on this trigger type, see the RISC-V Debug Specification.
Clear the type 4 trigger that was set using @command{riscv itrigger set}.
@end deffn
+@subsection RISC-V Program Buffer Commands
+
+Program Buffer is an optional feature of RISC-V targets - it is a mechanism that debuggers
+can use to execute sequences of arbitrary instructions (small programs) on the target.
+For details on the Program Buffer, please refer to the RISC-V Debug Specification.
+
+@deffn {Command} {riscv exec_progbuf} inst1 [inst2 [... inst16]]
+Execute the given sequence of instructions on the target using the Program Buffer.
+The command can only be used on halted targets.
+
+The instructions @var{inst1} .. @var{inst16} shall be specified in their binary form
+(as 32-bit integers). In case a pair of compressed (16-bit) instructions is used,
+the first instruction should be placed to the lower 16-bits of the 32-bit value.
+The terminating @var{ebreak} instruction needs not be specified - it is added
+automatically if needed.
+@end deffn
+
+Examples:
+
+@example
+# Execute 32-bit instructions "fence rw,rw" (0x0330000f)
+# and "fence.i" (0x0000100f) using the Program Buffer,
+# in this order:
+
+riscv exec_progbuf 0x0330000f 0x0000100f
+
+# Execute 16-bit instructions "c.addi s0,s0,1" (0x0405)
+# and "c.add s1,s1,s0" (0x94a2) using the Program Buffer,
+# in this order:
+
+riscv exec_progbuf 0x94a20405
+@end example
+
@section ARC Architecture
@cindex ARC
diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c
index f14923a..16baa4b 100644
--- a/src/target/riscv/program.c
+++ b/src/target/riscv/program.c
@@ -32,7 +32,8 @@ int riscv_program_init(struct riscv_program *p, struct target *target)
int riscv_program_write(struct riscv_program *program)
{
for (unsigned i = 0; i < program->instruction_count; ++i) {
- LOG_DEBUG("debug_buffer[%02x] = DASM(0x%08x)", i, program->debug_buffer[i]);
+ LOG_TARGET_DEBUG(program->target, "debug_buffer[%02x] = DASM(0x%08x)",
+ i, program->debug_buffer[i]);
if (riscv_write_debug_buffer(program->target, i,
program->debug_buffer[i]) != ERROR_OK)
return ERROR_FAIL;
@@ -48,7 +49,7 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1];
for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) {
if (p->writes_xreg[i]) {
- LOG_DEBUG("Saving register %d as used by program", (int)i);
+ LOG_TARGET_DEBUG(t, "Saving register %d as used by program", (int)i);
int result = riscv_get_register(t, &saved_registers[i], i);
if (result != ERROR_OK)
return result;
@@ -56,9 +57,9 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
}
if (riscv_program_ebreak(p) != ERROR_OK) {
- LOG_ERROR("Unable to write ebreak");
+ LOG_TARGET_ERROR(t, "Unable to insert ebreak into program buffer");
for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
- LOG_ERROR("ram[%02x]: DASM(0x%08" PRIx32 ") [0x%08" PRIx32 "]",
+ LOG_TARGET_ERROR(t, "ram[%02x]: DASM(0x%08" PRIx32 ") [0x%08" PRIx32 "]",
(int)i, p->debug_buffer[i], p->debug_buffer[i]);
return ERROR_FAIL;
}
@@ -67,7 +68,7 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
return ERROR_FAIL;
if (riscv_execute_debug_buffer(t) != ERROR_OK) {
- LOG_DEBUG("Unable to execute program %p", p);
+ LOG_TARGET_DEBUG(t, "Unable to execute program %p", p);
return ERROR_FAIL;
}
@@ -175,9 +176,9 @@ int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
{
if (p->instruction_count >= riscv_debug_buffer_size(p->target)) {
- LOG_ERROR("Unable to insert instruction:");
- LOG_ERROR(" instruction_count=%d", (int)p->instruction_count);
- LOG_ERROR(" buffer size =%d", (int)riscv_debug_buffer_size(p->target));
+ LOG_TARGET_ERROR(p->target, "Unable to insert program into progbuf, "
+ "capacity would be exceeded (progbufsize=%d).",
+ (int)riscv_debug_buffer_size(p->target));
return ERROR_FAIL;
}
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index f12d185..28789bd 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1700,7 +1700,7 @@ static int examine(struct target *target)
}
/* Without knowing anything else we can at least mess with the
- * program buffer. */
+ * program buffer. */
r->debug_buffer_size = info->progbufsize;
int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64);
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 058a810..3c797bc 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -20,6 +20,7 @@
#include "helper/base64.h"
#include "helper/time_support.h"
#include "riscv.h"
+#include "program.h"
#include "gdb_regs.h"
#include "rtos/rtos.h"
#include "debug_defines.h"
@@ -3589,6 +3590,52 @@ COMMAND_HANDLER(handle_info)
return 0;
}
+COMMAND_HANDLER(riscv_exec_progbuf)
+{
+ if (CMD_ARGC < 1 || CMD_ARGC > 16) {
+ LOG_ERROR("Command 'exec_progbuf' takes 1 to 16 arguments.");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ struct target *target = get_current_target(CMD_CTX);
+
+ RISCV_INFO(r);
+ if (r->dtm_version != 1) {
+ LOG_TARGET_ERROR(target, "exec_progbuf: Program buffer is "
+ "only supported on v0.13 or v1.0 targets.");
+ return ERROR_FAIL;
+ }
+
+ if (target->state != TARGET_HALTED) {
+ LOG_TARGET_ERROR(target, "exec_progbuf: Can't execute "
+ "program buffer, target not halted.");
+ return ERROR_FAIL;
+ }
+
+ if (riscv_debug_buffer_size(target) == 0) {
+ LOG_TARGET_ERROR(target, "exec_progbuf: Program buffer not implemented "
+ "in the target.");
+ return ERROR_FAIL;
+ }
+
+ struct riscv_program prog;
+ riscv_program_init(&prog, target);
+
+ for (unsigned int i = 0; i < CMD_ARGC; i++) {
+ riscv_insn_t instr;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i], instr);
+ if (riscv_program_insert(&prog, instr) != ERROR_OK)
+ return ERROR_FAIL;
+ }
+
+ if (riscv_program_exec(&prog, target) == ERROR_OK)
+ LOG_TARGET_DEBUG(target, "exec_progbuf: Program buffer execution successful.");
+ else
+ LOG_TARGET_ERROR(target, "exec_progbuf: Program buffer execution failed.");
+
+ return ERROR_OK;
+}
+
static const struct command_registration riscv_exec_command_handlers[] = {
{
.name = "dump_sample_buf",
@@ -3804,6 +3851,14 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.usage = "set [vs] [vu] [nmi] [m] [s] [u] <mie_bits>|clear",
.help = "Set or clear a single interrupt trigger."
},
+ {
+ .name = "exec_progbuf",
+ .handler = riscv_exec_progbuf,
+ .mode = COMMAND_EXEC,
+ .usage = "instr1 [instr2 [... instr16]]",
+ .help = "Execute a sequence of 32-bit instructions using the program buffer. "
+ "The final ebreak instruction is added automatically, if needed."
+ },
COMMAND_REGISTRATION_DONE
};