diff --git a/src/target/armv7m.c b/src/target/armv7m.c index dc2d84fe1..b8697c032 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -139,6 +139,9 @@ static const struct { { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV8M_MSPLIM, "msplim", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV8M_PSPLIM, "psplim", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.m-system", NULL, }, + /* ARMv8-M security extension (TrustZone) specific registers */ { ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, { ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, @@ -288,6 +291,12 @@ uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) case ARMV8M_MSP_NS...ARMV8M_PSPLIM_NS: return arm_reg_id - ARMV8M_MSP_NS + ARMV8M_REGSEL_MSP_NS; + case ARMV8M_PSPLIM: + return ARMV8M_REGSEL_PSPLIM; + + case ARMV8M_MSPLIM: + return ARMV8M_REGSEL_MSPLIM; + case ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S: return ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_S; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 942e22584..8020cf034 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -59,6 +59,8 @@ enum { ARMV8M_REGSEL_PSPLIM_S, ARMV8M_REGSEL_MSPLIM_NS, ARMV8M_REGSEL_PSPLIM_NS, + ARMV8M_REGSEL_MSPLIM = ARMV8M_REGSEL_MSPLIM_NS, + ARMV8M_REGSEL_PSPLIM = ARMV8M_REGSEL_PSPLIM_NS, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL = 0x14, ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_S = 0x22, @@ -150,6 +152,8 @@ enum { /* The end of block of container and contained registers */ /* ARMv8-M specific registers */ + ARMV8M_MSPLIM, + ARMV8M_PSPLIM, ARMV8M_MSP_NS, ARMV8M_PSP_NS, ARMV8M_MSP_S, @@ -207,8 +211,8 @@ enum { ARMV7M_CORE_LAST_REG = ARMV7M_XPSR, ARMV7M_FPU_FIRST_REG = ARMV7M_D0, ARMV7M_FPU_LAST_REG = ARMV8M_VPR, - ARMV8M_FIRST_REG = ARMV8M_MSP_NS, - ARMV8M_LAST_REG = ARMV8M_CONTROL_NS, + ARMV8M_TZ_FIRST_REG = ARMV8M_MSP_NS, + ARMV8M_TZ_LAST_REG = ARMV8M_CONTROL_NS, }; enum { diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 42e957260..21b611b29 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2613,6 +2613,21 @@ static bool cortex_m_has_tz(struct target *target) return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0; } +static bool cortex_m_main_extension(struct target *target, uint32_t cpuid) +{ + /* Inspect architecture to differentiate main extension/baseline */ + unsigned int extension = (cpuid & ARM_CPUID_ARCHITECTURE_MASK) >> ARM_CPUID_ARCHITECTURE_POS; + + if (extension == ARM_CPUID_MAIN_EXTENSION) + return true; + else if (extension == ARM_CPUID_NO_MAIN_EXTENSION) + return false; + + LOG_TARGET_WARNING(target, "Fail to detect target extension"); + + return false; +} + int cortex_m_set_secure(struct target *target, struct cortex_m_saved_security *ssec) { if (ssec) { @@ -2872,10 +2887,45 @@ int cortex_m_examine(struct target *target) if (armv7m->fp_feature != FPV5_MVE_F && armv7m->fp_feature != FPV5_MVE_I) armv7m->arm.core_cache->reg_list[ARMV8M_VPR].exist = false; - if (!cortex_m_has_tz(target)) - for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++) + if (cortex_m->core_info->arch == ARM_ARCH_V8M) { + bool cm_has_tz = cortex_m_has_tz(target); + bool main_ext = cortex_m_main_extension(target, cpuid); + bool baseline = !main_ext; + + if (!cm_has_tz) { + for (size_t idx = ARMV8M_TZ_FIRST_REG; idx <= ARMV8M_TZ_LAST_REG; idx++) + armv7m->arm.core_cache->reg_list[idx].exist = false; + + if (baseline) { + armv7m->arm.core_cache->reg_list[ARMV8M_MSPLIM].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_PSPLIM].exist = false; + } + } else { + if (baseline) { + /* ARMV8M without main extension but with the security extension has + only two stack limit registers in Secure state */ + armv7m->arm.core_cache->reg_list[ARMV8M_MSPLIM_NS].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_PSPLIM_NS].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_MSPLIM].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_PSPLIM].exist = false; + } else { + /* There is no separate regsel for msplim/psplim of ARMV8M mainline + with the security extension that would point to correct alias + depending on security state of the processor, thus register marked + as non-existing letting to choose between S/NS alias manually */ + armv7m->arm.core_cache->reg_list[ARMV8M_MSPLIM].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_PSPLIM].exist = false; + } + } + } else { + /* Security extension and stack limit checking introduced in ARMV8M */ + for (size_t idx = ARMV8M_TZ_FIRST_REG; idx <= ARMV8M_TZ_LAST_REG; idx++) armv7m->arm.core_cache->reg_list[idx].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_MSPLIM].exist = false; + armv7m->arm.core_cache->reg_list[ARMV8M_PSPLIM].exist = false; + } + if (!armv7m->is_hla_target) { if (cortex_m->core_info->flags & CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K) /* Cortex-M3/M4 have 4096 bytes autoincrement range, diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index e0a4e8552..615369f34 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -37,6 +37,11 @@ #define ARM_CPUID_PARTNO_POS 4 #define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS) +#define ARM_CPUID_ARCHITECTURE_POS 16 +#define ARM_CPUID_ARCHITECTURE_MASK (0xF << ARM_CPUID_ARCHITECTURE_POS) +#define ARM_CPUID_MAIN_EXTENSION 0xF +#define ARM_CPUID_NO_MAIN_EXTENSION 0xC + #define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTER_POS) & ARM_CPUID_IMPLEMENTER_MASK) | \ (((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK))