arm7_9_common: fix host endianness bug in arm7_9_full_context()
The original code passes to ->read_core_regs() and to ->read_xpsr() the pointer to the little-endian buffer reg.value. This is incorrect because the two functions above require a pointer to uint32_t, since they already run the conversion with arm_le_to_h_u32() in the jtag callback. This causes a mismatch on big-endian host and the registers get read with the incorrect endianness. Use an intermediate buffer to read the registers as uint32_t and to track the destination reg.value pointer, then copy the value in reg.value after the call to jtag_execute_queue(). Tested with qemu-armeb and an OpenOCD built through buildroot configured for cortex-a7 big-endian. Note that if jtag_execute_queue() fails, the openocd register cache is not updated, so the already modified flags 'valid' and 'dirty' are incorrect. This part should be moved after the call to jtag_execute_queue() too. Change-Id: Iba70d964ffbb74bf0860bfd9d299f218e3bc65bf Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/5943 Tested-by: jenkins Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
This commit is contained in:
parent
62686ab161
commit
a56b729191
|
@ -1391,6 +1391,11 @@ static int arm7_9_full_context(struct target *target)
|
||||||
int retval;
|
int retval;
|
||||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||||
struct arm *arm = &arm7_9->arm;
|
struct arm *arm = &arm7_9->arm;
|
||||||
|
struct {
|
||||||
|
uint32_t value;
|
||||||
|
void *reg_p;
|
||||||
|
} read_cache[6 * (16 + 1)];
|
||||||
|
int read_cache_idx = 0;
|
||||||
|
|
||||||
LOG_DEBUG("-");
|
LOG_DEBUG("-");
|
||||||
|
|
||||||
|
@ -1433,10 +1438,12 @@ static int arm7_9_full_context(struct target *target)
|
||||||
for (j = 0; j < 15; j++) {
|
for (j = 0; j < 15; j++) {
|
||||||
if (!ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
if (!ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
armv4_5_number_to_mode(i), j).valid) {
|
armv4_5_number_to_mode(i), j).valid) {
|
||||||
reg_p[j] = (uint32_t *)ARMV4_5_CORE_REG_MODE(
|
read_cache[read_cache_idx].reg_p = ARMV4_5_CORE_REG_MODE(
|
||||||
arm->core_cache,
|
arm->core_cache,
|
||||||
armv4_5_number_to_mode(i),
|
armv4_5_number_to_mode(i),
|
||||||
j).value;
|
j).value;
|
||||||
|
reg_p[j] = &read_cache[read_cache_idx].value;
|
||||||
|
read_cache_idx++;
|
||||||
mask |= 1 << j;
|
mask |= 1 << j;
|
||||||
ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
armv4_5_number_to_mode(i),
|
armv4_5_number_to_mode(i),
|
||||||
|
@ -1454,9 +1461,10 @@ static int arm7_9_full_context(struct target *target)
|
||||||
/* check if the PSR has to be read */
|
/* check if the PSR has to be read */
|
||||||
if (!ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
|
if (!ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
|
||||||
16).valid) {
|
16).valid) {
|
||||||
arm7_9->read_xpsr(target,
|
read_cache[read_cache_idx].reg_p = ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
||||||
(uint32_t *)ARMV4_5_CORE_REG_MODE(arm->core_cache,
|
armv4_5_number_to_mode(i), 16).value;
|
||||||
armv4_5_number_to_mode(i), 16).value, 1);
|
arm7_9->read_xpsr(target, &read_cache[read_cache_idx].value, 1);
|
||||||
|
read_cache_idx++;
|
||||||
ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
|
ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
|
||||||
16).valid = true;
|
16).valid = true;
|
||||||
ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
|
ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
|
||||||
|
@ -1472,6 +1480,14 @@ static int arm7_9_full_context(struct target *target)
|
||||||
retval = jtag_execute_queue();
|
retval = jtag_execute_queue();
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
/*
|
||||||
|
* FIXME: regs in cache should be tagged as 'valid' only now,
|
||||||
|
* not before the jtag_execute_queue()
|
||||||
|
*/
|
||||||
|
while (read_cache_idx) {
|
||||||
|
read_cache_idx--;
|
||||||
|
buf_set_u32(read_cache[read_cache_idx].reg_p, 0, 32, read_cache[read_cache_idx].value);
|
||||||
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue