@@ -145,6 +145,60 @@ typedef struct {
145145 struct target * target ;
146146} target_list_t ;
147147
148+ struct ac_cache {
149+ uint32_t * commands ;
150+ size_t size ;
151+ };
152+
153+ static int ac_cache_elem_comparator (const void * lhs , const void * rhs )
154+ {
155+ return * (const uint32_t * )rhs - * (const uint32_t * )lhs ;
156+ }
157+
158+ static struct ac_cache ac_cache_construct (void )
159+ {
160+ struct ac_cache cache = {
161+ cache .commands = NULL ,
162+ cache .size = 0 ,
163+ };
164+ return cache ;
165+ }
166+
167+ static void ac_cache_free (struct ac_cache * cache )
168+ {
169+ free (cache -> commands );
170+ cache -> commands = NULL ;
171+ cache -> size = 0 ;
172+ }
173+
174+ static void ac_cache_insert (struct ac_cache * cache , uint32_t command )
175+ {
176+ assert (cache );
177+
178+ size_t old_size = cache -> size ;
179+ size_t new_size = old_size + 1 ;
180+ size_t entry_size = sizeof (* cache -> commands );
181+
182+ uint32_t * commands = realloc (cache -> commands , new_size * entry_size );
183+ if (!commands ) {
184+ LOG_ERROR ("Reallocation to %zu bytes failed" , new_size );
185+ return ;
186+ }
187+
188+ commands [old_size ] = command ;
189+ cache -> commands = commands ;
190+ cache -> size = new_size ;
191+
192+ qsort (cache -> commands , cache -> size , entry_size ,
193+ ac_cache_elem_comparator );
194+ }
195+
196+ static bool ac_cache_contains (const struct ac_cache * cache , uint32_t command )
197+ {
198+ return bsearch (& command , cache -> commands , cache -> size ,
199+ sizeof (* cache -> commands ), ac_cache_elem_comparator );
200+ }
201+
148202typedef struct {
149203 /* The indexed used to address this hart in its DM. */
150204 unsigned int index ;
@@ -175,12 +229,7 @@ typedef struct {
175229 */
176230 struct riscv_scan_delays learned_delays ;
177231
178- bool abstract_read_csr_supported ;
179- bool abstract_write_csr_supported ;
180- bool abstract_read_fpr_supported ;
181- bool abstract_write_fpr_supported ;
182-
183- yes_no_maybe_t has_aampostincrement ;
232+ struct ac_cache ac_not_supported_cache ;
184233
185234 /* Some fields from hartinfo. */
186235 uint8_t datasize ;
@@ -685,6 +734,11 @@ int riscv013_execute_abstract_command(struct target *target, uint32_t command,
685734 res = abstract_cmd_batch_check_and_clear_cmderr (target , batch ,
686735 abstractcs_read_key , cmderr );
687736cleanup :
737+ if (res != ERROR_OK && * cmderr == CMDERR_NOT_SUPPORTED ) {
738+ LOG_TARGET_DEBUG (target , "Command 0x%" PRIx32
739+ "is cached as not supported, bailing out" , command );
740+ ac_cache_insert (& get_info (target )-> ac_not_supported_cache , command );
741+ }
688742 riscv_batch_free (batch );
689743 return res ;
690744}
@@ -834,33 +888,22 @@ static int register_read_abstract_with_size(struct target *target,
834888{
835889 RISCV013_INFO (info );
836890
837- if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
838- !info -> abstract_read_fpr_supported )
839- return ERROR_FAIL ;
840- if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 &&
841- !info -> abstract_read_csr_supported )
842- return ERROR_FAIL ;
843891 /* The spec doesn't define abstract register numbers for vector registers. */
844892 if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31 )
845893 return ERROR_FAIL ;
846894
847895 uint32_t command = riscv013_access_register_command (target , number , size ,
848896 AC_ACCESS_REGISTER_TRANSFER );
897+ if (ac_cache_contains (& info -> ac_not_supported_cache , command )) {
898+ LOG_TARGET_DEBUG (target , "Command is cached as not supported, bailing out" );
899+ LOG_DEBUG_REG (target , AC_ACCESS_REGISTER , command );
900+ return ERROR_FAIL ;
901+ }
849902
850903 uint32_t cmderr ;
851904 int result = riscv013_execute_abstract_command (target , command , & cmderr );
852- if (result != ERROR_OK ) {
853- if (cmderr == CMDERR_NOT_SUPPORTED ) {
854- if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 ) {
855- info -> abstract_read_fpr_supported = false;
856- LOG_TARGET_INFO (target , "Disabling abstract command reads from FPRs." );
857- } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 ) {
858- info -> abstract_read_csr_supported = false;
859- LOG_TARGET_INFO (target , "Disabling abstract command reads from CSRs." );
860- }
861- }
905+ if (result != ERROR_OK )
862906 return result ;
863- }
864907
865908 if (value )
866909 return read_abstract_arg (target , value , 0 , size );
@@ -885,17 +928,16 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
885928 if (!dm )
886929 return ERROR_FAIL ;
887930
888- if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
889- !info -> abstract_write_fpr_supported )
890- return ERROR_FAIL ;
891- if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 &&
892- !info -> abstract_write_csr_supported )
893- return ERROR_FAIL ;
894-
895931 const unsigned int size_bits = register_size (target , number );
896932 const uint32_t command = riscv013_access_register_command (target , number , size_bits ,
897933 AC_ACCESS_REGISTER_TRANSFER |
898934 AC_ACCESS_REGISTER_WRITE );
935+ if (ac_cache_contains (& info -> ac_not_supported_cache , command )) {
936+ LOG_TARGET_DEBUG (target , "Command is cached as not supported, bailing out" );
937+ LOG_DEBUG_REG (target , AC_ACCESS_REGISTER , command );
938+ return ERROR_FAIL ;
939+ }
940+
899941 LOG_DEBUG_REG (target , AC_ACCESS_REGISTER , command );
900942 assert (size_bits % 32 == 0 );
901943 const unsigned int size_in_words = size_bits / 32 ;
@@ -916,16 +958,10 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
916958 res = abstract_cmd_batch_check_and_clear_cmderr (target , batch ,
917959 abstractcs_read_key , & cmderr );
918960
919- if (res != ERROR_OK ) {
920- if (cmderr == CMDERR_NOT_SUPPORTED ) {
921- if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 ) {
922- info -> abstract_write_fpr_supported = false;
923- LOG_TARGET_INFO (target , "Disabling abstract command writes to FPRs." );
924- } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 ) {
925- info -> abstract_write_csr_supported = false;
926- LOG_TARGET_INFO (target , "Disabling abstract command writes to CSRs." );
927- }
928- }
961+ if (res != ERROR_OK && cmderr == CMDERR_NOT_SUPPORTED ) {
962+ LOG_TARGET_DEBUG (target , "Caching the command as not supported" );
963+ LOG_DEBUG_REG (target , AC_ACCESS_REGISTER , command );
964+ ac_cache_insert (& info -> ac_not_supported_cache , command );
929965 }
930966cleanup :
931967 riscv_batch_free (batch );
@@ -1709,6 +1745,10 @@ static void deinit_target(struct target *target)
17091745 if (!info )
17101746 return ;
17111747
1748+ riscv013_info_t * vsinfo = info -> version_specific ;
1749+ if (vsinfo )
1750+ ac_cache_free (& vsinfo -> ac_not_supported_cache );
1751+
17121752 riscv013_dm_free (target );
17131753
17141754 free (info -> version_specific );
@@ -2819,17 +2859,7 @@ static int init_target(struct command_context *cmd_ctx,
28192859 info -> progbufsize = -1 ;
28202860 reset_learned_delays (target );
28212861
2822- /* Assume all these abstract commands are supported until we learn
2823- * otherwise.
2824- * TODO: The spec allows eg. one CSR to be able to be accessed abstractly
2825- * while another one isn't. We don't track that this closely here, but in
2826- * the future we probably should. */
2827- info -> abstract_read_csr_supported = true;
2828- info -> abstract_write_csr_supported = true;
2829- info -> abstract_read_fpr_supported = true;
2830- info -> abstract_write_fpr_supported = true;
2831-
2832- info -> has_aampostincrement = YNM_MAYBE ;
2862+ info -> ac_not_supported_cache = ac_cache_construct ();
28332863
28342864 return ERROR_OK ;
28352865}
@@ -3720,15 +3750,19 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
37203750 assert (riscv_mem_access_is_read (args ));
37213751
37223752 RISCV013_INFO (info );
3723- bool use_aampostincrement = info -> has_aampostincrement != YNM_NO ;
3724-
37253753 memset (args .read_buffer , 0 , args .count * args .size );
37263754
37273755 /* Convert the size (bytes) to width (bits) */
37283756 unsigned int width = args .size << 3 ;
37293757
37303758 /* Create the command (physical address, postincrement, read) */
3731- uint32_t command = access_memory_command (target , false, width , use_aampostincrement , false);
3759+ uint32_t command = access_memory_command (target , false, width ,
3760+ /* postincrement = */ true, /* is_write= */ false);
3761+ bool use_aampostincrement =
3762+ !ac_cache_contains (& info -> ac_not_supported_cache , command );
3763+ if (!use_aampostincrement )
3764+ command = access_memory_command (target , false, width ,
3765+ /* postincrement = */ false, /* is_write= */ false);
37323766
37333767 /* Execute the reads */
37343768 uint8_t * p = args .read_buffer ;
@@ -3749,33 +3783,14 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
37493783 /* Execute the command */
37503784 uint32_t cmderr ;
37513785 result = riscv013_execute_abstract_command (target , command , & cmderr );
3752-
3753- /* TODO: we need to modify error handling here. */
3754- /* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
3755- if (info -> has_aampostincrement == YNM_MAYBE ) {
3756- if (result == ERROR_OK ) {
3757- /* Safety: double-check that the address was really auto-incremented */
3758- riscv_reg_t new_address ;
3759- result = read_abstract_arg (target , & new_address , 1 , riscv_xlen (target ));
3760- if (result != ERROR_OK )
3761- return mem_access_result (MEM_ACCESS_FAILED_DM_ACCESS_FAILED );
3762-
3763- if (new_address == args .address + args .size ) {
3764- LOG_TARGET_DEBUG (target , "aampostincrement is supported on this target." );
3765- info -> has_aampostincrement = YNM_YES ;
3766- } else {
3767- LOG_TARGET_WARNING (target , "Buggy aampostincrement! Address not incremented correctly." );
3768- info -> has_aampostincrement = YNM_NO ;
3769- }
3770- } else {
3771- /* Try the same access but with postincrement disabled. */
3772- command = access_memory_command (target , false, width , false, false);
3773- result = riscv013_execute_abstract_command (target , command , & cmderr );
3774- if (result == ERROR_OK ) {
3775- LOG_TARGET_DEBUG (target , "aampostincrement is not supported on this target." );
3776- info -> has_aampostincrement = YNM_NO ;
3777- }
3778- }
3786+ if (use_aampostincrement && result != ERROR_OK &&
3787+ cmderr == CMDERR_NOT_SUPPORTED ) {
3788+ LOG_TARGET_DEBUG (target , "aampostincrement is not supported on this target." );
3789+ use_aampostincrement = false;
3790+
3791+ /* Try the same access but with postincrement disabled. */
3792+ command = access_memory_command (target , false, width , false, false);
3793+ result = riscv013_execute_abstract_command (target , command , & cmderr );
37793794 }
37803795
37813796 /* TODO:
@@ -3791,7 +3806,7 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
37913806 return mem_access_result (MEM_ACCESS_FAILED_DM_ACCESS_FAILED );
37923807 buf_set_u64 (p , 0 , 8 * args .size , value );
37933808
3794- if (info -> has_aampostincrement == YNM_YES )
3809+ if (use_aampostincrement )
37953810 updateaddr = false;
37963811 p += args .size ;
37973812 }
@@ -3811,13 +3826,18 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
38113826
38123827 RISCV013_INFO (info );
38133828 int result = ERROR_OK ;
3814- bool use_aampostincrement = info -> has_aampostincrement != YNM_NO ;
38153829
38163830 /* Convert the size (bytes) to width (bits) */
38173831 unsigned int width = args .size << 3 ;
38183832
38193833 /* Create the command (physical address, postincrement, write) */
3820- uint32_t command = access_memory_command (target , false, width , use_aampostincrement , true);
3834+ uint32_t command = access_memory_command (target , false, width ,
3835+ /* postincrement = */ true, /* is_write = */ true);
3836+ bool use_aampostincrement =
3837+ !ac_cache_contains (& info -> ac_not_supported_cache , command );
3838+ if (!use_aampostincrement )
3839+ command = access_memory_command (target , false, width ,
3840+ /* postincrement = */ false, /* is_write= */ false);
38213841
38223842 /* Execute the writes */
38233843 const uint8_t * p = args .write_buffer ;
@@ -3844,33 +3864,14 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
38443864 /* Execute the command */
38453865 uint32_t cmderr ;
38463866 result = riscv013_execute_abstract_command (target , command , & cmderr );
3847-
3848- /* TODO: we need to modify error handling here. */
3849- /* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
3850- if (info -> has_aampostincrement == YNM_MAYBE ) {
3851- if (result == ERROR_OK ) {
3852- /* Safety: double-check that the address was really auto-incremented */
3853- riscv_reg_t new_address ;
3854- result = read_abstract_arg (target , & new_address , 1 , riscv_xlen (target ));
3855- if (result != ERROR_OK )
3856- return mem_access_result (MEM_ACCESS_FAILED_DM_ACCESS_FAILED );
3857-
3858- if (new_address == args .address + args .size ) {
3859- LOG_TARGET_DEBUG (target , "aampostincrement is supported on this target." );
3860- info -> has_aampostincrement = YNM_YES ;
3861- } else {
3862- LOG_TARGET_WARNING (target , "Buggy aampostincrement! Address not incremented correctly." );
3863- info -> has_aampostincrement = YNM_NO ;
3864- }
3865- } else {
3866- /* Try the same access but with postincrement disabled. */
3867- command = access_memory_command (target , false, width , false, true);
3868- result = riscv013_execute_abstract_command (target , command , & cmderr );
3869- if (result == ERROR_OK ) {
3870- LOG_TARGET_DEBUG (target , "aampostincrement is not supported on this target." );
3871- info -> has_aampostincrement = YNM_NO ;
3872- }
3873- }
3867+ if (use_aampostincrement && result != ERROR_OK &&
3868+ cmderr == CMDERR_NOT_SUPPORTED ) {
3869+ LOG_TARGET_DEBUG (target , "aampostincrement is not supported on this target." );
3870+ use_aampostincrement = false;
3871+
3872+ /* Try the same access but with postincrement disabled. */
3873+ command = access_memory_command (target , false, width , false, true);
3874+ result = riscv013_execute_abstract_command (target , command , & cmderr );
38743875 }
38753876
38763877 /* TODO:
@@ -3879,7 +3880,7 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
38793880 if (result != ERROR_OK )
38803881 return mem_access_result (MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR );
38813882
3882- if (info -> has_aampostincrement == YNM_YES )
3883+ if (use_aampostincrement )
38833884 updateaddr = false;
38843885 p += args .size ;
38853886 }
0 commit comments