diff --git a/src/target/arm.h b/src/target/arm.h index bf0d9327e..b39957495 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -47,12 +47,16 @@ * on for example ARM7TDMI cores. * - ARM_CORE_TYPE_SEC_EXT indicates core has security extensions, thus * three more registers are shadowed for "Secure Monitor" mode. + * - ARM_CORE_TYPE_VIRT_EXT indicates core has virtualization extensions + * and also security extensions. Additional shadowed registers for + * "Secure Monitor" and "Hypervisor" modes. * - ARM_CORE_TYPE_M_PROFILE indicates a microcontroller profile core, * which only shadows SP. */ enum arm_core_type { ARM_CORE_TYPE_STD = -1, ARM_CORE_TYPE_SEC_EXT = 1, + ARM_CORE_TYPE_VIRT_EXT, ARM_CORE_TYPE_M_PROFILE, }; @@ -76,6 +80,7 @@ enum arm_mode { ARM_MODE_SVC = 19, ARM_MODE_MON = 22, ARM_MODE_ABT = 23, + ARM_MODE_HYP = 26, ARM_MODE_UND = 27, ARM_MODE_1176_MON = 28, ARM_MODE_SYS = 31, diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index c27e9537d..a0983cd54 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -48,6 +48,7 @@ enum { ARMV4_5_SPSR_ABT = 35, ARMV4_5_SPSR_UND = 36, ARM_SPSR_MON = 41, + ARM_SPSR_HYP = 43, }; static const uint8_t arm_usr_indices[17] = { @@ -78,6 +79,10 @@ static const uint8_t arm_mon_indices[3] = { 39, 40, ARM_SPSR_MON, }; +static const uint8_t arm_hyp_indices[2] = { + 42, ARM_SPSR_HYP, +}; + static const struct { const char *name; unsigned short psr; @@ -163,6 +168,14 @@ static const struct { .name = "Handler", .psr = ARM_MODE_HANDLER, }, + + /* armv7-a with virtualization extension */ + { + .name = "Hypervisor", + .psr = ARM_MODE_HYP, + .n_indices = ARRAY_SIZE(arm_hyp_indices), + .indices = arm_hyp_indices, + }, }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ @@ -209,6 +222,8 @@ int arm_mode_to_number(enum arm_mode mode) case ARM_MODE_MON: case ARM_MODE_1176_MON: return 7; + case ARM_MODE_HYP: + return 8; default: LOG_ERROR("invalid mode value encountered %d", mode); return -1; @@ -235,6 +250,8 @@ enum arm_mode armv4_5_number_to_mode(int number) return ARM_MODE_SYS; case 7: return ARM_MODE_MON; + case 8: + return ARM_MODE_HYP; default: LOG_ERROR("mode index out of bounds %d", number); return ARM_MODE_ANY; @@ -342,6 +359,9 @@ static const struct { [40] = { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, }, [41] = { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, }, + /* These exist only when the Virtualization Extensions is present */ + [42] = { .name = "sp_hyp", .cookie = 13, .mode = ARM_MODE_HYP, .gdb_index = 51, }, + [43] = { .name = "spsr_hyp", .cookie = 16, .mode = ARM_MODE_HYP, .gdb_index = 52, }, }; static const struct { @@ -391,7 +411,7 @@ static const struct { /* map core mode (USR, FIQ, ...) and register number to * indices into the register cache */ -const int armv4_5_core_reg_map[8][17] = { +const int armv4_5_core_reg_map[9][17] = { { /* USR */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31 }, @@ -415,6 +435,9 @@ const int armv4_5_core_reg_map[8][17] = { }, { /* MON */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 39, 40, 15, 41, + }, + { /* HYP */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 42, 14, 15, 43, } }; @@ -658,7 +681,11 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) for (i = 0; i < num_core_regs; i++) { /* Skip registers this core doesn't expose */ if (arm_core_regs[i].mode == ARM_MODE_MON - && arm->core_type != ARM_CORE_TYPE_SEC_EXT) + && arm->core_type != ARM_CORE_TYPE_SEC_EXT + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + if (arm_core_regs[i].mode == ARM_MODE_HYP + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) continue; /* REVISIT handle Cortex-M, which only shadows R13/SP */ @@ -816,8 +843,13 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) name = "System and User"; sep = ""; break; + case ARM_MODE_HYP: + if (arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + /* FALLTHROUGH */ case ARM_MODE_MON: - if (arm->core_type != ARM_CORE_TYPE_SEC_EXT) + if (arm->core_type != ARM_CORE_TYPE_SEC_EXT + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) continue; /* FALLTHROUGH */ default: @@ -1194,7 +1226,16 @@ int arm_get_gdb_reg_list(struct target *target, break; case REG_CLASS_ALL: - *reg_list_size = (arm->core_type != ARM_CORE_TYPE_SEC_EXT ? 48 : 51); + switch (arm->core_type) { + case ARM_CORE_TYPE_SEC_EXT: + *reg_list_size = 51; + break; + case ARM_CORE_TYPE_VIRT_EXT: + *reg_list_size = 53; + break; + default: + *reg_list_size = 48; + } unsigned int list_size_core = *reg_list_size; if (arm->arm_vfp_version == ARM_VFP_V3) *reg_list_size += 33; @@ -1206,9 +1247,15 @@ int arm_get_gdb_reg_list(struct target *target, for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) { int reg_index = arm->core_cache->reg_list[i].number; - if (!(arm_core_regs[i].mode == ARM_MODE_MON - && arm->core_type != ARM_CORE_TYPE_SEC_EXT)) - (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); + + if (arm_core_regs[i].mode == ARM_MODE_MON + && arm->core_type != ARM_CORE_TYPE_SEC_EXT + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + if (arm_core_regs[i].mode == ARM_MODE_HYP + && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) + continue; + (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); } /* When we supply the target description, there is no need for fake FPA */ diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h index 3ce4ed0e5..bef1cfe32 100644 --- a/src/target/armv4_5.h +++ b/src/target/armv4_5.h @@ -38,7 +38,7 @@ int arm_mode_to_number(enum arm_mode mode); enum arm_mode armv4_5_number_to_mode(int number); -extern const int armv4_5_core_reg_map[8][17]; +extern const int armv4_5_core_reg_map[9][17]; #define ARMV4_5_CORE_REG_MODE(cache, mode, num) \ (cache->reg_list[armv4_5_core_reg_map[arm_mode_to_number(mode)][num]]) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 22cbc3d06..729a173eb 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2797,6 +2797,15 @@ static int cortex_a_examine_first(struct target *target) target->coreid); armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT; } + if (dbg_idpfr1 & 0x0000f000) { + LOG_DEBUG("target->coreid %" PRId32 " has virtualization extensions", + target->coreid); + /* + * overwrite and simplify the checks. + * virtualization extensions require implementation of security extension + */ + armv7a->arm.core_type = ARM_CORE_TYPE_VIRT_EXT; + } /* Avoid recreating the registers cache */ if (!target_was_examined(target)) {