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)
793799static 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
0 commit comments