From ec93209f51afc09e273a4742dc0b5f2cefc15e76 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 17 Nov 2009 23:50:23 -0800 Subject: [PATCH] ARM: add arm_mode_name() Add and use arm_mode_name() to map from PSR bits to user meaningful names. It uses a new table which, later, can be used to hold other mode-coupled data. Add definitions for the "Secure Monitor" mode, as seen on some ARM11 cores (like ARM1176) and on Cortex-A8. The previous mode name scheme didn't understand that mode. Remove the old mechanism ... there were two copies, caused by Cortex-A8 needing to add "Secure Monitor" mode support. Signed-off-by: David Brownell --- src/target/arm720t.c | 2 +- src/target/arm7_9_common.c | 11 +++++-- src/target/arm920t.c | 2 +- src/target/arm926ejs.c | 2 +- src/target/armv4_5.c | 65 ++++++++++++++++++++++++++++++++++---- src/target/armv4_5.h | 4 +-- src/target/armv7a.c | 12 +------ src/target/armv7a.h | 2 -- src/target/xscale.c | 5 +-- 9 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/target/arm720t.c b/src/target/arm720t.c index b51f969a6a..a6c7cc78ec 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -239,7 +239,7 @@ static int arm720t_arch_state(struct target *target) "MMU: %s, Cache: %s", armv4_5_state_strings[armv4_5->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name , - armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)], + arm_mode_name(armv4_5->core_mode), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32), state[arm720t->armv4_5_mmu.mmu_enabled], diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index b29eb5cc5e..ff95a0cd7e 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1420,7 +1420,8 @@ static int arm7_9_debug_entry(struct target *target) return ERROR_TARGET_FAILURE; } - LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]); + LOG_DEBUG("target entered debug state in %s mode", + arm_mode_name(armv4_5->core_mode)); if (armv4_5->core_state == ARMV4_5_STATE_THUMB) { @@ -1613,7 +1614,8 @@ int arm7_9_restore_context(struct target *target) */ for (i = 0; i < 6; i++) { - LOG_DEBUG("examining %s mode", armv4_5_mode_strings[i]); + LOG_DEBUG("examining %s mode", + arm_mode_name(armv4_5->core_mode)); dirty = 0; mode_change = 0; /* check if there are dirty registers in the current mode @@ -1675,7 +1677,10 @@ int arm7_9_restore_context(struct target *target) num_regs++; reg->dirty = 0; reg->valid = 1; - LOG_DEBUG("writing register %i of mode %s with value 0x%8.8" PRIx32 "", j, armv4_5_mode_strings[i], regs[j]); + LOG_DEBUG("writing register %i mode %s " + "with value 0x%8.8" PRIx32, j, + arm_mode_name(armv4_5->core_mode), + regs[j]); } } diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 99b4bbd378..e1dcea7a82 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -451,7 +451,7 @@ int arm920t_arch_state(struct target *target) "MMU: %s, D-Cache: %s, I-Cache: %s", armv4_5_state_strings[armv4_5->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name, - armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)], + arm_mode_name(armv4_5->core_mode), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32), state[arm920t->armv4_5_mmu.mmu_enabled], diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index cc6318b9ad..27eb75295d 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -509,7 +509,7 @@ int arm926ejs_arch_state(struct target *target) "MMU: %s, D-Cache: %s, I-Cache: %s", armv4_5_state_strings[armv4_5->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason,target->debug_reason)->name, - armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)], + arm_mode_name(armv4_5->core_mode), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32), state[arm926ejs->armv4_5_mmu.mmu_enabled], diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index aba4431969..6864efbb16 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -53,13 +53,63 @@ char* armv4_5_core_reg_list[] = "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und" }; -static const char *armv4_5_mode_strings_list[] = -{ - "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System" +static const struct { + const char *name; + unsigned psr; +} arm_mode_data[] = { + /* Seven modes are standard from ARM7 on. "System" and "User" share + * the same registers; other modes shadow from 3 to 8 registers. + */ + { + .name = "User", + .psr = ARMV4_5_MODE_USR, + }, + { + .name = "FIQ", + .psr = ARMV4_5_MODE_FIQ, + }, + { + .name = "Supervisor", + .psr = ARMV4_5_MODE_SVC, + }, + { + .name = "Abort", + .psr = ARMV4_5_MODE_ABT, + }, + { + .name = "IRQ", + .psr = ARMV4_5_MODE_IRQ, + }, + { + .name = "Undefined" /* instruction */, + .psr = ARMV4_5_MODE_UND, + }, + { + .name = "System", + .psr = ARMV4_5_MODE_SYS, + }, + /* TrustZone "Security Extensions" add a secure monitor mode. + * This is distinct from a "debug monitor" which can support + * non-halting debug, in conjunction with some debuggers. + */ + { + .name = "Secure Monitor", + .psr = ARM_MODE_MON, + }, }; -/* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */ -const char **armv4_5_mode_strings = armv4_5_mode_strings_list + 1; +/** Map PSR mode bits to the name of an ARM processor operating mode. */ +const char *arm_mode_name(unsigned psr_mode) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { + if (arm_mode_data[i].psr == psr_mode) + return arm_mode_data[i].name; + } + LOG_ERROR("unrecognized psr mode: %#02x", psr_mode); + return "UNRECOGNIZED"; +} /** Map PSR mode bits to linear number */ int armv4_5_mode_to_number(enum armv4_5_mode mode) @@ -282,7 +332,8 @@ int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f)) { - LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]); + LOG_DEBUG("changing ARM core mode to '%s'", + arm_mode_name(value & 0x1f)); armv4_5_target->core_mode = value & 0x1f; armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value); } @@ -357,7 +408,7 @@ int armv4_5_arch_state(struct target *target) LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "", armv4_5_state_strings[armv4_5->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name, - armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)], + arm_mode_name(armv4_5->core_mode), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h index d126f964ef..5b7a5220af 100644 --- a/src/target/armv4_5.h +++ b/src/target/armv4_5.h @@ -35,16 +35,16 @@ typedef enum armv4_5_mode ARMV4_5_MODE_IRQ = 18, ARMV4_5_MODE_SVC = 19, ARMV4_5_MODE_ABT = 23, + ARM_MODE_MON = 26, ARMV4_5_MODE_UND = 27, ARMV4_5_MODE_SYS = 31, ARMV4_5_MODE_ANY = -1 } armv4_5_mode_t; +const char *arm_mode_name(unsigned psr_mode); int armv4_5_mode_to_number(enum armv4_5_mode mode); enum armv4_5_mode armv4_5_number_to_mode(int number); -extern const char **armv4_5_mode_strings; - typedef enum armv4_5_state { ARMV4_5_STATE_ARM, diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 1518674a20..e13b33b4e0 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -47,15 +47,6 @@ char* armv7a_core_reg_list[] = "r13_mon", "lr_mon", "spsr_mon" }; -char * armv7a_mode_strings_list[] = -{ - "Illegal mode value", "User", "FIQ", "IRQ", - "Supervisor", "Abort", "Undefined", "System", "Monitor" -}; - -/* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */ -char** armv7a_mode_strings = armv7a_mode_strings_list+1; - char* armv7a_state_strings[] = { "ARM", "Thumb", "Jazelle", "ThumbEE" @@ -183,8 +174,7 @@ int armv7a_arch_state(struct target *target) armv7a_state_strings[armv7a->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name, - armv7a_mode_strings[ - armv7a_mode_to_number(armv4_5->core_mode)], + arm_mode_name(armv4_5->core_mode), armv7a_core_reg_list[armv7a_core_reg_map[ armv7a_mode_to_number(armv4_5->core_mode)][16]], buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache, diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 4d29ef9b21..e781e72070 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -37,8 +37,6 @@ typedef enum armv7a_mode ARMV7A_MODE_ANY = -1 } armv7a_t; -extern char **armv7a_mode_strings; - typedef enum armv7a_state { ARMV7A_STATE_ARM, diff --git a/src/target/xscale.c b/src/target/xscale.c index a4a8eabd61..38928f4178 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -857,7 +857,7 @@ static int xscale_arch_state(struct target *target) "%s", armv4_5_state_strings[armv4_5->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name , - armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)], + arm_mode_name(armv4_5->core_mode), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32), state[xscale->armv4_5_mmu.mmu_enabled], @@ -960,7 +960,8 @@ static int xscale_debug_entry(struct target *target) LOG_ERROR("cpsr contains invalid mode value - communication failure"); return ERROR_TARGET_FAILURE; } - LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]); + LOG_DEBUG("target entered debug state in %s mode", + arm_mode_name(armv4_5->core_mode)); if (buffer[9] & 0x20) armv4_5->core_state = ARMV4_5_STATE_THUMB; -- 2.30.2