target/cortex_m: introduce security manipulation routines

Running target algorithms on ARMv8M may require core in secure
mode with SAU and MPU off (as set after reset).

cortex_m_set_secure() forces this mode with optional save of
the previous state.

cortex_m_security_restore() restores previously saved state.

Change-Id: Ia71826db47ee7b0557eaffd55244ce13eacbcb4b
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/8959
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Tomas Vanek
2025-06-17 16:23:12 +02:00
committed by Antonio Borneo
parent ce3bf664c8
commit f547e55076
2 changed files with 133 additions and 0 deletions

View File

@@ -2563,6 +2563,112 @@ static bool cortex_m_has_tz(struct target *target)
return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0;
}
int cortex_m_set_secure(struct target *target, struct cortex_m_saved_security *ssec)
{
if (ssec) {
ssec->dscsr_dirty = false;
ssec->sau_ctrl_dirty = false;
ssec->mpu_ctrl_dirty = false;
}
if (!cortex_m_has_tz(target))
return ERROR_OK;
uint32_t dscsr;
int retval = target_read_u32(target, DCB_DSCSR, &dscsr);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: DSCSR read failed");
return retval;
}
if (!(dscsr & DSCSR_CDS)) {
if (ssec) {
ssec->dscsr_dirty = true;
ssec->dscsr = dscsr;
}
LOG_TARGET_DEBUG(target, "Setting Current Domain Secure in DSCSR");
retval = target_write_u32(target, DCB_DSCSR, DSCSR_CDS);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: DSCSR write failed");
return retval;
}
}
uint32_t sau_ctrl;
retval = target_read_u32(target, SAU_CTRL, &sau_ctrl);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: SAU_CTRL read failed");
return retval;
}
if (sau_ctrl & SAU_CTRL_ENABLE) {
if (ssec) {
ssec->sau_ctrl_dirty = true;
ssec->sau_ctrl = sau_ctrl;
}
retval = target_write_u32(target, SAU_CTRL, sau_ctrl & ~SAU_CTRL_ENABLE);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: SAU_CTRL write failed");
return retval;
}
}
uint32_t mpu_ctrl;
retval = target_read_u32(target, MPU_CTRL, &mpu_ctrl);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: MPU_CTRL read failed");
return retval;
}
if (mpu_ctrl & MPU_CTRL_ENABLE) {
if (ssec) {
ssec->mpu_ctrl_dirty = true;
ssec->mpu_ctrl = mpu_ctrl;
}
retval = target_write_u32(target, MPU_CTRL, mpu_ctrl & ~MPU_CTRL_ENABLE);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: MPU_CTRL write failed");
return retval;
}
}
return ERROR_OK;
}
int cortex_m_security_restore(struct target *target, struct cortex_m_saved_security *ssec)
{
int retval;
if (!cortex_m_has_tz(target))
return ERROR_OK;
if (!ssec)
return ERROR_OK;
if (ssec->mpu_ctrl_dirty) {
retval = target_write_u32(target, MPU_CTRL, ssec->mpu_ctrl);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M security restore: MPU_CTRL write failed");
return retval;
}
ssec->mpu_ctrl_dirty = false;
}
if (ssec->sau_ctrl_dirty) {
retval = target_write_u32(target, SAU_CTRL, ssec->sau_ctrl);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M security restore: SAU_CTRL write failed");
return retval;
}
ssec->sau_ctrl_dirty = false;
}
if (ssec->dscsr_dirty) {
LOG_TARGET_DEBUG(target, "Restoring Current Domain Security in DSCSR");
retval = target_write_u32(target, DCB_DSCSR, ssec->dscsr & ~DSCSR_CDSKEY);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "ARMv8M set secure: DSCSR write failed");
return retval;
}
ssec->dscsr_dirty = false;
}
return ERROR_OK;
}
#define MVFR0 0xE000EF40
#define MVFR0_SP_MASK 0x000000F0