target/riscv: support multiple DMs

Support assign DMI address of the debug module by pass
-dbgbase to the target create command

Change-Id: I774c3746567f6e6d77c43a62dea5e9e67bb25770
Signed-off-by: Mark Zhuang <mark.zhuang@spacemit.com>
This commit is contained in:
Mark Zhuang 2023-05-06 20:24:05 +08:00
parent 895185caff
commit 80a8aa9e19
1 changed files with 54 additions and 18 deletions

View File

@ -123,7 +123,8 @@ typedef enum slot {
typedef struct {
struct list_head list;
int abs_chain_position;
/* The base address to access this DM on DMI */
uint32_t base;
/* The number of harts connected to this DM. */
int hart_count;
/* Indicates we already reset this DM, so don't need to do it again. */
@ -243,7 +244,8 @@ static dm013_info_t *get_dm(struct target *target)
dm013_info_t *entry;
dm013_info_t *dm = NULL;
list_for_each_entry(entry, &dm_list, list) {
if (entry->abs_chain_position == abs_chain_position) {
if (entry->abs_chain_position == abs_chain_position
&& entry->base == target->dbgbase) {
dm = entry;
break;
}
@ -255,6 +257,11 @@ static dm013_info_t *get_dm(struct target *target)
if (!dm)
return NULL;
dm->abs_chain_position = abs_chain_position;
/* Safety check for dbgbase */
assert(target->dbgbase_set || target->dbgbase == 0);
dm->base = target->dbgbase;
dm->current_hartid = 0;
dm->hart_count = -1;
INIT_LIST_HEAD(&dm->target_list);
@ -378,12 +385,15 @@ static void decode_dm(char *text, unsigned int address, unsigned int data)
}
}
static void decode_dmi(char *text, unsigned int address, unsigned int data)
static void decode_dmi(struct target *target, char *text, unsigned int address, unsigned int data)
{
decode_dm(text, address, data);
dm013_info_t *dm = get_dm(target);
if (!dm)
return;
decode_dm(text, address - dm->base, data);
}
static void dump_field(int idle, const struct scan_field *field)
static void dump_field(struct target *target, int idle, const struct scan_field *field)
{
static const char * const op_string[] = {"-", "r", "w", "?"};
static const char * const status_string[] = {"+", "?", "F", "b"};
@ -409,8 +419,8 @@ static void dump_field(int idle, const struct scan_field *field)
char out_text[500];
char in_text[500];
decode_dmi(out_text, out_address, out_data);
decode_dmi(in_text, in_address, in_data);
decode_dmi(target, out_text, out_address, out_data);
decode_dmi(target, in_text, in_address, in_data);
if (in_text[0] || out_text[0]) {
log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", "%s -> %s",
out_text, in_text);
@ -549,7 +559,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
if (address_in)
*address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits);
dump_field(idle_count, &field);
dump_field(target, idle_count, &field);
return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
}
@ -698,7 +708,10 @@ static int dm_op_timeout(struct target *target, uint32_t *data_in,
bool *dmi_busy_encountered, int op, uint32_t address,
uint32_t data_out, int timeout_sec, bool exec, bool ensure_success)
{
dmi_op_timeout(target, data_in, dmi_busy_encountered, op, address,
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
return dmi_op_timeout(target, data_in, dmi_busy_encountered, op, address + dm->base,
data_out, timeout_sec, exec, ensure_success);
}
@ -706,29 +719,44 @@ static int dm_op(struct target *target, uint32_t *data_in,
bool *dmi_busy_encountered, int op, uint32_t address,
uint32_t data_out, bool exec, bool ensure_success)
{
return dmi_op(target, data_in, dmi_busy_encountered, op, address,
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
return dmi_op(target, data_in, dmi_busy_encountered, op, address + dm->base,
data_out, exec, ensure_success);
}
static int dm_read(struct target *target, uint32_t *value, uint32_t address)
{
return dmi_read(target, value, address);
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
return dmi_read(target, value, address + dm->base);
}
static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address)
{
return dmi_read_exec(target, value, address);
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
return dmi_read_exec(target, value, address + dm->base);
}
static int dm_write(struct target *target, uint32_t address, uint32_t value)
{
return dmi_write(target, address, value);
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
return dmi_write(target, address + dm->base, value);
}
static int dm_write_exec(struct target *target, uint32_t address,
uint32_t value, bool ensure_success)
{
return dmi_write_exec(target, address, value, ensure_success);
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
return dmi_write_exec(target, address + dm->base, value, ensure_success);
}
static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
@ -1739,6 +1767,8 @@ static int examine(struct target *target)
{
/* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
LOG_TARGET_DEBUG(target, "dbgbase=0x%x", target->dbgbase);
uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
LOG_TARGET_DEBUG(target, "dtmcontrol=0x%x", dtmcontrol);
LOG_TARGET_DEBUG(target, " dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET));
@ -1757,7 +1787,7 @@ static int examine(struct target *target)
}
riscv013_info_t *info = get_info(target);
/* TODO: This won't be true if there are multiple DMs. */
info->index = target->coreid;
info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
@ -1882,7 +1912,7 @@ static int examine(struct target *target)
LOG_TARGET_DEBUG(target, "Detected %d harts.", dm->hart_count);
}
if (dm->hart_count == 0) {
if (dm->hart_count <= 0) {
LOG_TARGET_ERROR(target, "No harts found!");
return ERROR_FAIL;
}
@ -4909,12 +4939,18 @@ static int riscv013_dmi_write_u64_bits(struct target *target)
void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d)
{
riscv013_fill_dmi_write_u64(target, buf, a, d);
dm013_info_t *dm = get_dm(target);
if (!dm)
return;
riscv013_fill_dmi_write_u64(target, buf, a + dm->base, d);
}
void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a)
{
riscv013_fill_dmi_read_u64(target, buf, a);
dm013_info_t *dm = get_dm(target);
if (!dm)
return;
riscv013_fill_dmi_read_u64(target, buf, a + dm->base);
}
void riscv013_fill_dm_nop_u64(struct target *target, char *buf)