Skip to content
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: Reject size 2 soft breakpoints when C extension not supported #908

Conversation

MarekVCodasip
Copy link
Collaborator

This patch disables software breakpoints of size 2 for targets which don't support compressed instructions.

Change-Id: I8200b22a51c97ba2aa89e6328beadde8dd35cdd5

src/target/riscv/riscv.c Outdated Show resolved Hide resolved
src/target/riscv/riscv.c Show resolved Hide resolved
src/target/riscv/riscv.c Outdated Show resolved Hide resolved
@MarekVCodasip MarekVCodasip force-pushed the disable-soft-bp-size-2-non-compressed branch from 159a49d to 58fd2a3 Compare August 28, 2023 06:40
JanMatCodasip
JanMatCodasip previously approved these changes Aug 28, 2023
Copy link
Collaborator

@JanMatCodasip JanMatCodasip left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

src/target/riscv/riscv.c Outdated Show resolved Hide resolved
JanMatCodasip
JanMatCodasip previously approved these changes Aug 28, 2023
Copy link
Collaborator

@timsifive timsifive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. Just have an OpenOCD style comment.

src/target/riscv/riscv.c Outdated Show resolved Hide resolved
…ported

This patch disables software breakpoints of size 2 for targets
which don't support compressed instructions.

Change-Id: I8200b22a51c97ba2aa89e6328beadde8dd35cdd5
Signed-off-by: Marek Vrbka <[email protected]>
@MarekVCodasip MarekVCodasip force-pushed the disable-soft-bp-size-2-non-compressed branch from 1faadde to 8ad4176 Compare September 4, 2023 05:47
@timsifive timsifive merged commit 54372dd into riscv-collab:riscv Sep 7, 2023
5 checks passed
/** @todo check RVC for size/alignment */
if (!(breakpoint->length == 4 || breakpoint->length == 2)) {
LOG_TARGET_ERROR(target, "Invalid breakpoint length %d", breakpoint->length);
const bool c_extension_supported = riscv_supports_extension(target, 'C');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a code size reduction isa called Zc*(ratified), see https://github.com/riscv/riscv-code-size-reduction

If Zc extension is used, the instruction can be also 16 bit, so this check by just riscv_supports_extension(target, 'C') maybe not correct, since as described here riscvarchive/riscv-code-size-reduction#144 (comment), this misa.c only set when all normal compress instruction are implemented, but in some case, for example, rv32imaf_zca, it will not set misa.c bit, but it still contains 16 bit instruction, so I think sw breakpoint can still set here, so the check by misa.c bit is not enough.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @MarekVCodasip @timsifive @tariqkurd-repo , is there any feedback on my comments regarding the new added Zc* extensions will affect this compress instructions existing checking.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing Zca and not C will not set misa.C
I think you actually need to specify C to set it
Is that your understanding @aswaterman ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing Zca and not C will not set misa.C I think you actually need to specify C to set it Is that your understanding @aswaterman ?

If I implement rv32imaf_zca_zcb_zcf_zcmp_zcmt it contains all C required zca_zcf will the misa.C bit be set? This riscv_supports_extension function only use the misa.C bit to check whether compressed instructions are supported.

@TommyMurphyTM1234
Copy link
Collaborator

TommyMurphyTM1234 commented Oct 7, 2023

Are there specific reasons not to simply always use the "lowest common denominator" of 32-bit software breakpoints regardless of the target's 16-bit instruction capabilities? Off the top of my head the only one that I can think of is the inability to write one at the instruction address 2 bytes from the "top" of a memory region. Are there other reasons not to just take the simpler approach?

@JanMatCodasip
Copy link
Collaborator

JanMatCodasip commented Oct 12, 2023

TommyMurphyTM1234: Are there specific reasons not to simply always use the "lowest common denominator" of 32-bit software breakpoints regardless of the target's 16-bit instruction capabilities?

By placing a SW breakpoint (ebreak or c.ebreak), we must not overwrite any other instruction than the one on which the break is placed. That's because the subsequent instruction after the break can be a target of a branch. And as such, it must remain intact.

Using always the 32-bit SW breaks is therefore not an option.

@TommyMurphyTM1234
Copy link
Collaborator

TommyMurphyTM1234 commented Oct 12, 2023

TommyMurphyTM1234: Are there specific reasons not to simply always use the "lowest common denominator" of 32-bit software breakpoints regardless of the target's 16-bit instruction capabilities?

By placing a SW breakpoint (ebreak or c.ebreak), we must not overwrite any other instruction than the one on which the break is placed. That's because the subsequent instruction after the break can be a target of a branch. And as such, it must remain intact.

Using always the 32-bit SW breaks is therefore not an option.

Thanks for that explanation @JanMatCodasip 👍

@fanghuaqi
Copy link
Contributor

Hi @MarekVCodasip @timsifive @JanMatCodasip , using this commit, I am not able to set breakpoint at 2 bytes aligned address, with Zc* extension enabled which also provided compressed instructions.

image

@JanMatCodasip
Copy link
Collaborator

@fanghuaqi

Is there a reliable way how OpenOCD can detect the c.ebreak support in the target hardware, please?

  • If so, we may consider implementing it in OpenOCD.
  • Otherwise we should probably revert/rework this commit, and simply obey the breakpoint length as asked by GDB (or by the user).

@fanghuaqi
Copy link
Contributor

@fanghuaqi

Is there a reliable way how OpenOCD can detect the c.ebreak support in the target hardware, please?

  • If so, we may consider implementing it in OpenOCD.
  • Otherwise we should probably revert/rework this commit, and simply obey the breakpoint length as asked by GDB (or by the user).

Hi @JanMatCodasip , I didn't know whether there is a way to check whether c.ebreak supported in hardware, don't DM provide some information about it? If not, may be make some notes in the doc will be good.

@TommyMurphyTM1234
Copy link
Collaborator

TommyMurphyTM1234 commented Oct 19, 2023

Earlier:

it was stated that:

There is a code size reduction isa called Zc*(ratified), see https://github.com/riscv/riscv-code-size-reduction

If Zc extension is used, the instruction can be also 16 bit

But, as far as I can see, support for c.ebreak is orthogonal to support for the Zc* extension/sub-extensions.

The Zc* extension/sub-extensions make no mention of c.ebreak - only The RISC-V Instruction Set Manual
Volume I: Unprivileged ISA mentions/specifies it.

That being the case shouldn't a check of $misa for the C bit being set should be sufficient for checking if the target supports c.ebreak?

@TommyMurphyTM1234
Copy link
Collaborator

TommyMurphyTM1234 commented Oct 19, 2023

Perhaps this is another option?

this patch instead examines
the existing instruction at a breakpoint target to determine which
breakpoint instruction to use. If the existing instruction is a
compressed instruction, C.EBREAK is used, otherwise EBREAK is used.

@timsifive
Copy link
Collaborator

The simple option is to revert this change. gdb already has good logic to decide what breakpoint size to use, because it knows what size instruction is being replaced.

What was the original reason for this change? I don't see a rationale in the description.

@timsifive
Copy link
Collaborator

From what I can tell, c.ebreak is defined in the unprivileged spec, where it is part of the "C" Standard Extension chapter. That means to me that if c.ebreak is implemented then misa.C must be set.

That feels like a spec bug, though. If you are allowed to implement 16-bit instructions without setting misa.C, which the Zc* extensions clearly do, then obviously you want c.ebreak as well, without being required to implement all the other C extension instructions. I filed riscvarchive/riscv-code-size-reduction#228 for this.

I would expect the outcome to be something that allows c.ebreak even without C, and the result for OpenOCD is that we should revert this change.

@fanghuaqi
Copy link
Contributor

c.break is part of Zca which is the only part of C without(compressed F/D instructions).

@@ -1198,15 +1198,17 @@ static int riscv_add_breakpoint(struct target *target, struct breakpoint *breakp
LOG_TARGET_DEBUG(target, "@0x%" TARGET_PRIxADDR, breakpoint->address);
assert(breakpoint);
if (breakpoint->type == BKPT_SOFT) {
/** @todo check RVC for size/alignment */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timsifive I think this patch is added due to there is a todo here, is it possible to check whether 16bit instruction execute ok without any exception, such as test c.nop, if no exception, compress instruction is supported, otherwise no.

@JanMatCodasip
Copy link
Collaborator

JanMatCodasip commented Oct 20, 2023

Tim: The simple option is to revert this change.

I am in agreement.

Tim: What was the original reason for this change? I don't see a rationale in the description.

The reason was to prevent user mistakes and improve robustness (an attempt that in the end has the opposite effect: additional issues).

@TommyMurphyTM1234
Copy link
Collaborator

c.break is part of Zca which is the only part of C without(compressed F/D instructions).

Did you mean c.ebreak?
Can you clarify where in the Zc* spec that is stated?
I couldn't see it.

@fanghuaqi
Copy link
Contributor

c.break is part of Zca which is the only part of C without(compressed F/D instructions).

Did you mean c.ebreak? Can you clarify where in the Zc* spec that is stated? I couldn't see it.

Hi @TommyMurphyTM1234 , please check it here riscvarchive/riscv-code-size-reduction@4abffe7

@TommyMurphyTM1234
Copy link
Collaborator

c.break is part of Zca which is the only part of C without(compressed F/D instructions).

Did you mean c.ebreak? Can you clarify where in the Zc* spec that is stated? I couldn't see it.

Hi @TommyMurphyTM1234 , please check it here riscv/riscv-code-size-reduction@4abffe7

The ratified Zc* extension is listed here:

The ratified specification does not mention c.ebreak or the text in the commit that you linked to.

Are you referring to some proposed draft update?
I still don't see how what you linked to clarifies that Zc* necessarily implies support for c.ebreak.

@timsifive
Copy link
Collaborator

@TommyMurphyTM1234, see riscvarchive/riscv-code-size-reduction#228.

TLDR: Every Zc* requires Zca, and Zca is all of the existing C extension, except some 16-bit floating point ops.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants