Merge pull request #875 from zqb-all/support_multiple_DMs

target/riscv: support multiple DMs
This commit is contained in:
Tim Newsome 2023-07-27 08:44:34 -07:00 committed by GitHub
commit 1997e68dcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 396 additions and 166 deletions

View File

@ -10891,15 +10891,28 @@ Write the 32-bit value to authdata or authdata0 (index=0), or authdata1
@subsection RISC-V DMI Commands @subsection RISC-V DMI Commands
The following commands allow direct access to the Debug Module Interface, which The following commands allow for direct low-level access to the registers
can be used to interact with custom debug features. of the Debug Module (DM). They can be useful to access custom features in the DM.
@deffn {Command} {riscv dm_read} reg_address
Perform a 32-bit read from the register indicated by reg_address from the DM of the
current target.
@end deffn
@deffn {Command} {riscv dm_write} reg_address value
Write the 32-bit value to the register indicated by reg_address from the DM of the
current target.
@end deffn
The following commands allow for direct low-level access to the Debug Module
Interface (DMI). They can be useful to access any device that resides on the DMI.
@deffn {Command} {riscv dmi_read} address @deffn {Command} {riscv dmi_read} address
Perform a 32-bit DMI read at address, returning the value. Perform a 32-bit read from the given DMI address, returning the value.
@end deffn @end deffn
@deffn {Command} {riscv dmi_write} address value @deffn {Command} {riscv dmi_write} address value
Perform a 32-bit DMI write of value at address. Perform a 32-bit write to the given DMI address.
@end deffn @end deffn
@subsection RISC-V Trigger Commands @subsection RISC-V Trigger Commands

View File

@ -127,17 +127,17 @@ int riscv_batch_run(struct riscv_batch *batch)
return ERROR_OK; return ERROR_OK;
} }
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address, uint64_t data, void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, uint64_t data,
bool read_back) bool read_back)
{ {
assert(batch->used_scans < batch->allocated_scans); assert(batch->used_scans < batch->allocated_scans);
struct scan_field *field = batch->fields + batch->used_scans; struct scan_field *field = batch->fields + batch->used_scans;
field->num_bits = riscv_dmi_write_u64_bits(batch->target); field->num_bits = riscv_dmi_write_u64_bits(batch->target);
field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data); riscv_fill_dm_write_u64(batch->target, (char *)field->out_value, address, data);
if (read_back) { if (read_back) {
field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
} else { } else {
field->in_value = NULL; field->in_value = NULL;
} }
@ -145,15 +145,15 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address,
batch->used_scans++; batch->used_scans++;
} }
size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address) size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int address)
{ {
assert(batch->used_scans < batch->allocated_scans); assert(batch->used_scans < batch->allocated_scans);
struct scan_field *field = batch->fields + batch->used_scans; struct scan_field *field = batch->fields + batch->used_scans;
field->num_bits = riscv_dmi_write_u64_bits(batch->target); field->num_bits = riscv_dmi_write_u64_bits(batch->target);
field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dmi_read_u64(batch->target, (char *)field->out_value, address); riscv_fill_dm_read_u64(batch->target, (char *)field->out_value, address);
riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
batch->last_scan = RISCV_SCAN_TYPE_READ; batch->last_scan = RISCV_SCAN_TYPE_READ;
batch->used_scans++; batch->used_scans++;
@ -188,8 +188,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
field->num_bits = riscv_dmi_write_u64_bits(batch->target); field->num_bits = riscv_dmi_write_u64_bits(batch->target);
field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dmi_nop_u64(batch->target, (char *)field->out_value); riscv_fill_dm_nop_u64(batch->target, (char *)field->out_value);
riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
batch->last_scan = RISCV_SCAN_TYPE_NOP; batch->last_scan = RISCV_SCAN_TYPE_NOP;
batch->used_scans++; batch->used_scans++;
} }

View File

@ -58,14 +58,14 @@ bool riscv_batch_full(struct riscv_batch *batch);
/* Executes this scan batch. */ /* Executes this scan batch. */
int riscv_batch_run(struct riscv_batch *batch); int riscv_batch_run(struct riscv_batch *batch);
/* Adds a DMI write to this batch. */ /* Adds a DM register write to this batch. */
void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address, uint64_t data, void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, uint64_t data,
bool read_back); bool read_back);
/* DMI reads must be handled in two parts: the first one schedules a read and /* DM register reads must be handled in two parts: the first one schedules a read and
* provides a key, the second one actually obtains the result of the read - * provides a key, the second one actually obtains the result of the read -
* status (op) and the actual data. */ * status (op) and the actual data. */
size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address); size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int address);
unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key); unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key);
uint32_t riscv_batch_get_dmi_read_data(const struct riscv_batch *batch, size_t key); uint32_t riscv_batch_get_dmi_read_data(const struct riscv_batch *batch, size_t key);

File diff suppressed because it is too large Load Diff

View File

@ -3479,14 +3479,13 @@ COMMAND_HANDLER(riscv_dmi_read)
if (r->dmi_read(target, &value, address) != ERROR_OK) if (r->dmi_read(target, &value, address) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
command_print(CMD, "0x%" PRIx32, value); command_print(CMD, "0x%" PRIx32, value);
return ERROR_OK;
} else { } else {
LOG_TARGET_ERROR(target, "dmi_read is not implemented for this target."); LOG_TARGET_ERROR(target, "dmi_read is not implemented for this target.");
return ERROR_FAIL; return ERROR_FAIL;
} }
return ERROR_OK;
} }
COMMAND_HANDLER(riscv_dmi_write) COMMAND_HANDLER(riscv_dmi_write)
{ {
if (CMD_ARGC != 2) { if (CMD_ARGC != 2) {
@ -3524,6 +3523,76 @@ COMMAND_HANDLER(riscv_dmi_write)
return ERROR_FAIL; return ERROR_FAIL;
} }
COMMAND_HANDLER(riscv_dm_read)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
}
struct target *target = get_current_target(CMD_CTX);
if (!target) {
LOG_ERROR("target is NULL!");
return ERROR_FAIL;
}
RISCV_INFO(r);
if (!r) {
LOG_TARGET_ERROR(target, "riscv_info is NULL!");
return ERROR_FAIL;
}
if (r->dm_read) {
uint32_t address, value;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
if (r->dm_read(target, &value, address) != ERROR_OK)
return ERROR_FAIL;
command_print(CMD, "0x%" PRIx32, value);
} else {
LOG_TARGET_ERROR(target, "dm_read is not implemented for this target.");
return ERROR_FAIL;
}
return ERROR_OK;
}
COMMAND_HANDLER(riscv_dm_write)
{
if (CMD_ARGC != 2) {
LOG_ERROR("Command takes exactly 2 arguments");
return ERROR_COMMAND_SYNTAX_ERROR;
}
struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r);
uint32_t address, value;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
if (r->dm_write) {
/* Perform the DM write */
int retval = r->dm_write(target, address, value);
/* Invalidate our cached progbuf copy:
- if the user tinkered directly with a progbuf register
- if debug module was reset, in which case progbuf registers
may not retain their value.
*/
bool progbuf_touched = (address >= DM_PROGBUF0 && address <= DM_PROGBUF15);
bool dm_deactivated = (address == DM_DMCONTROL && (value & DM_DMCONTROL_DMACTIVE) == 0);
if (progbuf_touched || dm_deactivated) {
if (r->invalidate_cached_debug_buffer)
r->invalidate_cached_debug_buffer(target);
}
return retval;
}
LOG_TARGET_ERROR(target, "dm_write is not implemented for this target.");
return ERROR_FAIL;
}
COMMAND_HANDLER(riscv_reset_delays) COMMAND_HANDLER(riscv_reset_delays)
{ {
int wait = 0; int wait = 0;
@ -4285,6 +4354,20 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.usage = "address value", .usage = "address value",
.help = "Perform a 32-bit DMI write of value at address." .help = "Perform a 32-bit DMI write of value at address."
}, },
{
.name = "dm_read",
.handler = riscv_dm_read,
.mode = COMMAND_ANY,
.usage = "reg_address",
.help = "Perform a 32-bit read from DM register at reg_address, returning the value."
},
{
.name = "dm_write",
.handler = riscv_dm_write,
.mode = COMMAND_ANY,
.usage = "reg_address value",
.help = "Write a 32-bit value to the DM register at reg_address."
},
{ {
.name = "reset_delays", .name = "reset_delays",
.handler = riscv_reset_delays, .handler = riscv_reset_delays,
@ -4916,22 +4999,22 @@ int riscv_execute_debug_buffer(struct target *target)
return r->execute_debug_buffer(target); return r->execute_debug_buffer(target);
} }
void riscv_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d) void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d)
{ {
RISCV_INFO(r); RISCV_INFO(r);
r->fill_dmi_write_u64(target, buf, a, d); r->fill_dm_write_u64(target, buf, a, d);
} }
void riscv_fill_dmi_read_u64(struct target *target, char *buf, int a) void riscv_fill_dm_read_u64(struct target *target, char *buf, int a)
{ {
RISCV_INFO(r); RISCV_INFO(r);
r->fill_dmi_read_u64(target, buf, a); r->fill_dm_read_u64(target, buf, a);
} }
void riscv_fill_dmi_nop_u64(struct target *target, char *buf) void riscv_fill_dm_nop_u64(struct target *target, char *buf)
{ {
RISCV_INFO(r); RISCV_INFO(r);
r->fill_dmi_nop_u64(target, buf); r->fill_dm_nop_u64(target, buf);
} }
int riscv_dmi_write_u64_bits(struct target *target) int riscv_dmi_write_u64_bits(struct target *target)

View File

@ -19,6 +19,7 @@ struct riscv_program;
#define RISCV_MAX_HARTS ((int)BIT(20)) #define RISCV_MAX_HARTS ((int)BIT(20))
#define RISCV_MAX_TRIGGERS 32 #define RISCV_MAX_TRIGGERS 32
#define RISCV_MAX_HWBPS 16 #define RISCV_MAX_HWBPS 16
#define RISCV_MAX_DMS 100
#define DEFAULT_COMMAND_TIMEOUT_SEC 2 #define DEFAULT_COMMAND_TIMEOUT_SEC 2
#define DEFAULT_RESET_TIMEOUT_SEC 30 #define DEFAULT_RESET_TIMEOUT_SEC 30
@ -220,9 +221,9 @@ struct riscv_info {
int (*execute_debug_buffer)(struct target *target); int (*execute_debug_buffer)(struct target *target);
int (*invalidate_cached_debug_buffer)(struct target *target); int (*invalidate_cached_debug_buffer)(struct target *target);
int (*dmi_write_u64_bits)(struct target *target); int (*dmi_write_u64_bits)(struct target *target);
void (*fill_dmi_write_u64)(struct target *target, char *buf, int a, uint64_t d); void (*fill_dm_write_u64)(struct target *target, char *buf, int a, uint64_t d);
void (*fill_dmi_read_u64)(struct target *target, char *buf, int a); void (*fill_dm_read_u64)(struct target *target, char *buf, int a);
void (*fill_dmi_nop_u64)(struct target *target, char *buf); void (*fill_dm_nop_u64)(struct target *target, char *buf);
int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index); int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index);
int (*authdata_write)(struct target *target, uint32_t value, unsigned int index); int (*authdata_write)(struct target *target, uint32_t value, unsigned int index);
@ -230,6 +231,9 @@ struct riscv_info {
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address); int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value); int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
int (*dm_read)(struct target *target, uint32_t *value, uint32_t address);
int (*dm_write)(struct target *target, uint32_t address, uint32_t value);
int (*sample_memory)(struct target *target, int (*sample_memory)(struct target *target,
struct riscv_sample_buf *buf, struct riscv_sample_buf *buf,
riscv_sample_config_t *config, riscv_sample_config_t *config,
@ -412,9 +416,9 @@ riscv_insn_t riscv_read_debug_buffer(struct target *target, int index);
int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn); int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn);
int riscv_execute_debug_buffer(struct target *target); int riscv_execute_debug_buffer(struct target *target);
void riscv_fill_dmi_nop_u64(struct target *target, char *buf); void riscv_fill_dm_nop_u64(struct target *target, char *buf);
void riscv_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d); void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d);
void riscv_fill_dmi_read_u64(struct target *target, char *buf, int a); void riscv_fill_dm_read_u64(struct target *target, char *buf, int a);
int riscv_dmi_write_u64_bits(struct target *target); int riscv_dmi_write_u64_bits(struct target *target);
int riscv_enumerate_triggers(struct target *target); int riscv_enumerate_triggers(struct target *target);