Skip to content

Commit cc7e5e3

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 cc7e5e3

File tree

1 file changed

+113
-112
lines changed

1 file changed

+113
-112
lines changed

src/target/riscv/riscv-013.c

Lines changed: 113 additions & 112 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;
@@ -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);
687736
cleanup:
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
}
930966
cleanup:
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

Comments
 (0)