Skip to content

Commit 13ade68

Browse files
committed
target/riscv: implement abstract command cache
Implemented cache of unsupported abstract commands. It's purpose is to replace set of caching variables to one. So this commit provides one ac_not_supported_cache instead of abstract_read_csr_supported, abstract_write_csr_supported, abstract_read_fpr_supported, abstract_write_fpr_supported, has_aampostincrement. Dropped check for buggy aampostincrement Fixes #1232 Change-Id: I75cae1481841f2cd0393d6cc80f0d913fbe34294 Signed-off-by: Farid Khaydari <[email protected]>
1 parent fa7e235 commit 13ade68

File tree

1 file changed

+137
-119
lines changed

1 file changed

+137
-119
lines changed

src/target/riscv/riscv-013.c

Lines changed: 137 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
148202
typedef 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;
@@ -651,6 +700,24 @@ static int abstract_cmd_batch_check_and_clear_cmderr(struct target *target,
651700
return res;
652701
}
653702

703+
static void mark_command_as_unsupported(struct target *target, uint32_t command)
704+
{
705+
enum riscv_debug_reg_ordinal val2cmdtype[4] = {
706+
AC_ACCESS_REGISTER_ORDINAL,
707+
AC_QUICK_ACCESS_ORDINAL,
708+
AC_ACCESS_MEMORY_ORDINAL,
709+
0,
710+
};
711+
712+
enum riscv_debug_reg_ordinal cmdtype =
713+
val2cmdtype[get_field(command, DM_COMMAND_CMDTYPE)];
714+
715+
LOG_TARGET_DEBUG(target, "Caching the abstract "
716+
"command 0x%" PRIx32 " as not supported", command);
717+
log_debug_reg(target, cmdtype, command, __FILE__, __LINE__, __func__);
718+
ac_cache_insert(&get_info(target)->ac_not_supported_cache, command);
719+
}
720+
654721
int riscv013_execute_abstract_command(struct target *target, uint32_t command,
655722
uint32_t *cmderr)
656723
{
@@ -684,6 +751,9 @@ int riscv013_execute_abstract_command(struct target *target, uint32_t command,
684751

685752
res = abstract_cmd_batch_check_and_clear_cmderr(target, batch,
686753
abstractcs_read_key, cmderr);
754+
if (res != ERROR_OK && *cmderr == CMDERR_NOT_SUPPORTED)
755+
mark_command_as_unsupported(target, command);
756+
687757
cleanup:
688758
riscv_batch_free(batch);
689759
return res;
@@ -829,38 +899,40 @@ uint32_t riscv013_access_register_command(struct target *target, uint32_t number
829899
return command;
830900
}
831901

902+
static bool is_command_unsupported(struct target *target, uint32_t command)
903+
{
904+
enum riscv_debug_reg_ordinal val2cmdtype[4] = {
905+
AC_ACCESS_REGISTER_ORDINAL,
906+
AC_QUICK_ACCESS_ORDINAL,
907+
AC_ACCESS_MEMORY_ORDINAL,
908+
0,
909+
};
910+
911+
enum riscv_debug_reg_ordinal cmdtype =
912+
val2cmdtype[get_field(command, DM_COMMAND_CMDTYPE)];
913+
914+
LOG_TARGET_DEBUG(target, "Abstract command 0x%"
915+
PRIx32 " is cached as not supported", command);
916+
log_debug_reg(target, cmdtype, command, __FILE__, __LINE__, __func__);
917+
return ac_cache_contains(&get_info(target)->ac_not_supported_cache, command);
918+
}
919+
832920
static int register_read_abstract_with_size(struct target *target,
833921
riscv_reg_t *value, enum gdb_regno number, unsigned int size)
834922
{
835-
RISCV013_INFO(info);
836-
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;
843923
/* The spec doesn't define abstract register numbers for vector registers. */
844924
if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31)
845925
return ERROR_FAIL;
846926

847927
uint32_t command = riscv013_access_register_command(target, number, size,
848928
AC_ACCESS_REGISTER_TRANSFER);
929+
if (is_command_unsupported(target, command))
930+
return ERROR_FAIL;
849931

850932
uint32_t cmderr;
851933
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-
}
934+
if (result != ERROR_OK)
862935
return result;
863-
}
864936

865937
if (value)
866938
return read_abstract_arg(target, value, 0, size);
@@ -879,23 +951,17 @@ static int register_read_abstract(struct target *target, riscv_reg_t *value,
879951
static int register_write_abstract(struct target *target, enum gdb_regno number,
880952
riscv_reg_t value)
881953
{
882-
RISCV013_INFO(info);
883-
884954
dm013_info_t *dm = get_dm(target);
885955
if (!dm)
886956
return ERROR_FAIL;
887957

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-
895958
const unsigned int size_bits = register_size(target, number);
896959
const uint32_t command = riscv013_access_register_command(target, number, size_bits,
897960
AC_ACCESS_REGISTER_TRANSFER |
898961
AC_ACCESS_REGISTER_WRITE);
962+
if (is_command_unsupported(target, command))
963+
return ERROR_FAIL;
964+
899965
LOG_DEBUG_REG(target, AC_ACCESS_REGISTER, command);
900966
assert(size_bits % 32 == 0);
901967
const unsigned int size_in_words = size_bits / 32;
@@ -915,18 +981,9 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
915981
uint32_t cmderr;
916982
res = abstract_cmd_batch_check_and_clear_cmderr(target, batch,
917983
abstractcs_read_key, &cmderr);
984+
if (res != ERROR_OK && cmderr == CMDERR_NOT_SUPPORTED)
985+
mark_command_as_unsupported(target, command);
918986

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-
}
929-
}
930987
cleanup:
931988
riscv_batch_free(batch);
932989
return res;
@@ -1709,6 +1766,10 @@ static void deinit_target(struct target *target)
17091766
if (!info)
17101767
return;
17111768

1769+
riscv013_info_t *vsinfo = info->version_specific;
1770+
if (vsinfo)
1771+
ac_cache_free(&vsinfo->ac_not_supported_cache);
1772+
17121773
riscv013_dm_free(target);
17131774

17141775
free(info->version_specific);
@@ -2819,17 +2880,7 @@ static int init_target(struct command_context *cmd_ctx,
28192880
info->progbufsize = -1;
28202881
reset_learned_delays(target);
28212882

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;
2883+
info->ac_not_supported_cache = ac_cache_construct();
28332884

28342885
return ERROR_OK;
28352886
}
@@ -3719,16 +3770,17 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
37193770
{
37203771
assert(riscv_mem_access_is_read(args));
37213772

3722-
RISCV013_INFO(info);
3723-
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
3724-
37253773
memset(args.read_buffer, 0, args.count * args.size);
37263774

37273775
/* Convert the size (bytes) to width (bits) */
37283776
unsigned int width = args.size << 3;
37293777

37303778
/* Create the command (physical address, postincrement, read) */
3731-
uint32_t command = access_memory_command(target, false, width, use_aampostincrement, false);
3779+
uint32_t command = access_memory_command(target, false, width,
3780+
/* postincrement = */ true, /* is_write= */ false);
3781+
bool use_aampostincrement = !is_command_unsupported(target, command);
3782+
command = access_memory_command(target, false, width,
3783+
/* postincrement = */ use_aampostincrement, /* is_write = */ false);
37323784

37333785
/* Execute the reads */
37343786
uint8_t *p = args.read_buffer;
@@ -3749,33 +3801,15 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
37493801
/* Execute the command */
37503802
uint32_t cmderr;
37513803
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-
}
3804+
if (use_aampostincrement && result != ERROR_OK &&
3805+
cmderr == CMDERR_NOT_SUPPORTED) {
3806+
LOG_TARGET_DEBUG(target, "Trying the same abstract memory "
3807+
"write command, but without aampostincrement");
3808+
use_aampostincrement = false;
3809+
3810+
/* Try the same access but with postincrement disabled. */
3811+
command = access_memory_command(target, false, width, false, false);
3812+
result = riscv013_execute_abstract_command(target, command, &cmderr);
37793813
}
37803814

37813815
/* TODO:
@@ -3791,7 +3825,7 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
37913825
return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED);
37923826
buf_set_u64(p, 0, 8 * args.size, value);
37933827

3794-
if (info->has_aampostincrement == YNM_YES)
3828+
if (use_aampostincrement)
37953829
updateaddr = false;
37963830
p += args.size;
37973831
}
@@ -3809,15 +3843,17 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
38093843
{
38103844
assert(riscv_mem_access_is_write(args));
38113845

3812-
RISCV013_INFO(info);
38133846
int result = ERROR_OK;
3814-
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
38153847

38163848
/* Convert the size (bytes) to width (bits) */
38173849
unsigned int width = args.size << 3;
38183850

38193851
/* Create the command (physical address, postincrement, write) */
3820-
uint32_t command = access_memory_command(target, false, width, use_aampostincrement, true);
3852+
uint32_t command = access_memory_command(target, false, width,
3853+
/* postincrement = */ true, /* is_write = */ true);
3854+
bool use_aampostincrement = !is_command_unsupported(target, command);
3855+
command = access_memory_command(target, false, width,
3856+
/* postincrement = */ use_aampostincrement, /* is_write = */ true);
38213857

38223858
/* Execute the writes */
38233859
const uint8_t *p = args.write_buffer;
@@ -3844,33 +3880,15 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
38443880
/* Execute the command */
38453881
uint32_t cmderr;
38463882
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-
}
3883+
if (use_aampostincrement && result != ERROR_OK &&
3884+
cmderr == CMDERR_NOT_SUPPORTED) {
3885+
LOG_TARGET_DEBUG(target, "Trying the same abstract memory "
3886+
"write command, but without aampostincrement");
3887+
use_aampostincrement = false;
3888+
3889+
/* Try the same access but with postincrement disabled. */
3890+
command = access_memory_command(target, false, width, false, true);
3891+
result = riscv013_execute_abstract_command(target, command, &cmderr);
38743892
}
38753893

38763894
/* TODO:
@@ -3879,7 +3897,7 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args)
38793897
if (result != ERROR_OK)
38803898
return mem_access_result(MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR);
38813899

3882-
if (info->has_aampostincrement == YNM_YES)
3900+
if (use_aampostincrement)
38833901
updateaddr = false;
38843902
p += args.size;
38853903
}

0 commit comments

Comments
 (0)