Detect hartsellen, limiting which harts we probe
Tested with doctored spike with hartsellens of 0, 1, 3, and 10. Change-Id: I97f57c7d03b076792d5ecd66545d9b9e853ed515
This commit is contained in:
parent
68c57474f9
commit
6a98fb7076
|
@ -441,12 +441,6 @@
|
||||||
#define CSR_MCONTROL_M_LENGTH 1
|
#define CSR_MCONTROL_M_LENGTH 1
|
||||||
#define CSR_MCONTROL_M (0x1ULL << CSR_MCONTROL_M_OFFSET)
|
#define CSR_MCONTROL_M (0x1ULL << CSR_MCONTROL_M_OFFSET)
|
||||||
/*
|
/*
|
||||||
* When set, enable this trigger in H mode.
|
|
||||||
*/
|
|
||||||
#define CSR_MCONTROL_H_OFFSET 5
|
|
||||||
#define CSR_MCONTROL_H_LENGTH 1
|
|
||||||
#define CSR_MCONTROL_H (0x1ULL << CSR_MCONTROL_H_OFFSET)
|
|
||||||
/*
|
|
||||||
* When set, enable this trigger in S mode.
|
* When set, enable this trigger in S mode.
|
||||||
*/
|
*/
|
||||||
#define CSR_MCONTROL_S_OFFSET 4
|
#define CSR_MCONTROL_S_OFFSET 4
|
||||||
|
@ -487,7 +481,7 @@
|
||||||
/*
|
/*
|
||||||
* When count is decremented to 0, the trigger fires. Instead of
|
* When count is decremented to 0, the trigger fires. Instead of
|
||||||
* changing \Fcount from 1 to 0, it is also acceptable for hardware to
|
* changing \Fcount from 1 to 0, it is also acceptable for hardware to
|
||||||
* clear \Fm, \Fh, \Fs, and \Fu. This allows \Fcount to be hard-wired
|
* clear \Fm, \Fs, and \Fu. This allows \Fcount to be hard-wired
|
||||||
* to 1 if this register just exists for single step.
|
* to 1 if this register just exists for single step.
|
||||||
*/
|
*/
|
||||||
#define CSR_ICOUNT_COUNT_OFFSET 10
|
#define CSR_ICOUNT_COUNT_OFFSET 10
|
||||||
|
@ -501,13 +495,6 @@
|
||||||
#define CSR_ICOUNT_M_LENGTH 1
|
#define CSR_ICOUNT_M_LENGTH 1
|
||||||
#define CSR_ICOUNT_M (0x1ULL << CSR_ICOUNT_M_OFFSET)
|
#define CSR_ICOUNT_M (0x1ULL << CSR_ICOUNT_M_OFFSET)
|
||||||
/*
|
/*
|
||||||
* When set, every instruction completed or exception taken in in H mode decrements \Fcount
|
|
||||||
* by 1.
|
|
||||||
*/
|
|
||||||
#define CSR_ICOUNT_H_OFFSET 8
|
|
||||||
#define CSR_ICOUNT_H_LENGTH 1
|
|
||||||
#define CSR_ICOUNT_H (0x1ULL << CSR_ICOUNT_H_OFFSET)
|
|
||||||
/*
|
|
||||||
* When set, every instruction completed or exception taken in S mode decrements \Fcount
|
* When set, every instruction completed or exception taken in S mode decrements \Fcount
|
||||||
* by 1.
|
* by 1.
|
||||||
*/
|
*/
|
||||||
|
@ -544,19 +531,6 @@
|
||||||
#define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET)
|
#define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET)
|
||||||
#define DMI_DMSTATUS 0x11
|
#define DMI_DMSTATUS 0x11
|
||||||
/*
|
/*
|
||||||
* Gets set if the Debug Module was accessed incorrectly.
|
|
||||||
*
|
|
||||||
* 0 (none): No error.
|
|
||||||
*
|
|
||||||
* 1 (badaddr): There was an access to an unimplemented Debug Module
|
|
||||||
* address.
|
|
||||||
*
|
|
||||||
* 7 (other): An access failed for another reason.
|
|
||||||
*/
|
|
||||||
#define DMI_DMSTATUS_DMERR_OFFSET 24
|
|
||||||
#define DMI_DMSTATUS_DMERR_LENGTH 3
|
|
||||||
#define DMI_DMSTATUS_DMERR (0x7U << DMI_DMSTATUS_DMERR_OFFSET)
|
|
||||||
/*
|
|
||||||
* If 1, then there is an implicit {\tt ebreak} instruction at the
|
* If 1, then there is an implicit {\tt ebreak} instruction at the
|
||||||
* non-existent word immediately after the Program Buffer. This saves
|
* non-existent word immediately after the Program Buffer. This saves
|
||||||
* the debugger from having to write the {\tt ebreak} itself, and
|
* the debugger from having to write the {\tt ebreak} itself, and
|
||||||
|
@ -700,7 +674,7 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_HALTREQ_OFFSET 31
|
#define DMI_DMCONTROL_HALTREQ_OFFSET 31
|
||||||
#define DMI_DMCONTROL_HALTREQ_LENGTH 1
|
#define DMI_DMCONTROL_HALTREQ_LENGTH 1
|
||||||
#define DMI_DMCONTROL_HALTREQ (0x1U << DMI_DMCONTROL_HALTREQ_OFFSET)
|
#define DMI_DMCONTROL_HALTREQ (0x1ULL << DMI_DMCONTROL_HALTREQ_OFFSET)
|
||||||
/*
|
/*
|
||||||
* Writes the resume request bit for all currently selected harts.
|
* Writes the resume request bit for all currently selected harts.
|
||||||
* When set to 1, each selected hart will resume if it is currently
|
* When set to 1, each selected hart will resume if it is currently
|
||||||
|
@ -713,7 +687,7 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_RESUMEREQ_OFFSET 30
|
#define DMI_DMCONTROL_RESUMEREQ_OFFSET 30
|
||||||
#define DMI_DMCONTROL_RESUMEREQ_LENGTH 1
|
#define DMI_DMCONTROL_RESUMEREQ_LENGTH 1
|
||||||
#define DMI_DMCONTROL_RESUMEREQ (0x1U << DMI_DMCONTROL_RESUMEREQ_OFFSET)
|
#define DMI_DMCONTROL_RESUMEREQ (0x1ULL << DMI_DMCONTROL_RESUMEREQ_OFFSET)
|
||||||
/*
|
/*
|
||||||
* This optional field writes the reset bit for all the currently
|
* This optional field writes the reset bit for all the currently
|
||||||
* selected harts. To perform a reset the debugger writes 1, and then
|
* selected harts. To perform a reset the debugger writes 1, and then
|
||||||
|
@ -727,7 +701,7 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_HARTRESET_OFFSET 29
|
#define DMI_DMCONTROL_HARTRESET_OFFSET 29
|
||||||
#define DMI_DMCONTROL_HARTRESET_LENGTH 1
|
#define DMI_DMCONTROL_HARTRESET_LENGTH 1
|
||||||
#define DMI_DMCONTROL_HARTRESET (0x1U << DMI_DMCONTROL_HARTRESET_OFFSET)
|
#define DMI_DMCONTROL_HARTRESET (0x1ULL << DMI_DMCONTROL_HARTRESET_OFFSET)
|
||||||
/*
|
/*
|
||||||
* Writing 1 to this bit clears the {\tt havereset} bits for
|
* Writing 1 to this bit clears the {\tt havereset} bits for
|
||||||
* any selected harts.
|
* any selected harts.
|
||||||
|
@ -736,7 +710,7 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_ACKHAVERESET_OFFSET 28
|
#define DMI_DMCONTROL_ACKHAVERESET_OFFSET 28
|
||||||
#define DMI_DMCONTROL_ACKHAVERESET_LENGTH 1
|
#define DMI_DMCONTROL_ACKHAVERESET_LENGTH 1
|
||||||
#define DMI_DMCONTROL_ACKHAVERESET (0x1U << DMI_DMCONTROL_ACKHAVERESET_OFFSET)
|
#define DMI_DMCONTROL_ACKHAVERESET (0x1ULL << DMI_DMCONTROL_ACKHAVERESET_OFFSET)
|
||||||
/*
|
/*
|
||||||
* Selects the definition of currently selected harts.
|
* Selects the definition of currently selected harts.
|
||||||
*
|
*
|
||||||
|
@ -752,14 +726,14 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_HASEL_OFFSET 26
|
#define DMI_DMCONTROL_HASEL_OFFSET 26
|
||||||
#define DMI_DMCONTROL_HASEL_LENGTH 1
|
#define DMI_DMCONTROL_HASEL_LENGTH 1
|
||||||
#define DMI_DMCONTROL_HASEL (0x1U << DMI_DMCONTROL_HASEL_OFFSET)
|
#define DMI_DMCONTROL_HASEL (0x1ULL << DMI_DMCONTROL_HASEL_OFFSET)
|
||||||
/*
|
/*
|
||||||
* The DM-specific index of the hart to select. This hart is always part of the
|
* The DM-specific index of the hart to select. This hart is always part of the
|
||||||
* currently selected harts.
|
* currently selected harts.
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_HARTSEL_OFFSET 16
|
#define DMI_DMCONTROL_HARTSEL_OFFSET 16
|
||||||
#define DMI_DMCONTROL_HARTSEL_LENGTH 10
|
#define DMI_DMCONTROL_HARTSEL_LENGTH HARTSELLEN
|
||||||
#define DMI_DMCONTROL_HARTSEL (0x3ffU << DMI_DMCONTROL_HARTSEL_OFFSET)
|
#define DMI_DMCONTROL_HARTSEL (((1L<<HARTSELLEN)-1) << DMI_DMCONTROL_HARTSEL_OFFSET)
|
||||||
/*
|
/*
|
||||||
* This bit controls the reset signal from the DM to the rest of the
|
* This bit controls the reset signal from the DM to the rest of the
|
||||||
* system. The signal should reset every part of the system, including
|
* system. The signal should reset every part of the system, including
|
||||||
|
@ -771,7 +745,7 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_NDMRESET_OFFSET 1
|
#define DMI_DMCONTROL_NDMRESET_OFFSET 1
|
||||||
#define DMI_DMCONTROL_NDMRESET_LENGTH 1
|
#define DMI_DMCONTROL_NDMRESET_LENGTH 1
|
||||||
#define DMI_DMCONTROL_NDMRESET (0x1U << DMI_DMCONTROL_NDMRESET_OFFSET)
|
#define DMI_DMCONTROL_NDMRESET (0x1ULL << DMI_DMCONTROL_NDMRESET_OFFSET)
|
||||||
/*
|
/*
|
||||||
* This bit serves as a reset signal for the Debug Module itself.
|
* This bit serves as a reset signal for the Debug Module itself.
|
||||||
*
|
*
|
||||||
|
@ -794,7 +768,7 @@
|
||||||
*/
|
*/
|
||||||
#define DMI_DMCONTROL_DMACTIVE_OFFSET 0
|
#define DMI_DMCONTROL_DMACTIVE_OFFSET 0
|
||||||
#define DMI_DMCONTROL_DMACTIVE_LENGTH 1
|
#define DMI_DMCONTROL_DMACTIVE_LENGTH 1
|
||||||
#define DMI_DMCONTROL_DMACTIVE (0x1U << DMI_DMCONTROL_DMACTIVE_OFFSET)
|
#define DMI_DMCONTROL_DMACTIVE (0x1ULL << DMI_DMCONTROL_DMACTIVE_OFFSET)
|
||||||
#define DMI_HARTINFO 0x12
|
#define DMI_HARTINFO 0x12
|
||||||
/*
|
/*
|
||||||
* Number of {\tt dscratch} registers available for the debugger
|
* Number of {\tt dscratch} registers available for the debugger
|
||||||
|
@ -822,6 +796,9 @@
|
||||||
*
|
*
|
||||||
* If \Fdataaccess is 1: Number of 32-bit words in the memory map
|
* If \Fdataaccess is 1: Number of 32-bit words in the memory map
|
||||||
* dedicated to shadowing the {\tt data} registers.
|
* dedicated to shadowing the {\tt data} registers.
|
||||||
|
*
|
||||||
|
* Since there are at most 12 {\tt data} registers, the value in this
|
||||||
|
* register must be 12 or smaller.
|
||||||
*/
|
*/
|
||||||
#define DMI_HARTINFO_DATASIZE_OFFSET 12
|
#define DMI_HARTINFO_DATASIZE_OFFSET 12
|
||||||
#define DMI_HARTINFO_DATASIZE_LENGTH 4
|
#define DMI_HARTINFO_DATASIZE_LENGTH 4
|
||||||
|
@ -988,8 +965,8 @@
|
||||||
* abstract command interface. Valid sizes are 0 - 12.
|
* abstract command interface. Valid sizes are 0 - 12.
|
||||||
*/
|
*/
|
||||||
#define DMI_ABSTRACTCS_DATACOUNT_OFFSET 0
|
#define DMI_ABSTRACTCS_DATACOUNT_OFFSET 0
|
||||||
#define DMI_ABSTRACTCS_DATACOUNT_LENGTH 5
|
#define DMI_ABSTRACTCS_DATACOUNT_LENGTH 4
|
||||||
#define DMI_ABSTRACTCS_DATACOUNT (0x1fU << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
|
#define DMI_ABSTRACTCS_DATACOUNT (0xfU << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
|
||||||
#define DMI_COMMAND 0x17
|
#define DMI_COMMAND 0x17
|
||||||
/*
|
/*
|
||||||
* The type determines the overall functionality of this
|
* The type determines the overall functionality of this
|
||||||
|
@ -1007,14 +984,14 @@
|
||||||
#define DMI_COMMAND_CONTROL (0xffffffU << DMI_COMMAND_CONTROL_OFFSET)
|
#define DMI_COMMAND_CONTROL (0xffffffU << DMI_COMMAND_CONTROL_OFFSET)
|
||||||
#define DMI_ABSTRACTAUTO 0x18
|
#define DMI_ABSTRACTAUTO 0x18
|
||||||
/*
|
/*
|
||||||
* When a bit in this field is 1, read or write accesses the corresponding {\tt progbuf} word
|
* When a bit in this field is 1, read or write accesses to the corresponding {\tt progbuf} word
|
||||||
* cause the command in \Rcommand to be executed again.
|
* cause the command in \Rcommand to be executed again.
|
||||||
*/
|
*/
|
||||||
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
|
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
|
||||||
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
|
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
|
||||||
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
|
#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
|
||||||
/*
|
/*
|
||||||
* When a bit in this field is 1, read or write accesses the corresponding {\tt data} word
|
* When a bit in this field is 1, read or write accesses to the corresponding {\tt data} word
|
||||||
* cause the command in \Rcommand to be executed again.
|
* cause the command in \Rcommand to be executed again.
|
||||||
*/
|
*/
|
||||||
#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
|
#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
|
||||||
|
@ -1041,17 +1018,59 @@
|
||||||
#define DMI_AUTHDATA_DATA_OFFSET 0
|
#define DMI_AUTHDATA_DATA_OFFSET 0
|
||||||
#define DMI_AUTHDATA_DATA_LENGTH 32
|
#define DMI_AUTHDATA_DATA_LENGTH 32
|
||||||
#define DMI_AUTHDATA_DATA (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET)
|
#define DMI_AUTHDATA_DATA (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET)
|
||||||
|
#define DMI_SBADDRESS3 0x37
|
||||||
|
/*
|
||||||
|
* Accesses bits 127:96 of the physical address in {\tt sbaddress} (if
|
||||||
|
* the system address bus is that wide).
|
||||||
|
*/
|
||||||
|
#define DMI_SBADDRESS3_ADDRESS_OFFSET 0
|
||||||
|
#define DMI_SBADDRESS3_ADDRESS_LENGTH 32
|
||||||
|
#define DMI_SBADDRESS3_ADDRESS (0xffffffffU << DMI_SBADDRESS3_ADDRESS_OFFSET)
|
||||||
#define DMI_SBCS 0x38
|
#define DMI_SBCS 0x38
|
||||||
/*
|
/*
|
||||||
* When a 1 is written here, triggers a read at the address in {\tt
|
* 0: The System Bus interface conforms to mainline drafts of this
|
||||||
* sbaddress} using the access size set by \Fsbaccess.
|
* spec older than 1 January, 2018.
|
||||||
|
*
|
||||||
|
* 1: The System Bus interface conforms to this version of the spec.
|
||||||
|
*
|
||||||
|
* Other values are reserved for future versions.
|
||||||
*/
|
*/
|
||||||
#define DMI_SBCS_SBSINGLEREAD_OFFSET 20
|
#define DMI_SBCS_SBVERSION_OFFSET 29
|
||||||
#define DMI_SBCS_SBSINGLEREAD_LENGTH 1
|
#define DMI_SBCS_SBVERSION_LENGTH 3
|
||||||
#define DMI_SBCS_SBSINGLEREAD (0x1U << DMI_SBCS_SBSINGLEREAD_OFFSET)
|
#define DMI_SBCS_SBVERSION (0x7U << DMI_SBCS_SBVERSION_OFFSET)
|
||||||
/*
|
/*
|
||||||
* Select the access size to use for system bus accesses triggered by
|
* Set when the debugger attempts to read data while a read is in
|
||||||
* writes to the {\tt sbaddress} registers or \Rsbdatazero.
|
* progress, or when the debugger initiates a new access while one is
|
||||||
|
* already in progress (while \Fsbbusy is set). It remains set until
|
||||||
|
* it's explicitly cleared by the debugger.
|
||||||
|
*
|
||||||
|
* While this field is non-zero, no more system bus accesses can be
|
||||||
|
* initiated by the debug module.
|
||||||
|
*/
|
||||||
|
#define DMI_SBCS_SBBUSYERROR_OFFSET 22
|
||||||
|
#define DMI_SBCS_SBBUSYERROR_LENGTH 1
|
||||||
|
#define DMI_SBCS_SBBUSYERROR (0x1U << DMI_SBCS_SBBUSYERROR_OFFSET)
|
||||||
|
/*
|
||||||
|
* When 1, indicates the system bus master is busy. (Whether the
|
||||||
|
* system bus itself is busy is related, but not the same thing.) This
|
||||||
|
* bit goes high immediately when a read or write is requested for any
|
||||||
|
* reason, and does not go low until the access is fully completed.
|
||||||
|
*
|
||||||
|
* To avoid race conditions, debuggers must not try to clear \Fsberror
|
||||||
|
* until they read \Fsbbusy as 0.
|
||||||
|
*/
|
||||||
|
#define DMI_SBCS_SBBUSY_OFFSET 21
|
||||||
|
#define DMI_SBCS_SBBUSY_LENGTH 1
|
||||||
|
#define DMI_SBCS_SBBUSY (0x1U << DMI_SBCS_SBBUSY_OFFSET)
|
||||||
|
/*
|
||||||
|
* When 1, every write to \Rsbaddresszero automatically triggers a
|
||||||
|
* system bus read at the new address.
|
||||||
|
*/
|
||||||
|
#define DMI_SBCS_SBREADONADDR_OFFSET 20
|
||||||
|
#define DMI_SBCS_SBREADONADDR_LENGTH 1
|
||||||
|
#define DMI_SBCS_SBREADONADDR (0x1U << DMI_SBCS_SBREADONADDR_OFFSET)
|
||||||
|
/*
|
||||||
|
* Select the access size to use for system bus accesses.
|
||||||
*
|
*
|
||||||
* 0: 8-bit
|
* 0: 8-bit
|
||||||
*
|
*
|
||||||
|
@ -1063,8 +1082,8 @@
|
||||||
*
|
*
|
||||||
* 4: 128-bit
|
* 4: 128-bit
|
||||||
*
|
*
|
||||||
* If an unsupported system bus access size is written here, the DM
|
* If \Fsbaccess has an unsupported value when the DM starts a bus
|
||||||
* does not perform the access and sberror is set to 3.
|
* access, the access is not performed and \Fsberror is set to 3.
|
||||||
*/
|
*/
|
||||||
#define DMI_SBCS_SBACCESS_OFFSET 17
|
#define DMI_SBCS_SBACCESS_OFFSET 17
|
||||||
#define DMI_SBCS_SBACCESS_LENGTH 3
|
#define DMI_SBCS_SBACCESS_LENGTH 3
|
||||||
|
@ -1080,9 +1099,9 @@
|
||||||
* When 1, every read from \Rsbdatazero automatically triggers a
|
* When 1, every read from \Rsbdatazero automatically triggers a
|
||||||
* system bus read at the (possibly auto-incremented) address.
|
* system bus read at the (possibly auto-incremented) address.
|
||||||
*/
|
*/
|
||||||
#define DMI_SBCS_SBAUTOREAD_OFFSET 15
|
#define DMI_SBCS_SBREADONDATA_OFFSET 15
|
||||||
#define DMI_SBCS_SBAUTOREAD_LENGTH 1
|
#define DMI_SBCS_SBREADONDATA_LENGTH 1
|
||||||
#define DMI_SBCS_SBAUTOREAD (0x1U << DMI_SBCS_SBAUTOREAD_OFFSET)
|
#define DMI_SBCS_SBREADONDATA (0x1U << DMI_SBCS_SBREADONDATA_OFFSET)
|
||||||
/*
|
/*
|
||||||
* When the debug module's system bus
|
* When the debug module's system bus
|
||||||
* master causes a bus error, this field gets set. The bits in this
|
* master causes a bus error, this field gets set. The bits in this
|
||||||
|
@ -1097,10 +1116,6 @@
|
||||||
* 2: A bad address was accessed.
|
* 2: A bad address was accessed.
|
||||||
*
|
*
|
||||||
* 3: There was some other error (eg. alignment).
|
* 3: There was some other error (eg. alignment).
|
||||||
*
|
|
||||||
* 4: The system bus master was busy when one of the
|
|
||||||
* {\tt sbaddress} or {\tt sbdata} registers was written,
|
|
||||||
* or \Rsbdatazero was read when it had stale data.
|
|
||||||
*/
|
*/
|
||||||
#define DMI_SBCS_SBERROR_OFFSET 12
|
#define DMI_SBCS_SBERROR_OFFSET 12
|
||||||
#define DMI_SBCS_SBERROR_LENGTH 3
|
#define DMI_SBCS_SBERROR_LENGTH 3
|
||||||
|
|
|
@ -179,8 +179,23 @@ typedef struct {
|
||||||
uint8_t datasize;
|
uint8_t datasize;
|
||||||
uint8_t dataaccess;
|
uint8_t dataaccess;
|
||||||
int16_t dataaddr;
|
int16_t dataaddr;
|
||||||
|
|
||||||
|
/* The width of the hartsel field. */
|
||||||
|
unsigned hartsellen;
|
||||||
} riscv013_info_t;
|
} riscv013_info_t;
|
||||||
|
|
||||||
|
static riscv013_info_t *get_info(const struct target *target)
|
||||||
|
{
|
||||||
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
return (riscv013_info_t *) info->version_specific;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t hartsel_mask(const struct target *target)
|
||||||
|
{
|
||||||
|
RISCV013_INFO(info);
|
||||||
|
return ((1L<<info->hartsellen)-1) << DMI_DMCONTROL_HARTSEL_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
static void decode_dmi(char *text, unsigned address, unsigned data)
|
static void decode_dmi(char *text, unsigned address, unsigned data)
|
||||||
{
|
{
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -192,7 +207,7 @@ static void decode_dmi(char *text, unsigned address, unsigned data)
|
||||||
{ DMI_DMCONTROL, DMI_DMCONTROL_RESUMEREQ, "resumereq" },
|
{ DMI_DMCONTROL, DMI_DMCONTROL_RESUMEREQ, "resumereq" },
|
||||||
{ DMI_DMCONTROL, DMI_DMCONTROL_HARTRESET, "hartreset" },
|
{ DMI_DMCONTROL, DMI_DMCONTROL_HARTRESET, "hartreset" },
|
||||||
{ DMI_DMCONTROL, DMI_DMCONTROL_HASEL, "hasel" },
|
{ DMI_DMCONTROL, DMI_DMCONTROL_HASEL, "hasel" },
|
||||||
{ DMI_DMCONTROL, DMI_DMCONTROL_HARTSEL, "hartsel" },
|
{ DMI_DMCONTROL, ((1L<<10)-1) << DMI_DMCONTROL_HARTSEL_OFFSET, "hartsel" },
|
||||||
{ DMI_DMCONTROL, DMI_DMCONTROL_NDMRESET, "ndmreset" },
|
{ DMI_DMCONTROL, DMI_DMCONTROL_NDMRESET, "ndmreset" },
|
||||||
{ DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE, "dmactive" },
|
{ DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE, "dmactive" },
|
||||||
|
|
||||||
|
@ -275,12 +290,6 @@ static void dump_field(const struct scan_field *field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static riscv013_info_t *get_info(const struct target *target)
|
|
||||||
{
|
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
|
||||||
return (riscv013_info_t *) info->version_specific;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Utility functions. ***/
|
/*** Utility functions. ***/
|
||||||
|
|
||||||
static void select_dmi(struct target *target)
|
static void select_dmi(struct target *target)
|
||||||
|
@ -1155,54 +1164,50 @@ static int examine(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the Debug Module. */
|
/* Reset the Debug Module. */
|
||||||
dmi_write(target, DMI_DMCONTROL, 0);
|
uint32_t max_hartsel_mask = ((1L<<10)-1) << DMI_DMCONTROL_HARTSEL_OFFSET;
|
||||||
dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
dmi_write(target, DMI_DMCONTROL, max_hartsel_mask);
|
||||||
|
dmi_write(target, DMI_DMCONTROL, max_hartsel_mask | DMI_DMCONTROL_DMACTIVE);
|
||||||
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||||
|
|
||||||
uint32_t hartinfo = dmi_read(target, DMI_HARTINFO);
|
|
||||||
|
|
||||||
LOG_DEBUG("dmcontrol: 0x%08x", dmcontrol);
|
|
||||||
LOG_DEBUG("dmstatus: 0x%08x", dmstatus);
|
|
||||||
LOG_DEBUG("hartinfo: 0x%08x", hartinfo);
|
|
||||||
|
|
||||||
info->datasize = get_field(hartinfo, DMI_HARTINFO_DATASIZE);
|
|
||||||
info->dataaccess = get_field(hartinfo, DMI_HARTINFO_DATAACCESS);
|
|
||||||
info->dataaddr = get_field(hartinfo, DMI_HARTINFO_DATAADDR);
|
|
||||||
|
|
||||||
if (!get_field(dmcontrol, DMI_DMCONTROL_DMACTIVE)) {
|
if (!get_field(dmcontrol, DMI_DMCONTROL_DMACTIVE)) {
|
||||||
LOG_ERROR("Debug Module did not become active. dmcontrol=0x%x",
|
LOG_ERROR("Debug Module did not become active. dmcontrol=0x%x",
|
||||||
dmcontrol);
|
dmcontrol);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t hartsel = get_field(dmcontrol, max_hartsel_mask);
|
||||||
|
info->hartsellen = 0;
|
||||||
|
while (hartsel & 1) {
|
||||||
|
info->hartsellen++;
|
||||||
|
hartsel >>= 1;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("hartsellen=%d", info->hartsellen);
|
||||||
|
|
||||||
|
uint32_t hartinfo = dmi_read(target, DMI_HARTINFO);
|
||||||
|
|
||||||
|
info->datasize = get_field(hartinfo, DMI_HARTINFO_DATASIZE);
|
||||||
|
info->dataaccess = get_field(hartinfo, DMI_HARTINFO_DATAACCESS);
|
||||||
|
info->dataaddr = get_field(hartinfo, DMI_HARTINFO_DATAADDR);
|
||||||
|
|
||||||
if (!get_field(dmstatus, DMI_DMSTATUS_AUTHENTICATED)) {
|
if (!get_field(dmstatus, DMI_DMSTATUS_AUTHENTICATED)) {
|
||||||
LOG_ERROR("Authentication required by RISC-V core but not "
|
LOG_ERROR("Authentication required by RISC-V core but not "
|
||||||
"supported by OpenOCD. dmcontrol=0x%x", dmcontrol);
|
"supported by OpenOCD. dmcontrol=0x%x", dmcontrol);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) {
|
|
||||||
LOG_ERROR("The hart is unavailable.");
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT)) {
|
|
||||||
LOG_ERROR("The hart doesn't exist.");
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that abstract data registers are accessible. */
|
/* Check that abstract data registers are accessible. */
|
||||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
|
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
|
||||||
info->progbufsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE);
|
info->progbufsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE);
|
||||||
|
|
||||||
/* Before doing anything else we must first enumerate the harts. */
|
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK);
|
r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK);
|
||||||
|
|
||||||
|
/* Before doing anything else we must first enumerate the harts. */
|
||||||
|
|
||||||
/* Don't call any riscv_* functions until after we've counted the number of
|
/* Don't call any riscv_* functions until after we've counted the number of
|
||||||
* cores and initialized registers. */
|
* cores and initialized registers. */
|
||||||
for (int i = 0; i < RISCV_MAX_HARTS; ++i) {
|
for (int i = 0; i < MIN(RISCV_MAX_HARTS, 1 << info->hartsellen); ++i) {
|
||||||
if (!riscv_rtos_enabled(target) && i != target->coreid)
|
if (!riscv_rtos_enabled(target) && i != target->coreid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1248,6 +1253,11 @@ static int examine(struct target *target)
|
||||||
|
|
||||||
LOG_DEBUG("Enumerated %d harts", r->hart_count);
|
LOG_DEBUG("Enumerated %d harts", r->hart_count);
|
||||||
|
|
||||||
|
if (r->hart_count == 0) {
|
||||||
|
LOG_ERROR("No harts found!");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Then we check the number of triggers availiable to each hart. */
|
/* Then we check the number of triggers availiable to each hart. */
|
||||||
riscv_enumerate_triggers(target);
|
riscv_enumerate_triggers(target);
|
||||||
|
|
||||||
|
@ -1297,7 +1307,7 @@ static int assert_reset(struct target *target)
|
||||||
if (!riscv_hart_enabled(target, i))
|
if (!riscv_hart_enabled(target, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
control = set_field(control_base, DMI_DMCONTROL_HARTSEL, i);
|
control = set_field(control_base, hartsel_mask(target), i);
|
||||||
control = set_field(control, DMI_DMCONTROL_HALTREQ,
|
control = set_field(control, DMI_DMCONTROL_HALTREQ,
|
||||||
target->reset_halt ? 1 : 0);
|
target->reset_halt ? 1 : 0);
|
||||||
dmi_write(target, DMI_DMCONTROL, control);
|
dmi_write(target, DMI_DMCONTROL, control);
|
||||||
|
@ -1308,7 +1318,7 @@ static int assert_reset(struct target *target)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Reset just this hart. */
|
/* Reset just this hart. */
|
||||||
uint32_t control = set_field(control_base, DMI_DMCONTROL_HARTSEL,
|
uint32_t control = set_field(control_base, hartsel_mask(target),
|
||||||
r->current_hartid);
|
r->current_hartid);
|
||||||
control = set_field(control, DMI_DMCONTROL_HALTREQ,
|
control = set_field(control, DMI_DMCONTROL_HALTREQ,
|
||||||
target->reset_halt ? 1 : 0);
|
target->reset_halt ? 1 : 0);
|
||||||
|
@ -1342,7 +1352,7 @@ static int deassert_reset(struct target *target)
|
||||||
/* Clear the reset, but make sure haltreq is still set */
|
/* Clear the reset, but make sure haltreq is still set */
|
||||||
uint32_t control = 0;
|
uint32_t control = 0;
|
||||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
|
control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
|
||||||
control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid);
|
control = set_field(control, hartsel_mask(target), r->current_hartid);
|
||||||
control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1);
|
control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1);
|
||||||
dmi_write(target, DMI_DMCONTROL, control);
|
dmi_write(target, DMI_DMCONTROL, control);
|
||||||
|
|
||||||
|
@ -1948,7 +1958,7 @@ static void riscv013_select_current_hart(struct target *target)
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
|
|
||||||
uint64_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
uint64_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSEL, r->current_hartid);
|
dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid);
|
||||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue