Skip to content

Commit 5773ff9

Browse files
Adrien Grasseinborneoa
authored andcommitted
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 <[email protected]> Signed-off-by: Adrien Charruel <[email protected]> Reviewed-on: https://review.openocd.org/c/openocd/+/8655 Reviewed-by: Antonio Borneo <[email protected]> Tested-by: jenkins
1 parent 98e34fd commit 5773ff9

File tree

4 files changed

+68
-0
lines changed

4 files changed

+68
-0
lines changed

src/target/armv8.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ struct armv8_cache_common {
162162
/* l2 external unified cache if some */
163163
void *l2_cache;
164164
int (*flush_all_data_cache)(struct target *target);
165+
int (*invalidate_all_instruction_cache)(struct target *target);
165166
int (*display_cache_info)(struct command_invocation *cmd,
166167
struct armv8_cache_common *armv8_cache);
167168
};

src/target/armv8_cache.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,36 @@ int armv8_cache_d_inner_flush_virt(struct armv8_common *armv8, target_addr_t va,
141141
return retval;
142142
}
143143

144+
static int armv8_cache_i_inner_clean_inval_all(struct armv8_common *armv8)
145+
{
146+
struct arm_dpm *dpm = armv8->arm.dpm;
147+
int retval;
148+
149+
retval = armv8_i_cache_sanity_check(armv8);
150+
if (retval != ERROR_OK)
151+
return retval;
152+
153+
LOG_DEBUG("flushing cache");
154+
155+
retval = dpm->prepare(dpm);
156+
if (retval != ERROR_OK)
157+
goto done;
158+
159+
retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_ICIALLU));
160+
if (retval != ERROR_OK)
161+
goto done;
162+
163+
dpm->finish(dpm);
164+
LOG_DEBUG("flushing cache done");
165+
return retval;
166+
167+
done:
168+
LOG_ERROR("i-cache invalidate failed");
169+
dpm->finish(dpm);
170+
171+
return retval;
172+
}
173+
144174
int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, size_t size)
145175
{
146176
struct arm_dpm *dpm = armv8->arm.dpm;
@@ -253,6 +283,32 @@ static int armv8_flush_all_data(struct target *target)
253283
return retval;
254284
}
255285

286+
static int armv8_flush_all_instruction(struct target *target)
287+
{
288+
int retval = ERROR_FAIL;
289+
/* check that armv8_cache is correctly identify */
290+
struct armv8_common *armv8 = target_to_armv8(target);
291+
if (armv8->armv8_mmu.armv8_cache.info == -1) {
292+
LOG_ERROR("trying to flush un-identified cache");
293+
return retval;
294+
}
295+
296+
if (target->smp) {
297+
/* look if all the other target have been flushed in order to flush icache */
298+
struct target_list *head;
299+
foreach_smp_target(head, target->smp_targets) {
300+
struct target *curr = head->target;
301+
if (curr->state == TARGET_HALTED) {
302+
LOG_TARGET_INFO(curr, "Wait flushing instruction l1.");
303+
retval = armv8_cache_i_inner_clean_inval_all(target_to_armv8(curr));
304+
}
305+
}
306+
} else {
307+
retval = armv8_cache_i_inner_clean_inval_all(armv8);
308+
}
309+
return retval;
310+
}
311+
256312
static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg)
257313
{
258314
struct armv8_common *armv8 = dpm->arm->arch_info;
@@ -412,6 +468,12 @@ int armv8_identify_cache(struct armv8_common *armv8)
412468
armv8->armv8_mmu.armv8_cache.flush_all_data_cache =
413469
armv8_flush_all_data;
414470
}
471+
if (!armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache) {
472+
armv8->armv8_mmu.armv8_cache.display_cache_info =
473+
armv8_handle_inner_cache_info_command;
474+
armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache =
475+
armv8_flush_all_instruction;
476+
}
415477

416478
done:
417479
armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);

src/target/armv8_opcodes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = {
4141
[ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP(1, 0),
4242
[ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP(1, 0),
4343
[ARMV8_OPC_STRD_IP] = ARMV8_STRD_IP(1, 0),
44+
[ARMV8_OPC_ICIALLU] = ARMV8_SYS(SYSTEM_ICIALLU, 0x1F),
4445
};
4546

4647
static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = {
@@ -68,6 +69,7 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = {
6869
[ARMV8_OPC_STRB_IP] = ARMV8_STRB_IP_T3(1, 0),
6970
[ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP_T3(1, 0),
7071
[ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP_T3(1, 0),
72+
[ARMV8_OPC_ICIALLU] = ARMV4_5_MCR(15, 0, 0, 7, 5, 0),
7173
};
7274

7375
void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64)

src/target/armv8_opcodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
#define SYSTEM_DCCISW 0x43F2
7373
#define SYSTEM_DCCSW 0x43D2
7474
#define SYSTEM_ICIVAU 0x5BA9
75+
/* Attention, SYSTEM_ICIALLU requires rt=0x1f */
76+
#define SYSTEM_ICIALLU 0x03A8
7577
#define SYSTEM_DCCVAU 0x5BD9
7678
#define SYSTEM_DCCIVAC 0x5BF1
7779

@@ -207,6 +209,7 @@ enum armv8_opcode {
207209
ARMV8_OPC_LDRH_IP,
208210
ARMV8_OPC_LDRW_IP,
209211
ARMV8_OPC_LDRD_IP,
212+
ARMV8_OPC_ICIALLU,
210213
ARMV8_OPC_NUM,
211214
};
212215

0 commit comments

Comments
 (0)