cortex_a: add 'dacrfixup' to cortex-a command group

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>
__archive__
Matthias Welwarsky 2015-11-24 22:11:56 +01:00 committed by Andreas Fritiofson
parent 082417fc71
commit 5bee7f5b2c
3 changed files with 76 additions and 2 deletions

View File

@ -7678,6 +7678,13 @@ Disabled by default
display information about target caches display information about target caches
@end deffn @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} @deffn Command {cortex_a dbginit}
Initialize core debug Initialize core debug
Enables debug by unlocking the Software Lock and clearing sticky powerdown indications Enables debug by unlocking the Software Lock and clearing sticky powerdown indications

View 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) static int cortex_a_prep_memaccess(struct target *target, int phys_access)
{ {
struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_common *armv7a = target_to_armv7a(target);
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
int mmu_enabled = 0; int mmu_enabled = 0;
if (phys_access == 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); cortex_a_mmu(target, &mmu_enabled);
if (mmu_enabled) if (mmu_enabled)
cortex_a_mmu_modify(target, 1); 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 { } else {
cortex_a_mmu(target, &mmu_enabled); cortex_a_mmu(target, &mmu_enabled);
if (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) static int cortex_a_post_memaccess(struct target *target, int phys_access)
{ {
struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_common *armv7a = target_to_armv7a(target);
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
if (phys_access == 0) { 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); dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
} else { } else {
int mmu_enabled = 0; 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); buf_set_u32(arm->pc->value, 0, 32, resume_pc);
arm->pc->dirty = 1; arm->pc->dirty = 1;
arm->pc->valid = 1; arm->pc->valid = 1;
/* restore dpm_mode at system halt */ /* restore dpm_mode at system halt */
dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
/* called it now before restoring context because it uses cpu /* 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->cp15_control_reg & 0x1000U) ? 1 : 0;
cortex_a->curr_mode = armv7a->arm.core_mode; 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; return ERROR_OK;
} }
@ -3325,6 +3350,32 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
return ERROR_OK; 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[] = { static const struct command_registration cortex_a_exec_command_handlers[] = {
{ {
.name = "cache_info", .name = "cache_info",
@ -3366,7 +3417,14 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
.help = "mask cortex_a interrupts", .help = "mask cortex_a interrupts",
.usage = "['on'|'off']", .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 COMMAND_REGISTRATION_DONE
}; };

View File

@ -60,6 +60,11 @@ enum cortex_a_isrmasking_mode {
CORTEX_A_ISRMASK_ON, CORTEX_A_ISRMASK_ON,
}; };
enum cortex_a_dacrfixup_mode {
CORTEX_A_DACRFIXUP_OFF,
CORTEX_A_DACRFIXUP_ON
};
struct cortex_a_brp { struct cortex_a_brp {
int used; int used;
int type; int type;
@ -78,9 +83,12 @@ struct cortex_a_common {
uint32_t cp15_control_reg; uint32_t cp15_control_reg;
/* latest cp15 register value written and cpsr processor mode */ /* latest cp15 register value written and cpsr processor mode */
uint32_t cp15_control_reg_curr; 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; enum arm_mode curr_mode;
/* Breakpoint register pairs */ /* Breakpoint register pairs */
int brp_num_context; int brp_num_context;
int brp_num; int brp_num;
@ -96,6 +104,7 @@ struct cortex_a_common {
uint32_t didr; uint32_t didr;
enum cortex_a_isrmasking_mode isrmasking_mode; enum cortex_a_isrmasking_mode isrmasking_mode;
enum cortex_a_dacrfixup_mode dacrfixup_mode;
struct armv7a_common armv7a_common; struct armv7a_common armv7a_common;