This is an automated email from Gerrit. "Name of user not set <liam.fletc...@microchip.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8872
-- gerrit commit 025ecc353018af2215d4e0821094b481e24b06c8 Author: Liam Fletcher <liam.fletc...@microchip.com> Date: Thu Apr 10 14:01:30 2025 +0100 target/riscv: support multiple DMs Introduces the handling of more than one Debug Module(DM) per Debug Module Interface(DMI) for RISC-V. Creates a DM layer to allow access to the registers of the DM. Creates a -dbgbase argument to specify the first DM address in a DM chain. Checks the nextdm register of the current DM which contains the address of the next DM in a chain. A nextdm address of 0 indicates the end of a DM chain. See RISC-V Debug Specification v1.0 chapter 3.1: [https://github.com/riscv/riscv-debug-spec/releases/download/1.0/ riscv-debug-specification.pdf] Ported from 3 commits in riscv-openocd: [https://github.com/riscv-collab/riscv-openocd/pull/875/] target/riscv: add dm layer original commit: [895185caffac591e923bfeaa42672fa604eb642f] prepare for support multiple DMs target/riscv: support multiple DMs original commit: [80a8aa9e195757f082919108f71511b76bd7ca92] Support assign DMI address of the debug module by pass -dbgbase to the target create command target/riscv: support check dbgbase exist original commit: [a9f28dafd7a67bf6f0a734f087fc9de283d001f1] Change-Id: I91df626a9c68aa28344728ceceb55f7b69c719dc Signed-off-by: Liam Fletcher <liam.fletc...@microchip.com> diff --git a/doc/openocd.texi b/doc/openocd.texi index 32a2895ecf..8213608bbc 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11593,15 +11593,28 @@ Write the 32-bit value to authdata. @subsection RISC-V DMI Commands -The following commands allow direct access to the Debug Module Interface, which -can be used to interact with custom debug features. +The following commands allow for direct low-level access to the registers +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 -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 @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 @section ARC Architecture diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index e3f8ff3d4b..b339d17e8e 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -127,28 +127,28 @@ int riscv_batch_run(struct riscv_batch *batch) 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) { assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; 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->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); - riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data); - riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); + field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); + riscv_fill_dm_write_u64(batch->target, (char *)field->out_value, address, data); + riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value); batch->last_scan = RISCV_SCAN_TYPE_WRITE; batch->used_scans++; } -size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int address) +size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int address) { assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; 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->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_dmi_nop_u64(batch->target, (char *)field->in_value); + field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); + riscv_fill_dm_read_u64(batch->target, (char *)field->out_value, address); + riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value); batch->last_scan = RISCV_SCAN_TYPE_READ; batch->used_scans++; @@ -183,8 +183,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch) 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->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_dmi_nop_u64(batch->target, (char *)field->in_value); + riscv_fill_dm_nop_u64(batch->target, (char *)field->out_value); + riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value); batch->last_scan = RISCV_SCAN_TYPE_NOP; batch->used_scans++; } diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index 537fa59233..8b7bf74a50 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -58,13 +58,13 @@ bool riscv_batch_full(struct riscv_batch *batch); /* Executes this scan batch. */ int riscv_batch_run(struct riscv_batch *batch); -/* Adds a DMI write to this batch. */ -void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int address, uint64_t data); +/* Adds a DM register write to this batch. */ +void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, uint64_t data); -/* 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 - * status (op) and the actual data. */ -size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int address); +size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int address); uint32_t riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key); uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index bb450ce623..52030b746b 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -53,9 +53,12 @@ static int riscv013_write_debug_buffer(struct target *target, unsigned int index static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned int index); static int riscv013_execute_debug_buffer(struct target *target); static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, uint64_t d); +static void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d); static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a); +static void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a); static int riscv013_dmi_write_u64_bits(struct target *target); static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf); +static void riscv013_fill_dm_nop_u64(struct target *target, char *buf); static int register_read(struct target *target, uint64_t *value, uint32_t number); static int register_read_direct(struct target *target, uint64_t *value, uint32_t number); static int register_write_direct(struct target *target, unsigned int number, @@ -132,7 +135,8 @@ typedef enum { typedef struct { struct list_head list; unsigned 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. */ @@ -240,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; } @@ -252,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 = -1; dm->hart_count = -1; INIT_LIST_HEAD(&dm->target_list); @@ -289,7 +299,7 @@ static uint32_t set_hartsel(uint32_t initial, uint32_t index) return initial; } -static void decode_dmi(char *text, unsigned int address, unsigned int data) +static void decode_dm(char *text, unsigned int address, unsigned int data) { static const struct { unsigned int address; @@ -368,7 +378,15 @@ static void decode_dmi(char *text, unsigned int address, unsigned int data) } } -static void dump_field(int idle, const struct scan_field *field) +static void decode_dmi(struct target *target, char *text, unsigned int address, unsigned int data) +{ + dm013_info_t *dm = get_dm(target); + if (!dm) + return; + decode_dm(text, address - dm->base, data); +} + +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"}; @@ -394,8 +412,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); @@ -533,7 +551,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); } @@ -543,7 +561,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, * @param dmi_busy_encountered * If non-NULL, will be updated to reflect whether DMI busy was * encountered while executing this operation or not. - * @param dmi_op The operation to perform (read/write/nop). + * @param op The operation to perform (read/write/nop). * @param address The address argument to that operation. * @param data_out The data to send to the target. * @param timeout_sec @@ -554,7 +572,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, * DMI operation succeeded. */ static int dmi_op_timeout(struct target *target, uint32_t *data_in, - bool *dmi_busy_encountered, int dmi_op, uint32_t address, + bool *dmi_busy_encountered, int op, uint32_t address, uint32_t data_out, int timeout_sec, bool exec, bool ensure_success) { select_dmi(target); @@ -566,7 +584,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, *dmi_busy_encountered = false; const char *op_name; - switch (dmi_op) { + switch (op) { case DMI_OP_NOP: op_name = "nop"; break; @@ -577,7 +595,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, op_name = "write"; break; default: - LOG_ERROR("Invalid DMI operation: %d", dmi_op); + LOG_ERROR("Invalid DMI operation: %d", op); return ERROR_FAIL; } @@ -587,7 +605,7 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, /* This first loop performs the request. Note that if for some reason this * stays busy, it is actually due to the previous access. */ while (1) { - status = dmi_scan(target, NULL, NULL, dmi_op, address, data_out, + status = dmi_scan(target, NULL, NULL, op, address, data_out, exec); if (status == DMI_STATUS_BUSY) { increase_dmi_busy_delay(target); @@ -642,10 +660,10 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, } static int dmi_op(struct target *target, uint32_t *data_in, - bool *dmi_busy_encountered, int dmi_op, uint32_t address, + bool *dmi_busy_encountered, int op, uint32_t address, uint32_t data_out, bool exec, bool ensure_success) { - int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, dmi_op, + int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, op, address, data_out, riscv_command_timeout_sec, exec, ensure_success); if (result == ERROR_TIMEOUT_REACHED) { LOG_ERROR("DMI operation didn't complete in %d seconds. The target is " @@ -678,10 +696,92 @@ static int dmi_write_exec(struct target *target, uint32_t address, return dmi_op(target, NULL, NULL, DMI_OP_WRITE, address, value, true, ensure_success); } +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) +{ + 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); +} + +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) +{ + 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) +{ + 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) +{ + 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) +{ + 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) +{ + dm013_info_t *dm = get_dm(target); + if (!dm) + return ERROR_FAIL; + return dmi_write_exec(target, address + dm->base, value, ensure_success); +} + +static bool check_dbgbase_exists(struct target *target) +{ + uint32_t next_dm = 0; + unsigned int count = 1; + + LOG_TARGET_DEBUG(target, "Searching for DM with DMI base address (dbgbase) = 0x%x", target->dbgbase); + while (1) { + uint32_t current_dm = next_dm; + if (current_dm == target->dbgbase) + return true; + if (dmi_read(target, &next_dm, DM_NEXTDM + current_dm) != ERROR_OK) + break; + LOG_TARGET_DEBUG(target, "dm @ 0x%x --> nextdm=0x%x", current_dm, next_dm); + /* Check if it's last one in the chain. */ + if (next_dm == 0) { + LOG_TARGET_ERROR(target, "Reached the end of DM chain (detected %u DMs in total).", count); + break; + } + /* Safety: Avoid looping forever in case of buggy nextdm values in the hardware. */ + if (count++ > RISCV_MAX_DMS) { + LOG_TARGET_ERROR(target, "Supporting no more than %d DMs on a DMI bus. Aborting", RISCV_MAX_DMS); + break; + } + } + return false; +} + static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus, bool authenticated, unsigned int timeout_sec) { - int result = dmi_op_timeout(target, dmstatus, NULL, DMI_OP_READ, + int result = dm_op_timeout(target, dmstatus, NULL, DMI_OP_READ, DM_DMSTATUS, 0, timeout_sec, false, true); if (result != ERROR_OK) return result; @@ -736,7 +836,7 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs) RISCV013_INFO(info); time_t start = time(NULL); while (1) { - if (dmi_read(target, abstractcs, DM_ABSTRACTCS) != ERROR_OK) + if (dm_read(target, abstractcs, DM_ABSTRACTCS) != ERROR_OK) return ERROR_FAIL; if (get_field(*abstractcs, DM_ABSTRACTCS_BUSY) == 0) @@ -789,7 +889,7 @@ static int execute_abstract_command(struct target *target, uint32_t command) } } - if (dmi_write_exec(target, DM_COMMAND, command, false) != ERROR_OK) + if (dm_write_exec(target, DM_COMMAND, command, false) != ERROR_OK) return ERROR_FAIL; uint32_t abstractcs = 0; @@ -799,7 +899,7 @@ static int execute_abstract_command(struct target *target, uint32_t command) if (info->cmderr != 0 || result != ERROR_OK) { LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, abstractcs); /* Clear the error. */ - dmi_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); + dm_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); return ERROR_FAIL; } @@ -817,11 +917,11 @@ static riscv_reg_t read_abstract_arg(struct target *target, unsigned int index, LOG_ERROR("Unsupported size: %d bits", size_bits); return ~0; case 64: - dmi_read(target, &v, DM_DATA0 + offset + 1); + dm_read(target, &v, DM_DATA0 + offset + 1); value |= ((uint64_t) v) << 32; /* falls through */ case 32: - dmi_read(target, &v, DM_DATA0 + offset); + dm_read(target, &v, DM_DATA0 + offset); value |= v; } return value; @@ -836,10 +936,10 @@ static int write_abstract_arg(struct target *target, unsigned int index, LOG_ERROR("Unsupported size: %d bits", size_bits); return ERROR_FAIL; case 64: - dmi_write(target, DM_DATA0 + offset + 1, value >> 32); + dm_write(target, DM_DATA0 + offset + 1, value >> 32); /* falls through */ case 32: - dmi_write(target, DM_DATA0 + offset, value); + dm_write(target, DM_DATA0 + offset, value); } return ERROR_OK; } @@ -1045,7 +1145,7 @@ static int examine_progbuf(struct target *target) } uint32_t written; - if (dmi_read(target, &written, DM_PROGBUF0) != ERROR_OK) + if (dm_read(target, &written, DM_PROGBUF0) != ERROR_OK) return ERROR_FAIL; if (written == (uint32_t) info->progbuf_address) { LOG_INFO("progbuf is writable at 0x%" PRIx64, @@ -1203,18 +1303,18 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch, uint32_t v; switch (scratch->memory_space) { case SPACE_DM_DATA: - if (dmi_read(target, &v, DM_DATA0 + scratch->debug_address) != ERROR_OK) + if (dm_read(target, &v, DM_DATA0 + scratch->debug_address) != ERROR_OK) return ERROR_FAIL; *value = v; - if (dmi_read(target, &v, DM_DATA1 + scratch->debug_address) != ERROR_OK) + if (dm_read(target, &v, DM_DATA1 + scratch->debug_address) != ERROR_OK) return ERROR_FAIL; *value |= ((uint64_t) v) << 32; break; case SPACE_DMI_PROGBUF: - if (dmi_read(target, &v, DM_PROGBUF0 + scratch->debug_address) != ERROR_OK) + if (dm_read(target, &v, DM_PROGBUF0 + scratch->debug_address) != ERROR_OK) return ERROR_FAIL; *value = v; - if (dmi_read(target, &v, DM_PROGBUF1 + scratch->debug_address) != ERROR_OK) + if (dm_read(target, &v, DM_PROGBUF1 + scratch->debug_address) != ERROR_OK) return ERROR_FAIL; *value |= ((uint64_t) v) << 32; break; @@ -1242,12 +1342,12 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch, { switch (scratch->memory_space) { case SPACE_DM_DATA: - dmi_write(target, DM_DATA0 + scratch->debug_address, value); - dmi_write(target, DM_DATA1 + scratch->debug_address, value >> 32); + dm_write(target, DM_DATA0 + scratch->debug_address, value); + dm_write(target, DM_DATA1 + scratch->debug_address, value >> 32); break; case SPACE_DMI_PROGBUF: - dmi_write(target, DM_PROGBUF0 + scratch->debug_address, value); - dmi_write(target, DM_PROGBUF1 + scratch->debug_address, value >> 32); + dm_write(target, DM_PROGBUF0 + scratch->debug_address, value); + dm_write(target, DM_PROGBUF1 + scratch->debug_address, value >> 32); break; case SPACE_DMI_RAM: { @@ -1562,6 +1662,8 @@ static int examine(struct target *target) { /* Don't need to select dbus, since the first thing we do is read dtmcontrol. */ + LOG_DEBUG("dbgbase=0x%x", target->dbgbase); + uint32_t dtmcontrol = dtmcontrol_scan(target, 0); LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol); LOG_DEBUG(" dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET)); @@ -1580,26 +1682,31 @@ 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); + if (!check_dbgbase_exists(target)) { + LOG_TARGET_ERROR(target, "Could not find debug module with DMI base address (dbgbase) = 0x%x", target->dbgbase); + return ERROR_FAIL; + } + /* Reset the Debug Module. */ dm013_info_t *dm = get_dm(target); if (!dm) return ERROR_FAIL; if (!dm->was_reset) { - dmi_write(target, DM_DMCONTROL, 0); - dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE); + dm_write(target, DM_DMCONTROL, 0); + dm_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE); dm->was_reset = true; } - dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_HARTSELLO | + dm_write(target, DM_DMCONTROL, DM_DMCONTROL_HARTSELLO | DM_DMCONTROL_HARTSELHI | DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_HASEL); uint32_t dmcontrol; - if (dmi_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK) + if (dm_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK) return ERROR_FAIL; if (!get_field(dmcontrol, DM_DMCONTROL_DMACTIVE)) { @@ -1632,7 +1739,7 @@ static int examine(struct target *target) LOG_DEBUG("hartsellen=%d", info->hartsellen); uint32_t hartinfo; - if (dmi_read(target, &hartinfo, DM_HARTINFO) != ERROR_OK) + if (dm_read(target, &hartinfo, DM_HARTINFO) != ERROR_OK) return ERROR_FAIL; info->datasize = get_field(hartinfo, DM_HARTINFO_DATASIZE); @@ -1650,12 +1757,12 @@ static int examine(struct target *target) return ERROR_OK; } - if (dmi_read(target, &info->sbcs, DM_SBCS) != ERROR_OK) + if (dm_read(target, &info->sbcs, DM_SBCS) != ERROR_OK) return ERROR_FAIL; /* Check that abstract data registers are accessible. */ uint32_t abstractcs; - if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) + if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) return ERROR_FAIL; info->datacount = get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); info->progbufsize = get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); @@ -1694,7 +1801,7 @@ static int examine(struct target *target) dm->hart_count = i + 1; if (get_field(s, DM_DMSTATUS_ANYHAVERESET)) - dmi_write(target, DM_DMCONTROL, + dm_write(target, DM_DMCONTROL, set_hartsel(DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_ACKHAVERESET, i)); } @@ -1788,7 +1895,7 @@ static int riscv013_authdata_read(struct target *target, uint32_t *value, unsign if (wait_for_authbusy(target, NULL) != ERROR_OK) return ERROR_FAIL; - return dmi_read(target, value, DM_AUTHDATA); + return dm_read(target, value, DM_AUTHDATA); } static int riscv013_authdata_write(struct target *target, uint32_t value, unsigned int index) @@ -1802,7 +1909,7 @@ static int riscv013_authdata_write(struct target *target, uint32_t value, unsign if (wait_for_authbusy(target, &before) != ERROR_OK) return ERROR_FAIL; - dmi_write(target, DM_AUTHDATA, value); + dm_write(target, DM_AUTHDATA, value); if (wait_for_authbusy(target, &after) != ERROR_OK) return ERROR_FAIL; @@ -2079,12 +2186,12 @@ static int sb_write_address(struct target *target, target_addr_t address, unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); /* There currently is no support for >64-bit addresses in OpenOCD. */ if (sbasize > 96) - dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS3, 0, false, false); + dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS3, 0, false, false); if (sbasize > 64) - dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS2, 0, false, false); + dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS2, 0, false, false); if (sbasize > 32) - dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS1, address >> 32, false, false); - return dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS0, address, + dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS1, address >> 32, false, false); + return dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS0, address, false, ensure_success); } @@ -2183,7 +2290,7 @@ static int sample_memory_bus_v1(struct target *target, sbcs_write |= DM_SBCS_SBREADONDATA; sbcs_write |= sb_sbaccess(config->bucket[i].size_bytes); if (!sbcs_valid || sbcs_write != sbcs) { - riscv_batch_add_dmi_write(batch, DM_SBCS, sbcs_write); + riscv_batch_add_dm_write(batch, DM_SBCS, sbcs_write); sbcs = sbcs_write; sbcs_valid = true; } @@ -2192,18 +2299,18 @@ static int sample_memory_bus_v1(struct target *target, (!sbaddress1_valid || sbaddress1 != config->bucket[i].address >> 32)) { sbaddress1 = config->bucket[i].address >> 32; - riscv_batch_add_dmi_write(batch, DM_SBADDRESS1, sbaddress1); + riscv_batch_add_dm_write(batch, DM_SBADDRESS1, sbaddress1); sbaddress1_valid = true; } if (!sbaddress0_valid || sbaddress0 != (config->bucket[i].address & 0xffffffff)) { sbaddress0 = config->bucket[i].address; - riscv_batch_add_dmi_write(batch, DM_SBADDRESS0, sbaddress0); + riscv_batch_add_dm_write(batch, DM_SBADDRESS0, sbaddress0); sbaddress0_valid = true; } if (config->bucket[i].size_bytes > 4) - riscv_batch_add_dmi_read(batch, DM_SBDATA1); - riscv_batch_add_dmi_read(batch, DM_SBDATA0); + riscv_batch_add_dm_read(batch, DM_SBDATA1); + riscv_batch_add_dm_read(batch, DM_SBDATA0); result_bytes += 1 + config->bucket[i].size_bytes; } } @@ -2214,7 +2321,7 @@ static int sample_memory_bus_v1(struct target *target, break; } - size_t sbcs_key = riscv_batch_add_dmi_read(batch, DM_SBCS); + size_t sbcs_key = riscv_batch_add_dm_read(batch, DM_SBCS); int result = batch_run(target, batch); if (result != ERROR_OK) @@ -2225,13 +2332,13 @@ static int sample_memory_bus_v1(struct target *target, /* Discard this batch (too much hassle to try to recover partial * data) and try again with a larger delay. */ info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1; - dmi_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR); + dm_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR); riscv_batch_free(batch); continue; } if (get_field(sbcs_read, DM_SBCS_SBERROR)) { /* The memory we're sampling was unreadable, somehow. Give up. */ - dmi_write(target, DM_SBCS, DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR); + dm_write(target, DM_SBCS, DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR); riscv_batch_free(batch); return ERROR_FAIL; } @@ -2293,14 +2400,16 @@ static int init_target(struct command_context *cmd_ctx, generic_info->read_debug_buffer = &riscv013_read_debug_buffer; generic_info->write_debug_buffer = &riscv013_write_debug_buffer; generic_info->execute_debug_buffer = &riscv013_execute_debug_buffer; - generic_info->fill_dmi_write_u64 = &riscv013_fill_dmi_write_u64; - generic_info->fill_dmi_read_u64 = &riscv013_fill_dmi_read_u64; - generic_info->fill_dmi_nop_u64 = &riscv013_fill_dmi_nop_u64; + generic_info->fill_dm_write_u64 = &riscv013_fill_dm_write_u64; + generic_info->fill_dm_read_u64 = &riscv013_fill_dm_read_u64; + generic_info->fill_dm_nop_u64 = &riscv013_fill_dm_nop_u64; generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits; generic_info->authdata_read = &riscv013_authdata_read; generic_info->authdata_write = &riscv013_authdata_write; generic_info->dmi_read = &dmi_read; generic_info->dmi_write = &dmi_write; + generic_info->dm_read = &dm_read; + generic_info->dm_write = &dm_write; generic_info->read_memory = read_memory; generic_info->hart_count = &riscv013_hart_count; generic_info->data_bits = &riscv013_data_bits; @@ -2356,11 +2465,11 @@ static int assert_reset(struct target *target) uint32_t control = set_hartsel(control_base, target->coreid); control = set_field(control, DM_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); - dmi_write(target, DM_DMCONTROL, control); + dm_write(target, DM_DMCONTROL, control); /* Assert ndmreset */ control = set_field(control, DM_DMCONTROL_NDMRESET, 1); - dmi_write(target, DM_DMCONTROL, control); + dm_write(target, DM_DMCONTROL, control); } else { /* Reset just this hart. */ @@ -2368,7 +2477,7 @@ static int assert_reset(struct target *target) control = set_field(control, DM_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); control = set_field(control, DM_DMCONTROL_NDMRESET, 1); - dmi_write(target, DM_DMCONTROL, control); + dm_write(target, DM_DMCONTROL, control); } target->state = TARGET_RESET; @@ -2395,7 +2504,7 @@ static int deassert_reset(struct target *target) uint32_t control = 0, control_haltreq; control = set_field(control, DM_DMCONTROL_DMACTIVE, 1); control_haltreq = set_field(control, DM_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); - dmi_write(target, DM_DMCONTROL, + dm_write(target, DM_DMCONTROL, set_hartsel(control_haltreq, r->current_hartid)); uint32_t dmstatus; @@ -2407,7 +2516,7 @@ static int deassert_reset(struct target *target) if (target->rtos) { if (index != target->coreid) continue; - dmi_write(target, DM_DMCONTROL, + dm_write(target, DM_DMCONTROL, set_hartsel(control_haltreq, index)); } else { index = r->current_hartid; @@ -2445,7 +2554,7 @@ static int deassert_reset(struct target *target) if (get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET)) { /* Ack reset and clear DM_DMCONTROL_HALTREQ if previously set */ - dmi_write(target, DM_DMCONTROL, + dm_write(target, DM_DMCONTROL, set_hartsel(control, index) | DM_DMCONTROL_ACKHAVERESET); } @@ -2511,7 +2620,7 @@ static int read_memory_bus_word(struct target *target, target_addr_t address, static int sbdata[4] = { DM_SBDATA0, DM_SBDATA1, DM_SBDATA2, DM_SBDATA3 }; assert(size <= 16); for (int i = (size - 1) / 4; i >= 0; i--) { - result = dmi_op(target, &value, NULL, DMI_OP_READ, sbdata[i], 0, false, true); + result = dm_op(target, &value, NULL, DMI_OP_READ, sbdata[i], 0, false, true); if (result != ERROR_OK) return result; buf_set_u32(buffer + i * 4, 0, 8 * MIN(size, 4), value); @@ -2527,11 +2636,11 @@ static target_addr_t sb_read_address(struct target *target) target_addr_t address = 0; uint32_t v; if (sbasize > 32) { - dmi_read(target, &v, DM_SBADDRESS1); + dm_read(target, &v, DM_SBADDRESS1); address |= v; address <<= 32; } - dmi_read(target, &v, DM_SBADDRESS0); + dm_read(target, &v, DM_SBADDRESS0); address |= v; return address; } @@ -2540,7 +2649,7 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs) { time_t start = time(NULL); while (1) { - if (dmi_read(target, sbcs, DM_SBCS) != ERROR_OK) + if (dm_read(target, sbcs, DM_SBCS) != ERROR_OK) return ERROR_FAIL; if (!get_field(*sbcs, DM_SBCS_SBBUSY)) return ERROR_OK; @@ -2608,17 +2717,17 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, /* ww favorise one off reading if there is an issue */ if (count == 1) { for (uint32_t i = 0; i < count; i++) { - if (dmi_read(target, &access, DM_SBCS) != ERROR_OK) + if (dm_read(target, &access, DM_SBCS) != ERROR_OK) return ERROR_FAIL; - dmi_write(target, DM_SBADDRESS0, cur_addr); + dm_write(target, DM_SBADDRESS0, cur_addr); /* size/2 matching the bit access of the spec 0.13 */ access = set_field(access, DM_SBCS_SBACCESS, size/2); access = set_field(access, DM_SBCS_SBSINGLEREAD, 1); LOG_DEBUG("\r\nread_memory: sab: access: 0x%08x", access); - dmi_write(target, DM_SBCS, access); + dm_write(target, DM_SBCS, access); /* 3) read */ uint32_t value; - if (dmi_read(target, &value, DM_SBDATA0) != ERROR_OK) + if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("\r\nread_memory: sab: value: 0x%08x", value); buf_set_u32(t_buffer, 0, 8 * size, value); @@ -2630,10 +2739,10 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, /* has to be the same size if we want to read a block */ LOG_DEBUG("reading block until final address 0x%" PRIx64, fin_addr); - if (dmi_read(target, &access, DM_SBCS) != ERROR_OK) + if (dm_read(target, &access, DM_SBCS) != ERROR_OK) return ERROR_FAIL; /* set current address */ - dmi_write(target, DM_SBADDRESS0, cur_addr); + dm_write(target, DM_SBADDRESS0, cur_addr); /* 2) write sbaccess=2, sbsingleread,sbautoread,sbautoincrement * size/2 matching the bit access of the spec 0.13 */ access = set_field(access, DM_SBCS_SBACCESS, size/2); @@ -2641,14 +2750,14 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, access = set_field(access, DM_SBCS_SBSINGLEREAD, 1); access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 1); LOG_DEBUG("\r\naccess: 0x%08x", access); - dmi_write(target, DM_SBCS, access); + dm_write(target, DM_SBCS, access); while (cur_addr < fin_addr) { LOG_DEBUG("\r\nsab:autoincrement: \r\n size: %d\tcount:%d\taddress: 0x%08" PRIx64, size, count, cur_addr); /* read */ uint32_t value; - if (dmi_read(target, &value, DM_SBDATA0) != ERROR_OK) + if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK) return ERROR_FAIL; buf_set_u32(t_buffer, 0, 8 * size, value); cur_addr += size; @@ -2656,15 +2765,15 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, /* if we are reaching last address, we must clear autoread */ if (cur_addr == fin_addr && count != 1) { - dmi_write(target, DM_SBCS, 0); - if (dmi_read(target, &value, DM_SBDATA0) != ERROR_OK) + dm_write(target, DM_SBCS, 0); + if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK) return ERROR_FAIL; buf_set_u32(t_buffer, 0, 8 * size, value); } } uint32_t sbcs; - if (dmi_read(target, &sbcs, DM_SBCS) != ERROR_OK) + if (dm_read(target, &sbcs, DM_SBCS) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; @@ -2692,7 +2801,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, sbcs_write = set_field(sbcs_write, DM_SBCS_SBAUTOINCREMENT, 1); if (count > 1) sbcs_write = set_field(sbcs_write, DM_SBCS_SBREADONDATA, count > 1); - if (dmi_write(target, DM_SBCS, sbcs_write) != ERROR_OK) + if (dm_write(target, DM_SBCS, sbcs_write) != ERROR_OK) return ERROR_FAIL; /* This address write will trigger the first read. */ @@ -2768,7 +2877,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, return ERROR_FAIL; sbcs_write = set_field(sbcs_write, DM_SBCS_SBREADONDATA, 0); - if (dmi_write(target, DM_SBCS, sbcs_write) != ERROR_OK) + if (dm_write(target, DM_SBCS, sbcs_write) != ERROR_OK) return ERROR_FAIL; } @@ -2785,7 +2894,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, if (get_field(sbcs_read, DM_SBCS_SBBUSYERROR)) { /* We read while the target was busy. Slow down and try again. */ - if (dmi_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR) != ERROR_OK) + if (dm_write(target, DM_SBCS, sbcs_read | DM_SBCS_SBBUSYERROR) != ERROR_OK) return ERROR_FAIL; next_address = sb_read_address(target); info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1; @@ -2798,7 +2907,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, } else { /* Some error indicating the bus access failed, but not because of * something we did wrong. */ - if (dmi_write(target, DM_SBCS, DM_SBCS_SBERROR) != ERROR_OK) + if (dm_write(target, DM_SBCS, DM_SBCS_SBERROR) != ERROR_OK) return ERROR_FAIL; return ERROR_FAIL; } @@ -3133,13 +3242,13 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres return ERROR_OK; } - if (dmi_write(target, DM_ABSTRACTAUTO, + if (dm_write(target, DM_ABSTRACTAUTO, 1 << DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET) != ERROR_OK) goto error; /* Read garbage from dmi_data0, which triggers another execution of the * program. Now dmi_data0 contains the first good result, and s1 the next * memory value. */ - if (dmi_read_exec(target, NULL, DM_DATA0) != ERROR_OK) + if (dm_read_exec(target, NULL, DM_DATA0) != ERROR_OK) goto error; /* read_addr is the next address that the hart will read from, which is the @@ -3164,8 +3273,8 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres unsigned int reads = 0; for (unsigned int j = index; j < count; j++) { if (size > 4) - riscv_batch_add_dmi_read(batch, DM_DATA1); - riscv_batch_add_dmi_read(batch, DM_DATA0); + riscv_batch_add_dm_read(batch, DM_DATA1); + riscv_batch_add_dm_read(batch, DM_DATA0); reads++; if (riscv_batch_full(batch)) @@ -3178,10 +3287,10 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres * and update our copy of cmderr. If we see that DMI is busy here, * dmi_busy_delay will be incremented. */ uint32_t abstractcs; - if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) + if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) return ERROR_FAIL; while (get_field(abstractcs, DM_ABSTRACTCS_BUSY)) - if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) + if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) return ERROR_FAIL; info->cmderr = get_field(abstractcs, DM_ABSTRACTCS_CMDERR); @@ -3198,13 +3307,13 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres increase_ac_busy_delay(target); riscv013_clear_abstract_error(target); - dmi_write(target, DM_ABSTRACTAUTO, 0); + dm_write(target, DM_ABSTRACTAUTO, 0); uint32_t dmi_data0, dmi_data1 = 0; /* This is definitely a good version of the value that we * attempted to read when we discovered that the target was * busy. */ - if (dmi_read(target, &dmi_data0, DM_DATA0) != ERROR_OK) { + if (dm_read(target, &dmi_data0, DM_DATA0) != ERROR_OK) { riscv_batch_free(batch); goto error; } @@ -3239,7 +3348,7 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres dmi_write_exec(target, DM_COMMAND, command, true); next_index++; - dmi_write(target, DM_ABSTRACTAUTO, + dm_write(target, DM_ABSTRACTAUTO, 1 << DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); ignore_last = 1; @@ -3305,7 +3414,7 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres riscv_batch_free(batch); } - dmi_write(target, DM_ABSTRACTAUTO, 0); + dm_write(target, DM_ABSTRACTAUTO, 0); if (count > 1) { /* Read the penultimate word. */ @@ -3330,7 +3439,7 @@ static int read_memory_progbuf_inner(struct target *target, target_addr_t addres return ERROR_OK; error: - dmi_write(target, DM_ABSTRACTAUTO, 0); + dm_write(target, DM_ABSTRACTAUTO, 0); return result; } @@ -3598,7 +3707,7 @@ static int write_memory_bus_v0(struct target *target, target_addr_t address, /*1) write sbaddress: for singlewrite and autoincrement, we need to write the address once*/ LOG_DEBUG("System Bus Access: size: %d\tcount:%d\tstart address: 0x%08" TARGET_PRIxADDR, size, count, address); - dmi_write(target, DM_SBADDRESS0, address); + dm_write(target, DM_SBADDRESS0, address); int64_t value = 0; int64_t access = 0; riscv_addr_t offset = 0; @@ -3611,10 +3720,10 @@ static int write_memory_bus_v0(struct target *target, target_addr_t address, access = 0; access = set_field(access, DM_SBCS_SBACCESS, size/2); - dmi_write(target, DM_SBCS, access); + dm_write(target, DM_SBCS, access); LOG_DEBUG("\r\naccess: 0x%08" PRIx64, access); LOG_DEBUG("\r\nwrite_memory:SAB: ONE OFF: value 0x%08" PRIx64, value); - dmi_write(target, DM_SBDATA0, value); + dm_write(target, DM_SBDATA0, value); return ERROR_OK; } @@ -3624,7 +3733,7 @@ static int write_memory_bus_v0(struct target *target, target_addr_t address, access = set_field(access, DM_SBCS_SBACCESS, size/2); access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 1); LOG_DEBUG("\r\naccess: 0x%08" PRIx64, access); - dmi_write(target, DM_SBCS, access); + dm_write(target, DM_SBCS, access); /*2)set the value according to the size required and write*/ for (riscv_addr_t i = 0; i < count; ++i) { @@ -3636,11 +3745,11 @@ static int write_memory_bus_v0(struct target *target, target_addr_t address, value = buf_get_u64(t_buffer, 0, 8 * size); LOG_DEBUG("SAB:autoincrement: expected address: 0x%08x value: 0x%08x" PRIx64, (uint32_t)t_addr, (uint32_t)value); - dmi_write(target, DM_SBDATA0, value); + dm_write(target, DM_SBDATA0, value); } /*reset the autoincrement when finished (something weird is happening if this is not done at the end*/ access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 0); - dmi_write(target, DM_SBCS, access); + dm_write(target, DM_SBCS, access); return ERROR_OK; } @@ -3651,7 +3760,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, RISCV013_INFO(info); uint32_t sbcs = sb_sbaccess(size); sbcs = set_field(sbcs, DM_SBCS_SBAUTOINCREMENT, 1); - dmi_write(target, DM_SBCS, sbcs); + dm_write(target, DM_SBCS, sbcs); target_addr_t next_address = address; target_addr_t end_address = address + count * size; @@ -3677,20 +3786,20 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, break; if (size > 12) - riscv_batch_add_dmi_write(batch, DM_SBDATA3, + riscv_batch_add_dm_write(batch, DM_SBDATA3, ((uint32_t) p[12]) | (((uint32_t) p[13]) << 8) | (((uint32_t) p[14]) << 16) | (((uint32_t) p[15]) << 24)); if (size > 8) - riscv_batch_add_dmi_write(batch, DM_SBDATA2, + riscv_batch_add_dm_write(batch, DM_SBDATA2, ((uint32_t) p[8]) | (((uint32_t) p[9]) << 8) | (((uint32_t) p[10]) << 16) | (((uint32_t) p[11]) << 24)); if (size > 4) - riscv_batch_add_dmi_write(batch, DM_SBDATA1, + riscv_batch_add_dm_write(batch, DM_SBDATA1, ((uint32_t) p[4]) | (((uint32_t) p[5]) << 8) | (((uint32_t) p[6]) << 16) | @@ -3702,7 +3811,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, } if (size > 1) value |= ((uint32_t) p[1]) << 8; - riscv_batch_add_dmi_write(batch, DM_SBDATA0, value); + riscv_batch_add_dm_write(batch, DM_SBDATA0, value); log_memory_access(address + i * size, value, size, false); next_address += size; @@ -3717,7 +3826,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, /* Read sbcs value. * At the same time, detect if DMI busy has occurred during the batch write. */ bool dmi_busy_encountered; - if (dmi_op(target, &sbcs, &dmi_busy_encountered, DMI_OP_READ, + if (dm_op(target, &sbcs, &dmi_busy_encountered, DMI_OP_READ, DM_SBCS, 0, false, true) != ERROR_OK) return ERROR_FAIL; if (dmi_busy_encountered) @@ -3732,7 +3841,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, riscv_command_timeout_sec, sbcs); return ERROR_FAIL; } - if (dmi_read(target, &sbcs, DM_SBCS) != ERROR_OK) + if (dm_read(target, &sbcs, DM_SBCS) != ERROR_OK) return ERROR_FAIL; } @@ -3740,7 +3849,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, /* We wrote while the target was busy. */ LOG_DEBUG("Sbbusyerror encountered during system bus write."); /* Clear the sticky error flag. */ - dmi_write(target, DM_SBCS, sbcs | DM_SBCS_SBBUSYERROR); + dm_write(target, DM_SBCS, sbcs | DM_SBCS_SBBUSYERROR); /* Slow down before trying again. */ info->bus_master_write_delay += info->bus_master_write_delay / 10 + 1; } @@ -3776,7 +3885,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, " - buggy sbautoincrement in hw?", next_address); } /* Clear the sticky error flag */ - dmi_write(target, DM_SBCS, DM_SBCS_SBERROR); + dm_write(target, DM_SBCS, DM_SBCS_SBERROR); /* Fail the whole operation */ return ERROR_FAIL; } @@ -3886,8 +3995,8 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, /* Write value. */ if (size > 4) - dmi_write(target, DM_DATA1, value >> 32); - dmi_write(target, DM_DATA0, value); + dm_write(target, DM_DATA1, value >> 32); + dm_write(target, DM_DATA0, value); /* Write and execute command that moves value into S1 and * executes program buffer. */ @@ -3903,14 +4012,14 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, } /* Turn on autoexec */ - dmi_write(target, DM_ABSTRACTAUTO, + dm_write(target, DM_ABSTRACTAUTO, 1 << DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); setup_needed = false; } else { if (size > 4) - riscv_batch_add_dmi_write(batch, DM_DATA1, value >> 32); - riscv_batch_add_dmi_write(batch, DM_DATA0, value); + riscv_batch_add_dm_write(batch, DM_DATA1, value >> 32); + riscv_batch_add_dm_write(batch, DM_DATA0, value); if (riscv_batch_full(batch)) break; } @@ -3927,12 +4036,12 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, uint32_t abstractcs; bool dmi_busy_encountered; - result = dmi_op(target, &abstractcs, &dmi_busy_encountered, + result = dm_op(target, &abstractcs, &dmi_busy_encountered, DMI_OP_READ, DM_ABSTRACTCS, 0, false, true); if (result != ERROR_OK) goto error; while (get_field(abstractcs, DM_ABSTRACTCS_BUSY)) - if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) + if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK) return ERROR_FAIL; info->cmderr = get_field(abstractcs, DM_ABSTRACTCS_CMDERR); if (info->cmderr == CMDERR_NONE && !dmi_busy_encountered) { @@ -3945,7 +4054,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, riscv013_clear_abstract_error(target); increase_ac_busy_delay(target); - dmi_write(target, DM_ABSTRACTAUTO, 0); + dm_write(target, DM_ABSTRACTAUTO, 0); result = register_read_direct(target, &cur_addr, GDB_REGNO_S0); if (result != ERROR_OK) goto error; @@ -3959,7 +4068,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, } error: - dmi_write(target, DM_ABSTRACTAUTO, 0); + dm_write(target, DM_ABSTRACTAUTO, 0); if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) return ERROR_FAIL; @@ -4188,9 +4297,9 @@ static int select_prepped_harts(struct target *target, bool *use_hasel) } for (unsigned int i = 0; i < hawindow_count; i++) { - if (dmi_write(target, DM_HAWINDOWSEL, i) != ERROR_OK) + if (dm_write(target, DM_HAWINDOWSEL, i) != ERROR_OK) return ERROR_FAIL; - if (dmi_write(target, DM_HAWINDOW, hawindow[i]) != ERROR_OK) + if (dm_write(target, DM_HAWINDOW, hawindow[i]) != ERROR_OK) return ERROR_FAIL; } @@ -4217,7 +4326,7 @@ static int riscv013_halt_go(struct target *target) if (use_hasel) dmcontrol |= DM_DMCONTROL_HASEL; dmcontrol = set_hartsel(dmcontrol, r->current_hartid); - dmi_write(target, DM_DMCONTROL, dmcontrol); + dm_write(target, DM_DMCONTROL, dmcontrol); for (size_t i = 0; i < 256; ++i) if (riscv_is_halted(target)) break; @@ -4226,7 +4335,7 @@ static int riscv013_halt_go(struct target *target) uint32_t dmstatus; if (dmstatus_read(target, &dmstatus, true) != ERROR_OK) return ERROR_FAIL; - if (dmi_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK) + if (dm_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK) return ERROR_FAIL; LOG_ERROR("unable to halt hart %d", r->current_hartid); @@ -4236,7 +4345,7 @@ static int riscv013_halt_go(struct target *target) } dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HALTREQ, 0); - dmi_write(target, DM_DMCONTROL, dmcontrol); + dm_write(target, DM_DMCONTROL, dmcontrol); if (use_hasel) { target_list_t *entry; @@ -4307,7 +4416,7 @@ static bool riscv013_is_halted(struct target *target) */ if (target->state == TARGET_HALTED) dmcontrol |= DM_DMCONTROL_HALTREQ; - dmi_write(target, DM_DMCONTROL, dmcontrol); + dm_write(target, DM_DMCONTROL, dmcontrol); } return get_field(dmstatus, DM_DMSTATUS_ALLHALTED); } @@ -4351,7 +4460,7 @@ int riscv013_write_debug_buffer(struct target *target, unsigned int index, riscv if (!dm) return ERROR_FAIL; if (dm->progbuf_cache[index] != data) { - if (dmi_write(target, DM_PROGBUF0 + index, data) != ERROR_OK) + if (dm_write(target, DM_PROGBUF0 + index, data) != ERROR_OK) return ERROR_FAIL; dm->progbuf_cache[index] = data; } else { @@ -4408,6 +4517,27 @@ int riscv013_dmi_write_u64_bits(struct target *target) return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH; } +void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t 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) +{ + 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) +{ + riscv013_fill_dmi_nop_u64(target, buf); +} + static int maybe_execute_fence_i(struct target *target) { if (has_sufficient_progbuf(target, 3)) @@ -4448,7 +4578,7 @@ static int riscv013_step_or_resume_current_hart(struct target *target, if (use_hasel) dmcontrol |= DM_DMCONTROL_HASEL; dmcontrol = set_hartsel(dmcontrol, r->current_hartid); - dmi_write(target, DM_DMCONTROL, dmcontrol); + dm_write(target, DM_DMCONTROL, dmcontrol); dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HASEL, 0); dmcontrol = set_field(dmcontrol, DM_DMCONTROL_RESUMEREQ, 0); @@ -4463,11 +4593,11 @@ static int riscv013_step_or_resume_current_hart(struct target *target, if (step && get_field(dmstatus, DM_DMSTATUS_ALLHALTED) == 0) continue; - dmi_write(target, DM_DMCONTROL, dmcontrol); + dm_write(target, DM_DMCONTROL, dmcontrol); return ERROR_OK; } - dmi_write(target, DM_DMCONTROL, dmcontrol); + dm_write(target, DM_DMCONTROL, dmcontrol); LOG_ERROR("unable to resume hart %d", r->current_hartid); if (dmstatus_read(target, &dmstatus, true) != ERROR_OK) @@ -4488,9 +4618,9 @@ void riscv013_clear_abstract_error(struct target *target) /* Wait for busy to go away. */ time_t start = time(NULL); uint32_t abstractcs; - dmi_read(target, &abstractcs, DM_ABSTRACTCS); + dm_read(target, &abstractcs, DM_ABSTRACTCS); while (get_field(abstractcs, DM_ABSTRACTCS_BUSY)) { - dmi_read(target, &abstractcs, DM_ABSTRACTCS); + dm_read(target, &abstractcs, DM_ABSTRACTCS); if (time(NULL) - start > riscv_command_timeout_sec) { LOG_ERROR("abstractcs.busy is not going low after %d seconds " @@ -4502,5 +4632,5 @@ void riscv013_clear_abstract_error(struct target *target) } } /* Clear the error status. */ - dmi_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); + dm_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 11ef8f9b92..7c3bab7958 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -2677,14 +2677,13 @@ COMMAND_HANDLER(riscv_dmi_read) if (r->dmi_read(target, &value, address) != ERROR_OK) return ERROR_FAIL; command_print(CMD, "0x%" PRIx32, value); - return ERROR_OK; } else { LOG_ERROR("dmi_read is not implemented for this target."); return ERROR_FAIL; } + return ERROR_OK; } - COMMAND_HANDLER(riscv_dmi_write) { if (CMD_ARGC != 2) { @@ -2707,6 +2706,75 @@ COMMAND_HANDLER(riscv_dmi_write) } } +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) { int wait = 0; @@ -2946,6 +3014,20 @@ static const struct command_registration riscv_exec_command_handlers[] = { .usage = "address value", .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", .handler = riscv_reset_delays, @@ -3411,22 +3493,22 @@ int riscv_execute_debug_buffer(struct target *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); - 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); - 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); - r->fill_dmi_nop_u64(target, buf); + r->fill_dm_nop_u64(target, buf); } int riscv_dmi_write_u64_bits(struct target *target) diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index f06b5f516d..43eb7647f3 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -20,6 +20,7 @@ struct riscv_program; #define RISCV_MAX_REGISTERS 5000 #define RISCV_MAX_TRIGGERS 32 #define RISCV_MAX_HWBPS 16 +#define RISCV_MAX_DMS 100 #define DEFAULT_COMMAND_TIMEOUT_SEC 2 #define DEFAULT_RESET_TIMEOUT_SEC 30 @@ -163,10 +164,11 @@ struct riscv_info { riscv_insn_t d); riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned int index); int (*execute_debug_buffer)(struct target *target); + int (*invalidate_cached_debug_buffer)(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_dmi_read_u64)(struct target *target, char *buf, int a); - void (*fill_dmi_nop_u64)(struct target *target, char *buf); + void (*fill_dm_write_u64)(struct target *target, char *buf, int a, uint64_t d); + void (*fill_dm_read_u64)(struct target *target, char *buf, int a); + void (*fill_dm_nop_u64)(struct target *target, char *buf); int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index); int (*authdata_write)(struct target *target, uint32_t value, unsigned int index); @@ -174,6 +176,9 @@ struct riscv_info { 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 (*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, struct riscv_sample_buf *buf, riscv_sample_config_t *config, @@ -341,9 +346,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_execute_debug_buffer(struct target *target); -void riscv_fill_dmi_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_dmi_read_u64(struct target *target, char *buf, int a); +void riscv_fill_dm_nop_u64(struct target *target, char *buf); +void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t d); +void riscv_fill_dm_read_u64(struct target *target, char *buf, int a); int riscv_dmi_write_u64_bits(struct target *target); int riscv_enumerate_triggers(struct target *target); --