]> git.sur5r.net Git - openocd/commitdiff
cortex_a: add 'dacrfixup' to cortex-a command group
authorMatthias Welwarsky <matthias@welwarsky.de>
Tue, 24 Nov 2015 21:11:56 +0000 (22:11 +0100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Tue, 29 Dec 2015 21:43:45 +0000 (21:43 +0000)
work around issues with software breakpoints when the text segment
is mapped read-only by the OS. Set DACR to "all-manager" to bypass
TLB permission checks on memory access.

Change-Id: I79fd9b32b04a4d538d489896470ee30b26b72b30
Signed-off-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-on: http://openocd.zylin.com/3107
Tested-by: jenkins
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
doc/openocd.texi
src/target/cortex_a.c
src/target/cortex_a.h

index 8641531944d69faaf2cdbfc916bd1c969f457cf4..78298b8611a5ef45a48222988e32134260470663 100644 (file)
@@ -7678,6 +7678,13 @@ Disabled by default
 display information about target caches
 @end deffn
 
+@deffn Command {cortex_a dacrfixup [@option{on}|@option{off}]}
+Work around issues with software breakpoints when the program text is
+mapped read-only by the operating system. This option sets the CP15 DACR
+to "all-manager" to bypass MMU permission checks on memory access.
+Defaults to 'off'.
+@end deffn
+
 @deffn Command {cortex_a dbginit}
 Initialize core debug
 Enables debug by unlocking the Software Lock and clearing sticky powerdown indications
index 78ce33df7ead7f30029e0d2e25ea9a980d84b457..8a0d38bcab6cfb357a890bede23ea2d6b1d8eb1e 100644 (file)
@@ -106,6 +106,7 @@ static int cortex_a_restore_cp15_control_reg(struct target *target)
 static int cortex_a_prep_memaccess(struct target *target, int phys_access)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        int mmu_enabled = 0;
 
        if (phys_access == 0) {
@@ -113,6 +114,12 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access)
                cortex_a_mmu(target, &mmu_enabled);
                if (mmu_enabled)
                        cortex_a_mmu_modify(target, 1);
+               if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
+                       /* overwrite DACR to all-manager */
+                       armv7a->arm.mcr(target, 15,
+                                       0, 0, 3, 0,
+                                       0xFFFFFFFF);
+               }
        } else {
                cortex_a_mmu(target, &mmu_enabled);
                if (mmu_enabled)
@@ -129,8 +136,15 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access)
 static int cortex_a_post_memaccess(struct target *target, int phys_access)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
        if (phys_access == 0) {
+               if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
+                       /* restore */
+                       armv7a->arm.mcr(target, 15,
+                                       0, 0, 3, 0,
+                                       cortex_a->cp15_dacr_reg);
+               }
                dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        } else {
                int mmu_enabled = 0;
@@ -1040,6 +1054,7 @@ static int cortex_a_internal_restore(struct target *target, int current,
        buf_set_u32(arm->pc->value, 0, 32, resume_pc);
        arm->pc->dirty = 1;
        arm->pc->valid = 1;
+
        /* restore dpm_mode at system halt */
        dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        /* called it now before restoring context because it uses cpu
@@ -1336,6 +1351,16 @@ static int cortex_a_post_debug_entry(struct target *target)
                (cortex_a->cp15_control_reg & 0x1000U) ? 1 : 0;
        cortex_a->curr_mode = armv7a->arm.core_mode;
 
+       /* switch to SVC mode to read DACR */
+       dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
+       armv7a->arm.mrc(target, 15,
+                       0, 0, 3, 0,
+                       &cortex_a->cp15_dacr_reg);
+
+       LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32,
+                       cortex_a->cp15_dacr_reg);
+
+       dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        return ERROR_OK;
 }
 
@@ -3325,6 +3350,32 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(handle_cortex_a_dacrfixup_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       static const Jim_Nvp nvp_dacrfixup_modes[] = {
+               { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
+               { .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
+               { .name = NULL, .value = -1 },
+       };
+       const Jim_Nvp *n;
+
+       if (CMD_ARGC > 0) {
+               n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
+               if (n->name == NULL)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               cortex_a->dacrfixup_mode = n->value;
+
+       }
+
+       n = Jim_Nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
+       command_print(CMD_CTX, "cortex_a domain access control fixup %s", n->name);
+
+       return ERROR_OK;
+}
+
 static const struct command_registration cortex_a_exec_command_handlers[] = {
        {
                .name = "cache_info",
@@ -3366,7 +3417,14 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
                .help = "mask cortex_a interrupts",
                .usage = "['on'|'off']",
        },
-
+       {
+               .name = "dacrfixup",
+               .handler = handle_cortex_a_dacrfixup_command,
+               .mode = COMMAND_EXEC,
+               .help = "set domain access control (DACR) to all-manager "
+                       "on memory access",
+               .usage = "['on'|'off']",
+       },
 
        COMMAND_REGISTRATION_DONE
 };
index d33188ffcff98eb8557f696d19c556e90c7f1e2c..1c63588e2b2913a240c5b67215c1877aa12bae37 100644 (file)
@@ -60,6 +60,11 @@ enum cortex_a_isrmasking_mode {
        CORTEX_A_ISRMASK_ON,
 };
 
+enum cortex_a_dacrfixup_mode {
+       CORTEX_A_DACRFIXUP_OFF,
+       CORTEX_A_DACRFIXUP_ON
+};
+
 struct cortex_a_brp {
        int used;
        int type;
@@ -78,9 +83,12 @@ struct cortex_a_common {
        uint32_t cp15_control_reg;
        /* latest cp15 register value written and cpsr processor mode */
        uint32_t cp15_control_reg_curr;
+       /* auxiliary control reg */
+       uint32_t cp15_aux_control_reg;
+       /* DACR */
+       uint32_t cp15_dacr_reg;
        enum arm_mode curr_mode;
 
-
        /* Breakpoint register pairs */
        int brp_num_context;
        int brp_num;
@@ -96,6 +104,7 @@ struct cortex_a_common {
        uint32_t didr;
 
        enum cortex_a_isrmasking_mode isrmasking_mode;
+       enum cortex_a_dacrfixup_mode dacrfixup_mode;
 
        struct armv7a_common armv7a_common;