armv7a: cache ttbcr and ttb0/1 on debug state entry

Instead of re-reading ttbcr and ttb0/1 whenever a virt2phys translation
is done, cache the values once when entering debug state. Use the cached
values in armv7a_mmu_translate_va().

Change-Id: I1bc5349ad2f19b2dd75bdd48468a2c1f1e028699
Signed-off-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-on: http://openocd.zylin.com/3112
Tested-by: jenkins
This commit is contained in:
Matthias Welwarsky 2015-11-15 09:18:57 +01:00
parent f18ca510b3
commit bfc5c764df
2 changed files with 20 additions and 28 deletions

View File

@ -129,9 +129,13 @@ static int armv7a_read_ttbcr(struct target *target)
struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_common *armv7a = target_to_armv7a(target);
struct arm_dpm *dpm = armv7a->arm.dpm; struct arm_dpm *dpm = armv7a->arm.dpm;
uint32_t ttbcr, ttbcr_n; uint32_t ttbcr, ttbcr_n;
int retval = dpm->prepare(dpm); int ttbidx;
int retval;
retval = dpm->prepare(dpm);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto done; goto done;
/* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
retval = dpm->instr_read_data_r0(dpm, retval = dpm->instr_read_data_r0(dpm,
ARMV4_5_MRC(15, 0, 0, 2, 0, 2), ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
@ -145,6 +149,15 @@ static int armv7a_read_ttbcr(struct target *target)
armv7a->armv7a_mmu.ttbcr = ttbcr; armv7a->armv7a_mmu.ttbcr = ttbcr;
armv7a->armv7a_mmu.cached = 1; armv7a->armv7a_mmu.cached = 1;
for (ttbidx = 0; ttbidx < 2; ttbidx++) {
/* MRC p15,0,<Rt>,c2,c0,ttbidx */
retval = dpm->instr_read_data_r0(dpm,
ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
&armv7a->armv7a_mmu.ttbr[ttbidx]);
if (retval != ERROR_OK)
goto done;
}
/* /*
* ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition), * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
* document # ARM DDI 0406C * document # ARM DDI 0406C
@ -182,42 +195,21 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
uint32_t second_lvl_descriptor = 0x0; uint32_t second_lvl_descriptor = 0x0;
int retval; int retval;
struct armv7a_common *armv7a = target_to_armv7a(target); struct armv7a_common *armv7a = target_to_armv7a(target);
struct arm_dpm *dpm = armv7a->arm.dpm;
uint32_t ttbidx = 0; /* default to ttbr0 */ uint32_t ttbidx = 0; /* default to ttbr0 */
uint32_t ttb_mask; uint32_t ttb_mask;
uint32_t va_mask; uint32_t va_mask;
uint32_t ttbcr;
uint32_t ttb; uint32_t ttb;
retval = dpm->prepare(dpm); if (target->state != TARGET_HALTED)
if (retval != ERROR_OK) LOG_INFO("target not halted, using cached values for translation table!");
goto done;
/* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
retval = dpm->instr_read_data_r0(dpm,
ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
&ttbcr);
if (retval != ERROR_OK)
goto done;
/* if ttbcr has changed or was not read before, re-read the information */
if ((armv7a->armv7a_mmu.cached == 0) ||
(armv7a->armv7a_mmu.ttbcr != ttbcr)) {
armv7a_read_ttbcr(target);
}
/* if va is above the range handled by ttbr0, select ttbr1 */ /* if va is above the range handled by ttbr0, select ttbr1 */
if (va > armv7a->armv7a_mmu.ttbr_range[0]) { if (va > armv7a->armv7a_mmu.ttbr_range[0]) {
/* select ttb 1 */ /* select ttb 1 */
ttbidx = 1; ttbidx = 1;
} }
/* MRC p15,0,<Rt>,c2,c0,ttbidx */
retval = dpm->instr_read_data_r0(dpm,
ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
&ttb);
if (retval != ERROR_OK)
return retval;
ttb = armv7a->armv7a_mmu.ttbr[ttbidx];
ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx]; ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx];
va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx]; va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx];
@ -279,9 +271,6 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
} }
return ERROR_OK; return ERROR_OK;
done:
return retval;
} }
/* V7 method VA TO PA */ /* V7 method VA TO PA */
@ -740,6 +729,8 @@ int armv7a_arch_state(struct target *target)
arm_arch_state(target); arm_arch_state(target);
armv7a_read_ttbcr(target);
if (armv7a->is_armv7r) { if (armv7a->is_armv7r) {
LOG_USER("D-Cache: %s, I-Cache: %s", LOG_USER("D-Cache: %s, I-Cache: %s",
state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],

View File

@ -87,6 +87,7 @@ struct armv7a_mmu_common {
/* following field mmu working way */ /* following field mmu working way */
int32_t cached; /* 0: not initialized, 1: initialized */ int32_t cached; /* 0: not initialized, 1: initialized */
uint32_t ttbcr; /* cache for ttbcr register */ uint32_t ttbcr; /* cache for ttbcr register */
uint32_t ttbr[2];
uint32_t ttbr_mask[2]; uint32_t ttbr_mask[2];
uint32_t ttbr_range[2]; uint32_t ttbr_range[2];