target/armv8: Handle instruction cache invalidate

Some armv8 target have separate i-cache and d-cache.
The actual code only handles the flush of the d-cache.

Change-Id: I61a223b43c71646bbbed8fa63825360c67700988
Signed-off-by: Adrien Grassein <agrassein@nanoxplore.com>
Signed-off-by: Adrien Charruel <acharruel@nanoxplore.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8655
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
This commit is contained in:
Adrien Grassein
2024-01-18 11:58:38 +01:00
committed by Antonio Borneo
parent 98e34fd1f1
commit 5773ff9d82
4 changed files with 68 additions and 0 deletions

View File

@@ -141,6 +141,36 @@ done:
return retval;
}
static int armv8_cache_i_inner_clean_inval_all(struct armv8_common *armv8)
{
struct arm_dpm *dpm = armv8->arm.dpm;
int retval;
retval = armv8_i_cache_sanity_check(armv8);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("flushing cache");
retval = dpm->prepare(dpm);
if (retval != ERROR_OK)
goto done;
retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_ICIALLU));
if (retval != ERROR_OK)
goto done;
dpm->finish(dpm);
LOG_DEBUG("flushing cache done");
return retval;
done:
LOG_ERROR("i-cache invalidate failed");
dpm->finish(dpm);
return retval;
}
int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, size_t size)
{
struct arm_dpm *dpm = armv8->arm.dpm;
@@ -253,6 +283,32 @@ static int armv8_flush_all_data(struct target *target)
return retval;
}
static int armv8_flush_all_instruction(struct target *target)
{
int retval = ERROR_FAIL;
/* check that armv8_cache is correctly identify */
struct armv8_common *armv8 = target_to_armv8(target);
if (armv8->armv8_mmu.armv8_cache.info == -1) {
LOG_ERROR("trying to flush un-identified cache");
return retval;
}
if (target->smp) {
/* look if all the other target have been flushed in order to flush icache */
struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr->state == TARGET_HALTED) {
LOG_TARGET_INFO(curr, "Wait flushing instruction l1.");
retval = armv8_cache_i_inner_clean_inval_all(target_to_armv8(curr));
}
}
} else {
retval = armv8_cache_i_inner_clean_inval_all(armv8);
}
return retval;
}
static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg)
{
struct armv8_common *armv8 = dpm->arm->arch_info;
@@ -412,6 +468,12 @@ int armv8_identify_cache(struct armv8_common *armv8)
armv8->armv8_mmu.armv8_cache.flush_all_data_cache =
armv8_flush_all_data;
}
if (!armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache) {
armv8->armv8_mmu.armv8_cache.display_cache_info =
armv8_handle_inner_cache_info_command;
armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache =
armv8_flush_all_instruction;
}
done:
armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);