aarch64: Invalidate caches on reset

When a target is reset we must invalidate register caches in order
to avoid showing stale register values or writing them back to
registers. Use EDPRSR.SR to detect a previous reset, and EDPRSR.R to
detect a current reset state.

Change-Id: Ia1e97d7154cf7789d392274eee475733086a835b
Signed-off-by: Peter Collingbourne <pcc@google.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8425
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
This commit is contained in:
Peter Collingbourne 2024-08-01 15:48:25 -07:00 committed by Antonio Borneo
parent fd7b66c5eb
commit b14f63e004
2 changed files with 39 additions and 12 deletions

View File

@ -193,6 +193,20 @@ static int aarch64_mmu_modify(struct target *target, int enable)
return retval;
}
static int aarch64_read_prsr(struct target *target, uint32_t *prsr)
{
struct armv8_common *armv8 = target_to_armv8(target);
int retval;
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
armv8->debug_base + CPUV8_DBG_PRSR, prsr);
if (retval != ERROR_OK)
return retval;
armv8->sticky_reset |= *prsr & PRSR_SR;
return ERROR_OK;
}
/*
* Basic debug access, very low level assumes state is saved
*/
@ -213,8 +227,7 @@ static int aarch64_init_debug_access(struct target *target)
/* Clear Sticky Power Down status Bit in PRSR to enable access to
the registers in the Core Power Domain */
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
armv8->debug_base + CPUV8_DBG_PRSR, &dummy);
retval = aarch64_read_prsr(target, &dummy);
if (retval != ERROR_OK)
return retval;
@ -281,12 +294,10 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask,
static int aarch64_check_state_one(struct target *target,
uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr)
{
struct armv8_common *armv8 = target_to_armv8(target);
uint32_t prsr;
int retval;
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
armv8->debug_base + CPUV8_DBG_PRSR, &prsr);
retval = aarch64_read_prsr(target, &prsr);
if (retval != ERROR_OK)
return retval;
@ -506,16 +517,28 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
static int aarch64_poll(struct target *target)
{
struct armv8_common *armv8 = target_to_armv8(target);
enum target_state prev_target_state;
int retval = ERROR_OK;
int halted;
uint32_t prsr;
retval = aarch64_check_state_one(target,
PRSR_HALT, PRSR_HALT, &halted, NULL);
retval = aarch64_read_prsr(target, &prsr);
if (retval != ERROR_OK)
return retval;
if (halted) {
if (armv8->sticky_reset) {
armv8->sticky_reset = false;
if (target->state != TARGET_RESET) {
target->state = TARGET_RESET;
LOG_TARGET_INFO(target, "external reset detected");
if (armv8->arm.core_cache) {
register_cache_invalidate(armv8->arm.core_cache);
register_cache_invalidate(armv8->arm.core_cache->next);
}
}
}
if (prsr & PRSR_HALT) {
prev_target_state = target->state;
if (prev_target_state != TARGET_HALTED) {
enum target_debug_reason debug_reason = target->debug_reason;
@ -546,8 +569,11 @@ static int aarch64_poll(struct target *target)
break;
}
}
} else
} else if (prsr & PRSR_RESET) {
target->state = TARGET_RESET;
} else {
target->state = TARGET_RUNNING;
}
return retval;
}
@ -663,8 +689,7 @@ static int aarch64_prepare_restart_one(struct target *target)
if (retval == ERROR_OK) {
/* clear sticky bits in PRSR, SDR is now 0 */
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
armv8->debug_base + CPUV8_DBG_PRSR, &tmp);
retval = aarch64_read_prsr(target, &tmp);
}
return retval;

View File

@ -213,6 +213,8 @@ struct armv8_common {
/* True if OpenOCD provides pointer auth related info to GDB */
bool enable_pauth;
bool sticky_reset;
/* last run-control command issued to this target (resume, halt, step) */
enum run_control_op last_run_control_op;