-
Notifications
You must be signed in to change notification settings - Fork 327
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
[riscv] refactor functions that register read/write via progbuf #901
[riscv] refactor functions that register read/write via progbuf #901
Conversation
The issue mentioned above can be reproduced on spike if #900 is NOT applied (apparently, #900 hides this problem). Reproduction (I've tried to reduce it and this is what I've got):
During the second invocation OpenOCD will crash due to stack overflow (because of infinite recursion). |
Note: the intention of this patch is only to fix infinite recursion. The reason we have such a situation on spike with no apparent reason is another matter. |
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 will need to return to this one again for a more thorough review. However, overall, this looks very good.
These *_progbuf functions unconditionally attempt to cache S0 register and only then perform a bunch of extra checks to figure out if the requested register is a valid one. The problem is that there are few corner cases when _*progbuf functions could receive a GPR as an input.
I fully agree. The *_progbuf
functions should refuse invalid input argument (in this case, unsupported register type) at the very beginning, before attempting any further actions.
I also support the split of the original register_{read,write}_progbuf
to the smaller functions.
src/target/riscv/riscv-013.c
Outdated
else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) | ||
return register_write_to_csr_progbuf(target, number, value); | ||
|
||
LOG_ERROR("Unsupported register: %s", gdb_regno_name(number)); |
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 tried to reword this to make it more understandable for users:
LOG_ERROR("Unsupported register: %s", gdb_regno_name(number)); | |
LOG_TARGET_ERROR(target, "Write to register %s via program buffer not supported.", gdb_regno_name(number)); |
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.
yes, will address. Thanks!
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, though, I've changed the message a little bit.
src/target/riscv/riscv-013.c
Outdated
else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) | ||
return register_read_from_csr_progbuf(target, value, number); | ||
|
||
LOG_TARGET_ERROR(target, "Unsupported register: %s", gdb_regno_name(number)); |
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.
(For clarity of the message:)
LOG_TARGET_ERROR(target, "Unsupported register: %s", gdb_regno_name(number)); | |
LOG_TARGET_ERROR(target, "Reading register %s via program buffer is not supported.", gdb_regno_name(number)); |
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 one is addressed too
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.
Looks good overall.
The motivation for this refactor is to fixup error handling for some corner cases. These functions attempt to cache S0 register and only then perform a bunch of extra checks to figure out if the requested register is valid one in this context. The problem is that there are few corner cases when _*progbuf functions could receive a GPR as an input. For example, an abstract read could fail (for whatever reason) leading to infinite recursion: ```` save S0 -> read S0 -> save S0 -> read S0 -> ... ``` The case described above could be fixed by adding extra sanitity checks, however I decided to make these functions more modular since I find self-contained functions easier to read. Change-Id: I01f57bf474ca45ebb67a30cd4d8fdef21f307c7d Signed-off-by: Parshintsev Anatoly <[email protected]>
827a76f
to
a8fedeb
Compare
The motivation for this refactor is to fixup error handling for some corner cases. These *_progbuf functions unconditionally attempt to cache S0 register and only then perform a bunch of extra checks to figure out if the requested register is a valid one. The problem is that there are few corner cases when _*progbuf functions could receive a GPR as an input. For example, an abstract read could fail (for whatever reason) leading to infinite recursion:
The case described above could be fixed by adding extra sanitity checks, however I decided to make these functions more modular since I find self-contained functions easier to read.
Change-Id: I01f57bf474ca45ebb67a30cd4d8fdef21f307c7d