From: Mike Dunn Date: Sun, 19 Sep 2010 21:48:51 +0000 (-0700) Subject: xscale: check that wp length does not exceed address X-Git-Tag: v0.5.0-rc1~415 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=ebfb2f4f3715f264ae4474c1b2e78812d1625cdc xscale: check that wp length does not exceed address Hi everyone, A while back I sent in a patch that adds support for watchpoint lengths greater than four on xscale. It's been working well, until the other day, when it caused an unexpected debug exception. Looking into this I realized there is a case where it breaks: when the length arg is greater than the base address. This is a consequence of the way the hardware works. Don't see a work-around, so I added code to xscale_add_watchpoint() to check for and disallow this combination. Some more detail... xscale watchpoint hardware does not support a length directly. Instead, a mask value can be specified (not to be confused with the optional mask arg to the wp command, which xscale does not support). Any bits set in the mask are ignored when the watchpoint hardware compares the access address to the watchpoint address. So as long as the length is a power of two, setting the mask to length-1 effectively specifies the length. Or so I thought, until I realized that if the length exceeds the base address, *all* bits of the base address are ignored by the comaparator, and the watchpoint range effectively becomes 0 .. length. Questions, comments, criticisms gratefully received. Thanks, Mike Signed-off-by: Mike Dunn --- diff --git a/src/target/xscale.c b/src/target/xscale.c index 77f0f1b892..37a243857c 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -2401,6 +2401,13 @@ static int xscale_add_watchpoint(struct target *target, return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } + if (watchpoint->length > watchpoint->address) + { + LOG_ERROR("xscale does not support watchpoints with length " + "greater than address"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + xscale->dbr_available = 0; return ERROR_OK; }