aboutsummaryrefslogtreecommitdiff
path: root/src/target/armv4_5.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/armv4_5.c')
-rw-r--r--src/target/armv4_5.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index c27e9537..a0983cd5 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 */