Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Initial RISC-V debug support (v0.13 spec) #1380

Merged
merged 62 commits into from
Oct 31, 2023
Merged
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
13684c6
riscv_debug: Begun building a scan handler for RISC-V debug v0.13 dev…
dragonmux Feb 8, 2023
d955617
riscv_debug: Created a stub for initialising a DMI
dragonmux Feb 8, 2023
f827d4b
riscv_debug: Implemented a way to read/write the DTM control/status r…
dragonmux Feb 8, 2023
637f5f9
riscv_debug: Moved the JTAG-specific DTM handler into the JTAG DTM im…
dragonmux Mar 21, 2023
be66247
riscv_debug: Implemented support for reading and dispatching the DTM …
dragonmux Feb 8, 2023
55e8550
riscv_debug: Implemented reference counting and stub structures for t…
dragonmux Feb 8, 2023
0f3ce8d
riscv_debug: Restructed riscv_dmi_init() and riscv_jtag_dtm_init() to…
dragonmux Feb 8, 2023
1aefd61
riscv_debug: Handle the idle cycles component of the DTMCS register
dragonmux Feb 8, 2023
95a5d4d
riscv_debug: Implemented a way to read the DMI address space
dragonmux Feb 8, 2023
9ab2ad6
riscv_debug: Implemented logic for iterating and discovering DMs
dragonmux Feb 8, 2023
1a33d28
riscv_debug: Begun implementing the hart enumeration process
dragonmux Feb 8, 2023
104cfb3
riscv_debug: Implemented enumeration of the harts associated with a DM
dragonmux Feb 8, 2023
9494851
riscv_debug: Implemented support for grabbing the hart's address bus …
dragonmux Feb 8, 2023
f021934
riscv_debug: Implemented halt and resume support in preparation for r…
dragonmux Feb 8, 2023
582fefb
riscv_debug: Implemented readout of CSRs and reading the 4 hart ident…
dragonmux Feb 8, 2023
c9387aa
riscv_debug: Implemented readout of the ISA register to determine add…
dragonmux Feb 8, 2023
00752f7
riscv_debug: Implemented the ability for riscv_reg_read() to do 128-,…
dragonmux Feb 9, 2023
b59b369
riscv_debug: Implemented support for discovering the target Hart's IS…
dragonmux Feb 9, 2023
dafc14d
riscv_debug: Implemented writing to CSRs
dragonmux Feb 9, 2023
aa4f8b6
riscv_debug: Created probe stubs for probing RISC-V 32- and 64-bit ta…
dragonmux Feb 9, 2023
d8d70a2
riscv_debug: Set up the target designer code field
dragonmux Feb 9, 2023
825f622
riscv_debug: Documented the used CSR addresses
dragonmux Feb 9, 2023
4297679
riscv_debug: Implemented the ability to force a CSR access to a speci…
dragonmux Feb 9, 2023
9935f0a
riscv_debug: Implemented single-stepping support in riscv_halt_resume()
dragonmux Feb 9, 2023
d199ea4
riscv_debug: Added definitions for the abstract memory access command
dragonmux Feb 9, 2023
ba89798
riscv_debug: Implemented arbitrary memory read
dragonmux Feb 9, 2023
33ef9b5
riscv_debug: Fixed the target hart not being halted during probing
dragonmux Feb 9, 2023
d567386
riscv_debug: Added some DEBUG_TARGET information to the CSR functions…
dragonmux Feb 9, 2023
ab75c95
riscv_debug: Implemented the target check_error hook
dragonmux Feb 9, 2023
b018366
riscv_debug: Made more of the DM and hart machinary available in the …
dragonmux Feb 9, 2023
65a1d8e
riscv_debug: Moved the mem_read implementation into the bitness-speci…
dragonmux Feb 9, 2023
790a3fc
riscv_debug: Forced the vendor ID to be read 32-bit per the privilege…
dragonmux Feb 9, 2023
1bb0332
riscv_debug: Handle the rv128 case by complaining to the user we don'…
dragonmux Feb 9, 2023
9a91735
riscv_debug: Begun implementing attach/detach
dragonmux Feb 9, 2023
f84c117
riscv_debug: Implemented building the target description XML
dragonmux Feb 10, 2023
c9ea2aa
riscv_debug: Implemented regs_read for both rv32 and rv64
dragonmux Feb 10, 2023
3d024a2
riscv_debug: Halt the hart we're looking at to on attach, and resume …
dragonmux Feb 10, 2023
7727bd1
riscv32: Added some better documentation for what various things do
dragonmux Feb 10, 2023
07f80cc
riscv64: Added some better documentation for what various things do
dragonmux Feb 10, 2023
ce008df
riscv_debug: Fixed a couple of mistakes in the comments for riscv_dmi…
dragonmux Feb 10, 2023
7f892b7
riscv_debug: Implemented the target halt_poll hook
dragonmux Feb 10, 2023
ffbef8d
riscv_debug: Implemented discovery of the available "trigger" slots a…
dragonmux Feb 10, 2023
bbec2b1
riscv_debug: Implemented support machinary for being able to set watc…
dragonmux Feb 10, 2023
0cceab3
riscv_debug: Added documentation on where to find the debug specs used
dragonmux Feb 10, 2023
6e58808
riscv_debug: Implemented a translator for a breakwatch size to match …
dragonmux Feb 10, 2023
8fb27fd
riscv32: Implemented the target breakwatch_set hook
dragonmux Feb 10, 2023
f8e3c0c
riscv32: Implemented the target breakwatch_clear hook
dragonmux Feb 10, 2023
8c7059f
gdb_main: Added some comments to aid with understanding handle_z_pack…
dragonmux Feb 10, 2023
da2f94a
riscv_debug: Moved the part ID readout into its own function, fixing …
dragonmux Feb 11, 2023
0f392b3
riscv_debug: Implemented target reset
dragonmux Feb 11, 2023
c9ed334
riscv_debug: Refactored out the DM state polling code into a new func…
dragonmux Feb 11, 2023
c485fd6
riscv_debug: Implemented polling for reset succeeding and then acknow…
dragonmux Feb 11, 2023
8dad8bb
riscv32: Improved the checks in riscv32_breakwatch_set() to avoid usi…
dragonmux Feb 11, 2023
89846d3
riscv_debug: Cleaned up the nomenclature of riscv_halt_poll()'s halt …
dragonmux Feb 11, 2023
330beee
riscv_debug: Implemented regs_write for both rv32 and rv64
dragonmux Feb 11, 2023
fd6bf73
riscv32: Implemented mem_write and a data packing helper
dragonmux Feb 11, 2023
b7c38b5
riscv_debug: Transform JTAG ID Code designer into JEP-106 internal fo…
perigoso Feb 19, 2023
690cbd2
riscv_debug: Fixed the vendor ID decode in riscv_hart_read_ids() to a…
dragonmux Mar 28, 2023
037a35f
riscv_debug: Implemented poll timeouts for halt/resume
dragonmux Apr 1, 2023
7d936f9
riscv: check if hw reset worked, if not do a DM reset
Aug 13, 2023
a032220
riscv: make sure the hart is stopped when exiting reset
Aug 15, 2023
11ec1f1
riscv: add single register access, add csr access with an offset, exp…
Aug 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
riscv_debug: Implemented enumeration of the harts associated with a DM
dragonmux committed Oct 31, 2023
commit 104cfb302f7ab7cf460f100edc11ccc40bc2b72a
67 changes: 59 additions & 8 deletions src/target/riscv_debug.c
Original file line number Diff line number Diff line change
@@ -32,19 +32,29 @@
*/

#include "general.h"
#include "target_internal.h"
#include "riscv_debug.h"

#define RV_DM_CONTROL 0x10U
#define RV_DM_STATUS 0x11U
#define RV_DM_NEXT_DM 0x1dU

#define RV_DM_CTRL_ACTIVE 0x00000001U
#define RV_DM_CTRL_HARTSEL_MASK 0x0003ffc0U
#define RV_DM_CTRL_HARTSEL_SHIFT 6U
#define RV_DM_CTRL_ACTIVE 0x00000001U
#define RV_DM_CTRL_HARTSEL_MASK 0x03ffffc0U
#define RV_DM_CTRL_HARTSELLO_MASK 0x03ff0000U
#define RV_DM_CTRL_HARTSELHI_MASK 0x0000ffc0U
#define RV_DM_CTRL_HARTSELLO_SHIFT 16U
#define RV_DM_CTRL_HARTSELHI_SHIFT 4U

#define RV_DM_STAT_NON_EXISTENT 0x00004000U

static void riscv_dm_init(riscv_dm_s *dbg_module);
static bool riscv_hart_init(riscv_hart_s *hart);
static void riscv_hart_free(void *priv);
static bool riscv_dmi_read(riscv_dmi_s *dmi, uint32_t address, uint32_t *value);
static bool riscv_dmi_write(riscv_dmi_s *dmi, uint32_t address, uint32_t value);
static void riscv_dm_ref(riscv_dm_s *dbg_module);
static void riscv_dm_unref(riscv_dm_s *dbg_module);
static inline bool riscv_dm_read(riscv_dm_s *dbg_module, uint8_t address, uint32_t *value);
static inline bool riscv_dm_write(riscv_dm_s *dbg_module, uint8_t address, uint32_t value);
static riscv_debug_version_e riscv_dm_version(uint32_t status);
@@ -106,12 +116,53 @@ static void riscv_dm_init(riscv_dm_s *const dbg_module)
uint32_t control = RV_DM_CTRL_ACTIVE | RV_DM_CTRL_HARTSEL_MASK;
if (!riscv_dm_write(dbg_module, RV_DM_CONTROL, control) || !riscv_dm_read(dbg_module, RV_DM_CONTROL, &control))
return;
/* Extract the maxinium number of harts present and iterate through the harts */
const uint32_t harts_max = (control & RV_DM_CTRL_HARTSEL_MASK) >> RV_DM_CTRL_HARTSEL_SHIFT;
for (uint32_t hart = 0; hart <= harts_max; ++hart) {
/* Extract the maximum number of harts present and iterate through the harts */
const uint32_t harts_max = ((control & RV_DM_CTRL_HARTSELLO_MASK) >> RV_DM_CTRL_HARTSELLO_SHIFT) |
((control & RV_DM_CTRL_HARTSELHI_MASK) << RV_DM_CTRL_HARTSELHI_SHIFT);
for (uint32_t hart_idx = 0; hart_idx <= harts_max; ++hart_idx) {
/* Select the hart */
control = ((hart_idx << RV_DM_CTRL_HARTSELLO_SHIFT) & RV_DM_CTRL_HARTSELLO_MASK) |
((hart_idx >> RV_DM_CTRL_HARTSELHI_SHIFT) & RV_DM_CTRL_HARTSELHI_MASK) | RV_DM_CTRL_ACTIVE;
uint32_t status = 0;
if (!riscv_dm_write(dbg_module, RV_DM_CONTROL, control) || !riscv_dm_read(dbg_module, RV_DM_STATUS, &status))
return;
/* If the hart doesn't exist, the spec says to terminate scan */
if (status & RV_DM_STAT_NON_EXISTENT)
break;

riscv_hart_s *hart = calloc(1, sizeof(*hart));
if (!hart) { /* calloc failed: heap exhaustion */
DEBUG_WARN("calloc: failed in %s\n", __func__);
return;
}
/* Setup the hart structure and discover the target core */
hart->dbg_module = dbg_module;
hart->hartsel = control;
if (!riscv_hart_init(hart))
free(hart);
}
}

static bool riscv_hart_init(riscv_hart_s *const hart)
{
target_s *target = target_new();
if (!target)
return false;

riscv_dm_ref(hart->dbg_module);
target->cpuid = hart->dbg_module->dmi_bus->idcode;
target->driver = "RISC-V";
target->priv = hart;
target->priv_free = riscv_hart_free;
return true;
}

static void riscv_hart_free(void *const priv)
{
riscv_dm_unref(((riscv_hart_s *)priv)->dbg_module);
free(priv);
}

static bool riscv_dmi_read(riscv_dmi_s *const dmi, const uint32_t address, uint32_t *const value)
{
return dmi->read(dmi, address, value);
@@ -164,14 +215,14 @@ static inline void riscv_dmi_unref(riscv_dmi_s *const dmi)
free(dmi);
}

void riscv_dm_ref(riscv_dm_s *const dbg_module)
static void riscv_dm_ref(riscv_dm_s *const dbg_module)
{
if (!dbg_module->ref_count)
riscv_dmi_ref(dbg_module->dmi_bus);
++dbg_module->ref_count;
}

void riscv_dm_unref(riscv_dm_s *const dbg_module)
static void riscv_dm_unref(riscv_dm_s *const dbg_module)
{
--dbg_module->ref_count;
if (!dbg_module->ref_count) {
4 changes: 1 addition & 3 deletions src/target/riscv_debug.h
Original file line number Diff line number Diff line change
@@ -75,14 +75,12 @@ typedef struct riscv_dm {
/* This represents a specifc Hart on a DM */
typedef struct riscv_hart {
riscv_dm_s *dbg_module;
uint32_t hartsel;
} riscv_hart_s;

#define RV_STATUS_VERSION_MASK 0x0000000fU

void riscv_jtag_dtm_handler(uint8_t dev_index);
void riscv_dmi_init(riscv_dmi_s *dmi);

void riscv_dm_ref(riscv_dm_s *dbg_module);
void riscv_dm_unref(riscv_dm_s *dbg_module);

#endif /*TARGET_RISCV_DEBUG_H*/