Skip to content

Commit

Permalink
i#3544 RV64: Fix patch_stub for unaligned stub_pc (#6711)
Browse files Browse the repository at this point in the history
To simplify codegen, we require the exit stub pc to be aligned to 4
bytes. If it is not aligned, we place a 2-byte `c.nop` at the beginning
of the exit stub. Therefore, all functions that modify the exit stub
should skip the possible `c.nop`.

The wrongly implemented `patch_stub()` makes `unlink_branch()` not
affect the exit stub, which makes the async signal handling error-prone.

Before the fix, it hits the following assertion ~1/5 times when running
`linux.signal0001` on a RISC-V machine, which indicates that the second
signal comes from a different fragment after the unlinking, and the real
reason is that the unlinking is not successful.

```
ASSERT signal.c:4954 info->interrupted == NULL || info->interrupted == f
```

It would be great if we could enable the signal tests in CI, but these
tests do not work in QEMU for unknown reasons.

Issue: #3544
Related: #2328
  • Loading branch information
ksco authored Mar 19, 2024
1 parent 88d234b commit b2e6177
Showing 1 changed file with 3 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/arch/riscv64/emit_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ void
patch_stub(fragment_t *f, cache_pc stub_pc, cache_pc target_pc, cache_pc target_prefix_pc,
bool hot_patch)
{
/* If stub_pc is not aligned to 4 bytes, the first instruction will be c.nop, see
* insert_exit_stub_other_flags(). */
stub_pc = ALIGNED(stub_pc, 4) ? stub_pc : stub_pc + 2;
ptr_int_t off = (ptr_int_t)target_pc - (ptr_int_t)stub_pc;
if (off < 0x100000 && off > (ptr_int_t)0xFFFFFFFFFFF00000L) {
/* target_pc is a near fragment. We can get there with a J (OP_jal, 21-bit signed
Expand Down

0 comments on commit b2e6177

Please sign in to comment.