fix software breakpoints on xscale

This patch fixes xscale software breakpoints by cleaning the dcache and
invalidating the icache after the bkpt instruction is inserted or removed.  The
icache operation is necessary in order to flush the fetch buffers, even if the
icache is disabled (see section 4.2.7 of the xscale core developer's manual).
The dcache is presumed to be enabled; no harm done if not.  The dcache is also
invalidated after cleaning in order to safeguard against a future load of
invalid data, in the event that cache_clean_address points to memory that is
valid and in use.

Also corrected a confusing typo I noticed in a comment.

TODO (or not TODO...?): the xscale's 2K "mini dcache" is not cleaned.  This
cache is not used unless the 'X' bit in the page table entry is set.  This is a
proprietary xscale extension to the ARM architecture.  If a target's OS or
executive makes use of this for memory regions holding code, the breakpoint
problem will persist.  Flushing the mini dcache requires that 2K of valid
cacheable memory (mapped with 'X' bit set) be designated by the user for this
purpose.  The debug handler that gets downloaded to the target will also need to
be extended.
This commit is contained in:
Mike Dunn 2010-03-20 10:53:47 -04:00 committed by Øyvind Harboe
parent ccfaed8bc7
commit 4be9eded7f
1 changed files with 12 additions and 2 deletions

View File

@ -2125,7 +2125,7 @@ static int xscale_set_breakpoint(struct target *target,
{
return retval;
}
/* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
/* write the bkpt instruction in target endianness (arm7_9->arm_bkpt is host endian) */
if ((retval = target_write_u32(target, breakpoint->address, xscale->arm_bkpt)) != ERROR_OK)
{
return retval;
@ -2138,13 +2138,18 @@ static int xscale_set_breakpoint(struct target *target,
{
return retval;
}
/* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
/* write the bkpt instruction in target endianness (arm7_9->arm_bkpt is host endian) */
if ((retval = target_write_u32(target, breakpoint->address, xscale->thumb_bkpt)) != ERROR_OK)
{
return retval;
}
}
breakpoint->set = 1;
xscale_send_u32(target, 0x50); /* clean dcache */
xscale_send_u32(target, xscale->cache_clean_address);
xscale_send_u32(target, 0x51); /* invalidate dcache */
xscale_send_u32(target, 0x52); /* invalidate icache and flush fetch buffers */
}
return ERROR_OK;
@ -2225,6 +2230,11 @@ static int xscale_unset_breakpoint(struct target *target,
}
}
breakpoint->set = 0;
xscale_send_u32(target, 0x50); /* clean dcache */
xscale_send_u32(target, xscale->cache_clean_address);
xscale_send_u32(target, 0x51); /* invalidate dcache */
xscale_send_u32(target, 0x52); /* invalidate icache and flush fetch buffers */
}
return ERROR_OK;