From b5d2b1224fed3909aa3314339611ac5ac7ab0f82 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 25 Jun 2019 16:01:38 +0200 Subject: [PATCH] target/cortex_a: add hypervisor mode Hypervisor mode is present only if the optional virtualization extensions are available. Moreover, virtualization extensions require that also security extensions are implemented. Add the required infrastructure for the shadowed registers in hypervisor mode. Make monitor shadowed registers visible in hypervisor mode too. Make hypervisor shadowed registers visible in hypervisor mode only. Check during cortex_a examine if virtualization extensions are present and then conditionally enable the visibility of both hypervisor and monitor modes shadowed registers. Change-Id: I81dbb1ee8baf4c9f1a2226b77c10c8a2a7b34871 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/5261 Tested-by: jenkins --- src/target/arm.h | 5 ++++ src/target/armv4_5.c | 61 ++++++++++++++++++++++++++++++++++++++----- src/target/armv4_5.h | 2 +- src/target/cortex_a.c | 9 +++++++ 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/target/arm.h b/src/target/arm.h index bf0d9327e1..b39957495f 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 c27e9537d3..a0983cd54c 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 3ce4ed0e56..bef1cfe32a 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 22cbc3d063..729a173eb4 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)) { -- 2.30.2