mirror of
https://github.com/openocd-org/openocd.git
synced 2025-10-14 02:58:23 +08:00
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:

committed by
Antonio Borneo

parent
ce3bf664c8
commit
f547e55076
@@ -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
|
||||
|
@@ -167,6 +167,8 @@ struct cortex_m_part_info {
|
||||
#define NVIC_DFSR 0xE000ED30
|
||||
#define NVIC_MMFAR 0xE000ED34
|
||||
#define NVIC_BFAR 0xE000ED38
|
||||
#define MPU_CTRL 0xE000ED94
|
||||
#define SAU_CTRL 0xE000EDD0
|
||||
#define NVIC_SFSR 0xE000EDE4
|
||||
#define NVIC_SFAR 0xE000EDE8
|
||||
|
||||
@@ -184,6 +186,9 @@ struct cortex_m_part_info {
|
||||
#define DFSR_VCATCH 8
|
||||
#define DFSR_EXTERNAL 16
|
||||
|
||||
#define MPU_CTRL_ENABLE BIT(0)
|
||||
#define SAU_CTRL_ENABLE BIT(0)
|
||||
|
||||
#define FPCR_CODE 0
|
||||
#define FPCR_LITERAL 1
|
||||
#define FPCR_REPLACE_REMAP (0ul << 30)
|
||||
@@ -264,6 +269,15 @@ struct cortex_m_common {
|
||||
bool incorrect_halt_erratum;
|
||||
};
|
||||
|
||||
struct cortex_m_saved_security {
|
||||
bool dscsr_dirty;
|
||||
uint32_t dscsr;
|
||||
bool sau_ctrl_dirty;
|
||||
uint32_t sau_ctrl;
|
||||
bool mpu_ctrl_dirty;
|
||||
uint32_t mpu_ctrl;
|
||||
};
|
||||
|
||||
static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m)
|
||||
{
|
||||
return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC;
|
||||
@@ -341,4 +355,17 @@ void cortex_m_deinit_target(struct target *target);
|
||||
int cortex_m_profiling(struct target *target, uint32_t *samples,
|
||||
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
|
||||
|
||||
/**
|
||||
* Forces Cortex-M core to the basic secure context with SAU and MPU off
|
||||
* @param ssec pointer to save previous security state or NULL
|
||||
* @returns error code or ERROR_OK if secure mode was set or is not applicable
|
||||
* (not ARMv8M with security extension)
|
||||
*/
|
||||
int cortex_m_set_secure(struct target *target, struct cortex_m_saved_security *ssec);
|
||||
|
||||
/**
|
||||
* Restores saved security context to MPU_CTRL, SAU_CTRL and DSCSR
|
||||
*/
|
||||
int cortex_m_security_restore(struct target *target, struct cortex_m_saved_security *ssec);
|
||||
|
||||
#endif /* OPENOCD_TARGET_CORTEX_M_H */
|
||||
|
Reference in New Issue
Block a user