Merge pull request #181 from riscv/propagate_errors
Propagate register read errors
This commit is contained in:
commit
160b794274
|
@ -281,7 +281,12 @@ static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char
|
|||
*hex_reg_list[0] = '\0';
|
||||
for (size_t i = 0; i < n_regs; ++i) {
|
||||
if (riscv_has_register(rtos->target, thread_id, i)) {
|
||||
uint64_t reg_value = riscv_get_register_on_hart(rtos->target, thread_id - 1, i);
|
||||
uint64_t reg_value;
|
||||
int result = riscv_get_register_on_hart(rtos->target, ®_value,
|
||||
thread_id - 1, i);
|
||||
if (result != ERROR_OK)
|
||||
return JIM_ERR;
|
||||
|
||||
for (size_t byte = 0; byte < xlen / 8; ++byte) {
|
||||
uint8_t reg_byte = reg_value >> (byte * 8);
|
||||
char hex[3] = {'x', 'x', 'x'};
|
||||
|
|
|
@ -47,7 +47,9 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
|
|||
for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) {
|
||||
if (p->writes_xreg[i]) {
|
||||
LOG_DEBUG("Saving register %d as used by program", (int)i);
|
||||
saved_registers[i] = riscv_get_register(t, i);
|
||||
int result = riscv_get_register(t, &saved_registers[i], i);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,7 +217,8 @@ typedef struct {
|
|||
|
||||
static int poll_target(struct target *target, bool announce);
|
||||
static int riscv011_poll(struct target *target);
|
||||
static riscv_reg_t get_register(struct target *target, int hartid, int regid);
|
||||
static int get_register(struct target *target, riscv_reg_t *value, int hartid,
|
||||
int regid);
|
||||
|
||||
/*** Utility functions. ***/
|
||||
|
||||
|
@ -1180,8 +1181,8 @@ static int update_mstatus_actual(struct target *target)
|
|||
|
||||
/* Force reading the register. In that process mstatus_actual will be
|
||||
* updated. */
|
||||
get_register(target, 0, GDB_REGNO_MSTATUS);
|
||||
return ERROR_OK;
|
||||
riscv_reg_t mstatus;
|
||||
return get_register(target, &mstatus, 0, GDB_REGNO_MSTATUS);
|
||||
}
|
||||
|
||||
/*** OpenOCD target functions. ***/
|
||||
|
@ -1285,22 +1286,22 @@ static int register_write(struct target *target, unsigned int number,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static riscv_reg_t get_register(struct target *target, int hartid, int regid)
|
||||
static int get_register(struct target *target, riscv_reg_t *value, int hartid,
|
||||
int regid)
|
||||
{
|
||||
assert(hartid == 0);
|
||||
riscv011_info_t *info = get_info(target);
|
||||
|
||||
maybe_write_tselect(target);
|
||||
riscv_reg_t value = ~0;
|
||||
|
||||
if (regid <= GDB_REGNO_XPR31) {
|
||||
value = reg_cache_get(target, regid);
|
||||
*value = reg_cache_get(target, regid);
|
||||
} else if (regid == GDB_REGNO_PC) {
|
||||
value = info->dpc;
|
||||
*value = info->dpc;
|
||||
} else if (regid >= GDB_REGNO_FPR0 && regid <= GDB_REGNO_FPR31) {
|
||||
int result = update_mstatus_actual(target);
|
||||
if (result != ERROR_OK)
|
||||
return ~0;
|
||||
return result;
|
||||
unsigned i = 0;
|
||||
if ((info->mstatus_actual & MSTATUS_FS) == 0) {
|
||||
info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1);
|
||||
|
@ -1316,17 +1317,19 @@ static riscv_reg_t get_register(struct target *target, int hartid, int regid)
|
|||
cache_set_jump(target, i++);
|
||||
|
||||
if (cache_write(target, 4, true) != ERROR_OK)
|
||||
return ~0;
|
||||
return ERROR_FAIL;
|
||||
} else if (regid == GDB_REGNO_PRIV) {
|
||||
value = get_field(info->dcsr, DCSR_PRV);
|
||||
} else if (register_read(target, &value, regid) != ERROR_OK) {
|
||||
value = ~0;
|
||||
*value = get_field(info->dcsr, DCSR_PRV);
|
||||
} else {
|
||||
int result = register_read(target, value, regid);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (regid == GDB_REGNO_MSTATUS)
|
||||
target->reg_cache->reg_list[regid].valid = true;
|
||||
|
||||
return value;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int set_register(struct target *target, int hartid, int regid,
|
||||
|
|
|
@ -30,20 +30,21 @@
|
|||
#define DMI_DATA1 (DMI_DATA0 + 1)
|
||||
#define DMI_PROGBUF1 (DMI_PROGBUF0 + 1)
|
||||
|
||||
static void riscv013_on_step_or_resume(struct target *target, bool step);
|
||||
static int riscv013_on_step_or_resume(struct target *target, bool step);
|
||||
static int riscv013_step_or_resume_current_hart(struct target *target, bool step);
|
||||
static void riscv013_clear_abstract_error(struct target *target);
|
||||
|
||||
/* Implementations of the functions in riscv_info_t. */
|
||||
static riscv_reg_t riscv013_get_register(struct target *target, int hartid, int regid);
|
||||
static int riscv013_get_register(struct target *target,
|
||||
riscv_reg_t *value, int hid, int rid);
|
||||
static int riscv013_set_register(struct target *target, int hartid, int regid, uint64_t value);
|
||||
static void riscv013_select_current_hart(struct target *target);
|
||||
static int riscv013_halt_current_hart(struct target *target);
|
||||
static int riscv013_resume_current_hart(struct target *target);
|
||||
static int riscv013_step_current_hart(struct target *target);
|
||||
static void riscv013_on_halt(struct target *target);
|
||||
static void riscv013_on_step(struct target *target);
|
||||
static void riscv013_on_resume(struct target *target);
|
||||
static int riscv013_on_halt(struct target *target);
|
||||
static int riscv013_on_step(struct target *target);
|
||||
static int riscv013_on_resume(struct target *target);
|
||||
static bool riscv013_is_halted(struct target *target);
|
||||
static enum riscv_halt_reason riscv013_halt_reason(struct target *target);
|
||||
static int riscv013_write_debug_buffer(struct target *target, unsigned index,
|
||||
|
@ -1002,8 +1003,15 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
|||
|
||||
/* Write program to move data into s0. */
|
||||
|
||||
uint64_t mstatus;
|
||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||
/* TODO: Possibly set F in mstatus. */
|
||||
if (register_read_direct(target, &mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if ((mstatus & MSTATUS_FS) == 0)
|
||||
if (register_write_direct(target, GDB_REGNO_MSTATUS,
|
||||
set_field(mstatus, MSTATUS_FS, 1)) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) {
|
||||
/* There are no instructions to move all the bits from a
|
||||
* register, so we need to use some scratch RAM. */
|
||||
|
@ -1041,6 +1049,11 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
|
||||
(mstatus & MSTATUS_FS) == 0)
|
||||
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* Restore S0. */
|
||||
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
@ -1855,36 +1868,37 @@ struct target_type riscv013_target = {
|
|||
};
|
||||
|
||||
/*** 0.13-specific implementations of various RISC-V helper functions. ***/
|
||||
static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid)
|
||||
static int riscv013_get_register(struct target *target,
|
||||
riscv_reg_t *value, int hid, int rid)
|
||||
{
|
||||
LOG_DEBUG("reading register %s on hart %d", gdb_regno_name(rid), hid);
|
||||
|
||||
riscv_set_current_hartid(target, hid);
|
||||
|
||||
uint64_t out;
|
||||
riscv013_info_t *info = get_info(target);
|
||||
|
||||
int result = ERROR_OK;
|
||||
if (rid <= GDB_REGNO_XPR31) {
|
||||
register_read_direct(target, &out, rid);
|
||||
result = register_read_direct(target, value, rid);
|
||||
} else if (rid == GDB_REGNO_PC) {
|
||||
register_read_direct(target, &out, GDB_REGNO_DPC);
|
||||
LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, out);
|
||||
result = register_read_direct(target, value, GDB_REGNO_DPC);
|
||||
LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value);
|
||||
} else if (rid == GDB_REGNO_PRIV) {
|
||||
uint64_t dcsr;
|
||||
register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
|
||||
buf_set_u64((unsigned char *)&out, 0, 8, get_field(dcsr, CSR_DCSR_PRV));
|
||||
result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
|
||||
buf_set_u64((unsigned char *)value, 0, 8, get_field(dcsr, CSR_DCSR_PRV));
|
||||
} else {
|
||||
int result = register_read_direct(target, &out, rid);
|
||||
result = register_read_direct(target, value, rid);
|
||||
if (result != ERROR_OK) {
|
||||
LOG_ERROR("Unable to read register %d", rid);
|
||||
out = -1;
|
||||
*value = -1;
|
||||
}
|
||||
|
||||
if (rid == GDB_REGNO_MSTATUS)
|
||||
info->mstatus_actual = out;
|
||||
info->mstatus_actual = *value;
|
||||
}
|
||||
|
||||
return out;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int riscv013_set_register(struct target *target, int hid, int rid, uint64_t value)
|
||||
|
@ -1969,18 +1983,19 @@ static int riscv013_step_current_hart(struct target *target)
|
|||
return riscv013_step_or_resume_current_hart(target, true);
|
||||
}
|
||||
|
||||
static void riscv013_on_resume(struct target *target)
|
||||
static int riscv013_on_resume(struct target *target)
|
||||
{
|
||||
return riscv013_on_step_or_resume(target, false);
|
||||
}
|
||||
|
||||
static void riscv013_on_step(struct target *target)
|
||||
static int riscv013_on_step(struct target *target)
|
||||
{
|
||||
return riscv013_on_step_or_resume(target, true);
|
||||
}
|
||||
|
||||
static void riscv013_on_halt(struct target *target)
|
||||
static int riscv013_on_halt(struct target *target)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static bool riscv013_is_halted(struct target *target)
|
||||
|
@ -1995,7 +2010,11 @@ static bool riscv013_is_halted(struct target *target)
|
|||
|
||||
static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
|
||||
{
|
||||
uint64_t dcsr = riscv_get_register(target, GDB_REGNO_DCSR);
|
||||
riscv_reg_t dcsr;
|
||||
int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
|
||||
if (result != ERROR_OK)
|
||||
return RISCV_HALT_UNKNOWN;
|
||||
|
||||
switch (get_field(dcsr, CSR_DCSR_CAUSE)) {
|
||||
case CSR_DCSR_CAUSE_SWBP:
|
||||
case CSR_DCSR_CAUSE_TRIGGER:
|
||||
|
@ -2064,7 +2083,7 @@ int riscv013_dmi_write_u64_bits(struct target *target)
|
|||
}
|
||||
|
||||
/* Helper Functions. */
|
||||
static void riscv013_on_step_or_resume(struct target *target, bool step)
|
||||
static int riscv013_on_step_or_resume(struct target *target, bool step)
|
||||
{
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
|
@ -2073,12 +2092,15 @@ static void riscv013_on_step_or_resume(struct target *target, bool step)
|
|||
LOG_ERROR("Unable to execute fence.i");
|
||||
|
||||
/* We want to twiddle some bits in the debug CSR so debugging works. */
|
||||
uint64_t dcsr = riscv_get_register(target, GDB_REGNO_DCSR);
|
||||
riscv_reg_t dcsr;
|
||||
int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
|
||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, 1);
|
||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, 1);
|
||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, 1);
|
||||
riscv_set_register(target, GDB_REGNO_DCSR, dcsr);
|
||||
return riscv_set_register(target, GDB_REGNO_DCSR, dcsr);
|
||||
}
|
||||
|
||||
static int riscv013_step_or_resume_current_hart(struct target *target, bool step)
|
||||
|
|
|
@ -320,8 +320,10 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid,
|
|||
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1);
|
||||
|
||||
riscv_reg_t tdata1_rb = riscv_get_register_on_hart(target, hartid,
|
||||
GDB_REGNO_TDATA1);
|
||||
riscv_reg_t tdata1_rb;
|
||||
if (riscv_get_register_on_hart(target, &tdata1_rb, hartid,
|
||||
GDB_REGNO_TDATA1) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
|
||||
|
||||
if (tdata1 != tdata1_rb) {
|
||||
|
@ -370,7 +372,10 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid,
|
|||
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1);
|
||||
|
||||
uint64_t tdata1_rb = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TDATA1);
|
||||
uint64_t tdata1_rb;
|
||||
int result = riscv_get_register_on_hart(target, &tdata1_rb, hartid, GDB_REGNO_TDATA1);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
|
||||
|
||||
if (tdata1 != tdata1_rb) {
|
||||
|
@ -405,8 +410,10 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
|||
continue;
|
||||
if (first_hart < 0)
|
||||
first_hart = hartid;
|
||||
tselect[hartid] = riscv_get_register_on_hart(target, hartid,
|
||||
GDB_REGNO_TSELECT);
|
||||
int result = riscv_get_register_on_hart(target, &tselect[hartid],
|
||||
hartid, GDB_REGNO_TSELECT);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
assert(first_hart >= 0);
|
||||
|
||||
|
@ -417,10 +424,14 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
|||
|
||||
riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i);
|
||||
|
||||
uint64_t tdata1 = riscv_get_register_on_hart(target, first_hart, GDB_REGNO_TDATA1);
|
||||
uint64_t tdata1;
|
||||
int result = riscv_get_register_on_hart(target, &tdata1, first_hart,
|
||||
GDB_REGNO_TDATA1);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
|
||||
|
||||
int result = ERROR_OK;
|
||||
result = ERROR_OK;
|
||||
for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) {
|
||||
if (!riscv_hart_enabled(target, hartid))
|
||||
continue;
|
||||
|
@ -533,7 +544,10 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
|
|||
for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) {
|
||||
if (!riscv_hart_enabled(target, hartid))
|
||||
continue;
|
||||
riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT);
|
||||
riscv_reg_t tselect;
|
||||
int result = riscv_get_register_on_hart(target, &tselect, hartid, GDB_REGNO_TSELECT);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i);
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0);
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, tselect);
|
||||
|
@ -1553,17 +1567,20 @@ int riscv_set_register_on_hart(struct target *target, int hartid,
|
|||
return r->set_register(target, hartid, regid, value);
|
||||
}
|
||||
|
||||
riscv_reg_t riscv_get_register(struct target *target, enum gdb_regno r)
|
||||
int riscv_get_register(struct target *target, riscv_reg_t *value,
|
||||
enum gdb_regno r)
|
||||
{
|
||||
return riscv_get_register_on_hart(target, riscv_current_hartid(target), r);
|
||||
return riscv_get_register_on_hart(target, value,
|
||||
riscv_current_hartid(target), r);
|
||||
}
|
||||
|
||||
uint64_t riscv_get_register_on_hart(struct target *target, int hartid, enum gdb_regno regid)
|
||||
int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
|
||||
int hartid, enum gdb_regno regid)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
uint64_t value = r->get_register(target, hartid, regid);
|
||||
LOG_DEBUG("[%d] %s: %" PRIx64, hartid, gdb_regno_name(regid), value);
|
||||
return value;
|
||||
int result = r->get_register(target, value, hartid, regid);
|
||||
LOG_DEBUG("[%d] %s: %" PRIx64, hartid, gdb_regno_name(regid), *value);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool riscv_is_halted(struct target *target)
|
||||
|
@ -1669,22 +1686,32 @@ int riscv_enumerate_triggers(struct target *target)
|
|||
if (!riscv_hart_enabled(target, hartid))
|
||||
continue;
|
||||
|
||||
riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid,
|
||||
riscv_reg_t tselect;
|
||||
int result = riscv_get_register_on_hart(target, &tselect, hartid,
|
||||
GDB_REGNO_TSELECT);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
for (unsigned t = 0; t < RISCV_MAX_TRIGGERS; ++t) {
|
||||
r->trigger_count[hartid] = t;
|
||||
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, t);
|
||||
uint64_t tselect_rb = riscv_get_register_on_hart(target, hartid,
|
||||
uint64_t tselect_rb;
|
||||
result = riscv_get_register_on_hart(target, &tselect_rb, hartid,
|
||||
GDB_REGNO_TSELECT);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
/* Mask off the top bit, which is used as tdrmode in old
|
||||
* implementations. */
|
||||
tselect_rb &= ~(1ULL << (riscv_xlen(target)-1));
|
||||
if (tselect_rb != t)
|
||||
break;
|
||||
uint64_t tdata1 = riscv_get_register_on_hart(target, hartid,
|
||||
uint64_t tdata1;
|
||||
result = riscv_get_register_on_hart(target, &tdata1, hartid,
|
||||
GDB_REGNO_TDATA1);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
|
||||
switch (type) {
|
||||
case 1:
|
||||
|
@ -1760,7 +1787,10 @@ const char *gdb_regno_name(enum gdb_regno regno)
|
|||
static int register_get(struct reg *reg)
|
||||
{
|
||||
struct target *target = (struct target *) reg->arch_info;
|
||||
uint64_t value = riscv_get_register(target, reg->number);
|
||||
uint64_t value;
|
||||
int result = riscv_get_register(target, &value, reg->number);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
buf_set_u64(reg->value, 0, reg->size, value);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,8 @@ typedef struct {
|
|||
|
||||
/* Helper functions that target the various RISC-V debug spec
|
||||
* implementations. */
|
||||
riscv_reg_t (*get_register)(struct target *, int hartid, int regid);
|
||||
int (*get_register)(struct target *target,
|
||||
riscv_reg_t *value, int hid, int rid);
|
||||
int (*set_register)(struct target *, int hartid, int regid,
|
||||
uint64_t value);
|
||||
void (*select_current_hart)(struct target *);
|
||||
|
@ -96,9 +97,9 @@ typedef struct {
|
|||
int (*halt_current_hart)(struct target *);
|
||||
int (*resume_current_hart)(struct target *target);
|
||||
int (*step_current_hart)(struct target *target);
|
||||
void (*on_halt)(struct target *target);
|
||||
void (*on_resume)(struct target *target);
|
||||
void (*on_step)(struct target *target);
|
||||
int (*on_halt)(struct target *target);
|
||||
int (*on_resume)(struct target *target);
|
||||
int (*on_step)(struct target *target);
|
||||
enum riscv_halt_reason (*halt_reason)(struct target *target);
|
||||
int (*write_debug_buffer)(struct target *target, unsigned index,
|
||||
riscv_insn_t d);
|
||||
|
@ -205,8 +206,10 @@ bool riscv_has_register(struct target *target, int hartid, int regid);
|
|||
* are zero extended to 64 bits. */
|
||||
int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
|
||||
int riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
|
||||
riscv_reg_t riscv_get_register(struct target *target, enum gdb_regno i);
|
||||
riscv_reg_t riscv_get_register_on_hart(struct target *target, int hid, enum gdb_regno rid);
|
||||
int riscv_get_register(struct target *target, riscv_reg_t *value,
|
||||
enum gdb_regno r);
|
||||
int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
|
||||
int hartid, enum gdb_regno regid);
|
||||
|
||||
/* Checks the state of the current hart -- "is_halted" checks the actual
|
||||
* on-device register. */
|
||||
|
|
Loading…
Reference in New Issue