Skip to content

Commit 4e2e730

Browse files
Merge pull request #68 from riscv/multicore
Testsuite now passes on multicore target
2 parents 8d79a7c + 9cd9805 commit 4e2e730

File tree

4 files changed

+89
-38
lines changed

4 files changed

+89
-38
lines changed

src/rtos/riscv_debug.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
#include "riscv_debug.h"
66
#include "target/target.h"
77
#include "target/riscv/riscv.h"
8-
#include "rtos.h"
98
#include "server/gdb_server.h"
109

11-
static int riscv_update_threads(struct rtos *rtos);
1210
static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size);
1311
static int riscv_gdb_v_packet(struct connection *connection, const char *packet, int packet_size);
1412

@@ -40,7 +38,7 @@ static int riscv_create_rtos(struct target *target)
4038
return JIM_OK;
4139
}
4240

43-
static int riscv_update_threads(struct rtos *rtos)
41+
int riscv_update_threads(struct rtos *rtos)
4442
{
4543
LOG_DEBUG("Updating the RISC-V Hart List");
4644

src/rtos/riscv_debug.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
#ifndef RTOS__RISCV_H
22
#define RTOS__RISCV_H
33

4+
#include "rtos.h"
5+
46
struct riscv_rtos {
57
/* The index into the thread list used to handle */
68
int qs_thread_info_offset;
79
};
810

11+
int riscv_update_threads(struct rtos *rtos);
12+
913
#endif

src/target/riscv/riscv-013.c

Lines changed: 81 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "target/breakpoints.h"
2121
#include "helper/time_support.h"
2222
#include "riscv.h"
23+
#include "rtos/riscv_debug.h"
2324
#include "debug_defines.h"
2425
#include "rtos/rtos.h"
2526
#include "program.h"
@@ -578,6 +579,10 @@ static int register_write_direct(struct target *target, unsigned number,
578579
uint64_t value)
579580
{
580581
struct riscv_program program;
582+
583+
LOG_DEBUG("[%d] reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target),
584+
number, value);
585+
581586
riscv_program_init(&program, target);
582587

583588
riscv_addr_t input = riscv_program_alloc_d(&program);
@@ -640,7 +645,8 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
640645
*value = 0;
641646
*value |= ((uint64_t)(riscv_program_read_ram(&program, output + 4))) << 32;
642647
*value |= riscv_program_read_ram(&program, output);
643-
LOG_DEBUG("register 0x%x = 0x%" PRIx64, number, *value);
648+
LOG_DEBUG("[%d] reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target),
649+
number, *value);
644650
return ERROR_OK;
645651
}
646652

@@ -793,6 +799,14 @@ static void deinit_target(struct target *target)
793799
static int add_trigger(struct target *target, struct trigger *trigger)
794800
{
795801
riscv013_info_t *info = get_info(target);
802+
803+
// While we're using threads to fake harts, both gdb and OpenOCD assume
804+
// that hardware breakpoints are shared among threads. Make this true by
805+
// setting the same breakpoints on all harts.
806+
807+
// Assume that all triggers are configured the same on all harts.
808+
riscv_set_current_hartid(target, 0);
809+
796810
maybe_read_tselect(target);
797811

798812
int i;
@@ -816,42 +830,59 @@ static int add_trigger(struct target *target, struct trigger *trigger)
816830
continue;
817831
}
818832

819-
// address/data match trigger
820-
tdata1 |= MCONTROL_DMODE(riscv_xlen(target));
821-
tdata1 = set_field(tdata1, MCONTROL_ACTION,
822-
MCONTROL_ACTION_DEBUG_MODE);
823-
tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL);
824-
tdata1 |= MCONTROL_M;
825-
if (info->misa & (1 << ('H' - 'A')))
826-
tdata1 |= MCONTROL_H;
827-
if (info->misa & (1 << ('S' - 'A')))
828-
tdata1 |= MCONTROL_S;
829-
if (info->misa & (1 << ('U' - 'A')))
830-
tdata1 |= MCONTROL_U;
831-
832-
if (trigger->execute)
833-
tdata1 |= MCONTROL_EXECUTE;
834-
if (trigger->read)
835-
tdata1 |= MCONTROL_LOAD;
836-
if (trigger->write)
837-
tdata1 |= MCONTROL_STORE;
838-
839-
register_write_direct(target, GDB_REGNO_TDATA1, tdata1);
840-
841833
uint64_t tdata1_rb;
842-
register_read_direct(target, &tdata1_rb, GDB_REGNO_TDATA1);
843-
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
834+
for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) {
835+
riscv_set_current_hartid(target, hartid);
836+
837+
if (hartid > 0) {
838+
register_write_direct(target, GDB_REGNO_TSELECT, i);
839+
}
840+
841+
// address/data match trigger
842+
tdata1 |= MCONTROL_DMODE(riscv_xlen(target));
843+
tdata1 = set_field(tdata1, MCONTROL_ACTION,
844+
MCONTROL_ACTION_DEBUG_MODE);
845+
tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL);
846+
tdata1 |= MCONTROL_M;
847+
if (info->misa & (1 << ('H' - 'A')))
848+
tdata1 |= MCONTROL_H;
849+
if (info->misa & (1 << ('S' - 'A')))
850+
tdata1 |= MCONTROL_S;
851+
if (info->misa & (1 << ('U' - 'A')))
852+
tdata1 |= MCONTROL_U;
853+
854+
if (trigger->execute)
855+
tdata1 |= MCONTROL_EXECUTE;
856+
if (trigger->read)
857+
tdata1 |= MCONTROL_LOAD;
858+
if (trigger->write)
859+
tdata1 |= MCONTROL_STORE;
860+
861+
register_write_direct(target, GDB_REGNO_TDATA1, tdata1);
862+
863+
register_read_direct(target, &tdata1_rb, GDB_REGNO_TDATA1);
864+
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
865+
866+
if (tdata1 != tdata1_rb) {
867+
LOG_DEBUG("Trigger %d doesn't support what we need; After writing 0x%"
868+
PRIx64 " to tdata1 it contains 0x%" PRIx64,
869+
i, tdata1, tdata1_rb);
870+
register_write_direct(target, GDB_REGNO_TDATA1, 0);
871+
if (hartid > 0) {
872+
LOG_ERROR("Setting hardware breakpoints requires "
873+
"homogeneous harts.");
874+
return ERROR_FAIL;
875+
}
876+
break;
877+
}
878+
879+
register_write_direct(target, GDB_REGNO_TDATA2, trigger->address);
880+
}
844881

845882
if (tdata1 != tdata1_rb) {
846-
LOG_DEBUG("Trigger %d doesn't support what we need; After writing 0x%"
847-
PRIx64 " to tdata1 it contains 0x%" PRIx64,
848-
i, tdata1, tdata1_rb);
849-
register_write_direct(target, GDB_REGNO_TDATA1, 0);
850883
continue;
851884
}
852885

853-
register_write_direct(target, GDB_REGNO_TDATA2, trigger->address);
854-
855886
LOG_DEBUG("Using resource %d for bp %d", i,
856887
trigger->unique_id);
857888
info->trigger_unique_id[i] = trigger->unique_id;
@@ -869,6 +900,9 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
869900
{
870901
riscv013_info_t *info = get_info(target);
871902

903+
// Assume that all triggers are configured the same on all harts.
904+
riscv_set_current_hartid(target, 0);
905+
872906
maybe_read_tselect(target);
873907

874908
int i;
@@ -883,8 +917,11 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
883917
return ERROR_FAIL;
884918
}
885919
LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id);
886-
register_write_direct(target, GDB_REGNO_TSELECT, i);
887-
register_write_direct(target, GDB_REGNO_TDATA1, 0);
920+
for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) {
921+
riscv_set_current_hartid(target, hartid);
922+
register_write_direct(target, GDB_REGNO_TSELECT, i);
923+
register_write_direct(target, GDB_REGNO_TDATA1, 0);
924+
}
888925
info->trigger_unique_id[i] = -1;
889926

890927
return ERROR_OK;
@@ -1192,14 +1229,19 @@ static int examine(struct target *target)
11921229
riscv_resume_all_harts(target);
11931230
target_set_examined(target);
11941231

1232+
if (target->rtos) {
1233+
riscv_update_threads(target->rtos);
1234+
}
1235+
11951236
// Some regression suites rely on seeing 'Examined RISC-V core' to know
11961237
// when they can connect with gdb/telnet.
11971238
// We will need to update those suites if we want to change that text.
11981239
LOG_INFO("Examined RISC-V core; found %d harts",
11991240
riscv_count_harts(target));
12001241
for (int i = 0; i < riscv_count_harts(target); ++i) {
1201-
LOG_INFO(" hart %d: XLEN=%d, program buffer at 0x%" PRIx64, i,
1202-
r->xlen[i], r->debug_buffer_addr[i]);
1242+
LOG_INFO(" hart %d: XLEN=%d, program buffer at 0x%" PRIx64
1243+
", %d triggers", i, r->xlen[i], r->debug_buffer_addr[i],
1244+
r->trigger_count[i]);
12031245
}
12041246
return ERROR_OK;
12051247
}
@@ -1279,6 +1321,8 @@ static int read_memory(struct target *target, target_addr_t address,
12791321
size, address);
12801322

12811323
select_dmi(target);
1324+
/* There was a bug in the memory system and only accesses from hart 0 actually
1325+
* worked correctly. This should be obselete now. -palmer */
12821326
riscv_set_current_hartid(target, 0);
12831327

12841328
/* This program uses two temporary registers. A word of data and the
@@ -1475,6 +1519,8 @@ static int write_memory(struct target *target, target_addr_t address,
14751519
LOG_DEBUG("writing %d words of %d bytes to 0x%08lx", count, size, (long)address);
14761520

14771521
select_dmi(target);
1522+
/* There was a bug in the memory system and only accesses from hart 0 actually
1523+
* worked correctly. This should be obselete now. -palmer */
14781524
riscv_set_current_hartid(target, 0);
14791525

14801526
/* This program uses two temporary registers. A word of data and the

src/target/riscv/riscv.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,9 @@ bool riscv_rtos_enabled(const struct target *target)
10121012
void riscv_set_current_hartid(struct target *target, int hartid)
10131013
{
10141014
RISCV_INFO(r);
1015+
if (!r->select_current_hart)
1016+
return;
1017+
10151018
int previous_hartid = riscv_current_hartid(target);
10161019
r->current_hartid = hartid;
10171020
assert(riscv_rtos_enabled(target) || target->coreid == hartid);

0 commit comments

Comments
 (0)