-
Notifications
You must be signed in to change notification settings - Fork 328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
target/riscv: check abstractcs.busy
#1023
Conversation
a36ecb2
to
f138cd2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch.
As for the code, I have minor comments about naming.
As for the whole concept of this change:
- In function examine_dm() we believe with @JanMatCodasip that the check of busy is warranted.
- In the other functions it looks to us that
assert(!ac_busy)
would be more appropriate. Because the preceding command should always clean up after itself and leaveabstractcs.busy == 0
. Let us know what do you think and what was the rationale behind these checks to many places in the code. We don't mind keeping these as is, but still believe asserts are more appropriate in most places.
Thank you.
Or, possibly Still, it seems to me that OpenOCD code itself should ensure that DM is left in a clean state (including abstractcs.busy==0) when any command completes. That means should be possible to start a new command without checking if busy==0. (An exception from this rule could be malfunctioning hardware in which abstractcs.busy remains stuck at 1 for some reason, and I am afraid we cannot do much about that in OpenOCD in general.) If there is a command that can leave the DM in an unclean state, then that place should be fixed. Safety checks at the beginning of other commands seem like a good idea, but please preferably in the form of assertions or LOG_ERROR("BUG: ..."), making it very clear to the reader that these are safety checks that guard against cases that ideally should never happen. In any case, thank you for the time invested into the patch. For example the refactor of examine is beneficial in its own right 👍 |
Currently, in general, working with abstract commands is something along the lines of:
However, the loop in So, let's consider the following OpenOCD session:
I see a couple of options how to fix this:
|
f138cd2
to
7e3bc17
Compare
Thank you for the explanation. It really helped me to understand the idea behind the proposed changes.
For completeness, I can imagine two more options:
But anyway, I believe your chosen solution (point 3 above) is fine and I am in favor of it. I have posted several comments with the aim to make the intention behind the changes more clear to the reader of the code. Please let me know if you are OK with the suggestions. I don't expect to have any more review comments than what I have posted so far. Thank you. |
src/target/riscv/riscv-013.c
Outdated
if (!dm->abtractcs_busy) | ||
LOG_TARGET_ERROR(target, "BUG: dm->abtractcs_busy was not set in time!"); | ||
dm->abtractcs_busy = true; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks to me that this safety check can be moved to the top of the function. I believe it is the caller's responsibility to set dm->abstractcs_busy = true
, so we can move this check to the top.
Is that correct understanding? If so, I'd prefer to move this block.
Maybe the error message can also be updated to make it even clearer (if you like):
if (!dm->abtractcs_busy) | |
LOG_TARGET_ERROR(target, "BUG: dm->abtractcs_busy was not set in time!"); | |
dm->abtractcs_busy = true; | |
if (!dm->abtractcs_busy) | |
LOG_TARGET_ERROR(target, "BUG: dm->abtractcs_busy was not set at the start of abstract command"); | |
dm->abtractcs_busy = true; | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to leave it as-is.
It is convenient to use wait_for_idle()
as a default error handler in case there was a call to a subroutine which may execute an abstract command but may fail before executing the command.
I am not ready to pledge that that there are no such uses currently.
IMHO, it is desirable for wait_for_idle()
to be a NOP (apart from one read of abstractcs
) in case there was no abstract command execution to begin with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, understood, thank you for explanation.
Still, could we still change the wording a bit to make it clearer what has happened? For example as shown below:
if (!dm->abstract_cmd_maybe_busy)
LOG_TARGET_ERROR(target, "BUG: dm->abstract_cmd_maybe_busy had not been set when starting an abstract command");
dm->abstract_cmd_maybe_busy = true;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.
src/target/riscv/riscv-013.c
Outdated
/* Note, that this does not mean the DM was just reset. */ | ||
dm->was_reset = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment was a bit hard to grasp to me.
Instead, I'd recommend to move the was_reset = true
to line 1974 where the reset actually takes place, and the comment can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to leave it as-is.
On the line you mentioned reset of the DM is initiated.
However, we can not be sure the DM successfully came out of the reset.
It can be established only after dmcontrol.dmactive
was observed in a value read from the DM, which is exactly what happens here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, understood.
In that case, how about updating the comment as follows, to make it clearer what the was_reset = true
actually means:
/* Note, that this does not mean the DM was just reset. */ | |
dm->was_reset = true; | |
/* The DM has been reset and has successfully come out of the reset (dmactive=1): | |
* - either the reset has been performed by this function (above); | |
* - or the reset had already happened in an earlier call of examine_dm() when | |
* examining a different hart. | |
*/ | |
dm->was_reset = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.
9ea7085
to
8f6965b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, thank you, approved.
There are only two last threads open that deal with less important items (log prints and comments).
According to the RISC-V Debug Spec (1.0.0-rc1)[3.7 Abstract Commands]: > While an abstract command is executing (busy in abstractcs is high), a debugger must not change hartsel, and must not write 1 to haltreq, resumereq, ackhavereset, setresethaltreq, or clrresethaltreq. Tracking `abstractcs.busy` allows to enforce this rule. Change-Id: If5975b48cf9fd379033268145c79103c36fb8134 Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
8f6965b
to
ec52b39
Compare
This allows to examine each DM ones (e.g. enumerating harts assigned to the DM). Additionaly, it is guaranteed that the DM is reset before the examination. Change-Id: I2333d06ff1152bf51c647d59baa55cb402054cb9 Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
According to the RISC-V Debug Spec (1.0.0-rc1)[3.7 Abstract Commands]: > While an abstract command is executing (busy in abstractcs is high), a debugger must not change hartsel, and must not write 1 to haltreq, resumereq, ackhavereset, setresethaltreq, or clrresethaltreq. The patch ensures the rule is followed. Change-Id: Id7d363d9fdeb365181b7058e0ceb0be0df39654f Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
ec52b39
to
34d6fe3
Compare
According to the RISC-V Debug Spec (1.0.0-rc1)[3.7 Abstract Commands]:
This patch ensures OpenOCD does not violate this rule.
The patch is separated into three commits.
abstractcs.busy
indm013_info_t
-- provides facilities to track the state ofabstractcs.busy
examine_dm()
function -- ensures the rule is followed during examination.abstractcs.busy
-- takes care of other cases.