You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thanks for building Unicorn! It's been very helpful in my project.
I've been trying to emulate the behavior of a toy operating system using Unicorn so that I can run its applications on other operating systems and architectures. I'm using interrupt hooks to react to synchronous exceptions such as system calls, invalid instruction exceptions, and page faults.
Unfortunately Unicorn's treatment of the program counter in interrupt hooks is slightly incompatible with the RISC-V specification: when handling an exception it increments the program counter by 4 while the ISA specification1 calls for the exception program counter register (mepc in M-Mode, sepc in S-Mode) to contain the address of the instruction that caused the exception.
I see that this was added intentionally in response to #1477, but this makes it hard to treat exceptions the same way as real hardware would.
I think it's also a little flawed: this behavior is plausible for ecall because that instruction is always encoded in 4 bytes, but other exception types can be caused by 2-byte instructions from the "C" extension. For example, the C.LW instruction is 2 bytes long and can generate a page fault, which would then cause pc to be pointing to an incorrect address in the interrupt hook.
I understand that existing callers are probably depending on the current behavior successfully for ecall, and they might not care about handling other fault types or might not be using 2-byte instructions. Therefore I assume maintainers would prefer to keep the current behavior even though it produces a wrong result in some cases.
Therefore I'm not really sure what to suggest. For now I think I'm going to work around this by having my program immediately subtract 4 from the program counter on entry into my interrupt hook. That should work for now because Unicorn unconditionally adds 4 regardless of the exception type or instruction length, but I would be broken if a future Unicorn release would change to only add two to pc for a fault on a 2-byte instruction. 🤔
Is it reasonable for me to assume that the current behavior will never change in future? Although not ideal, I'd be satisfied with this just being documented that on RISC-V the interrupt hook is always called with the program counter set four bytes too high, as long as I can rely on that remaining true in future.
Thanks for building Unicorn! It's been very helpful in my project.
I've been trying to emulate the behavior of a toy operating system using Unicorn so that I can run its applications on other operating systems and architectures. I'm using interrupt hooks to react to synchronous exceptions such as system calls, invalid instruction exceptions, and page faults.
Unfortunately Unicorn's treatment of the program counter in interrupt hooks is slightly incompatible with the RISC-V specification: when handling an exception it increments the program counter by 4 while the ISA specification1 calls for the exception program counter register (
mepc
in M-Mode,sepc
in S-Mode) to contain the address of the instruction that caused the exception.unicorn/qemu/accel/tcg/cpu-exec.c
Lines 386 to 389 in d4b9248
I see that this was added intentionally in response to #1477, but this makes it hard to treat exceptions the same way as real hardware would.
I think it's also a little flawed: this behavior is plausible for
ecall
because that instruction is always encoded in 4 bytes, but other exception types can be caused by 2-byte instructions from the "C" extension. For example, theC.LW
instruction is 2 bytes long and can generate a page fault, which would then causepc
to be pointing to an incorrect address in the interrupt hook.I understand that existing callers are probably depending on the current behavior successfully for
ecall
, and they might not care about handling other fault types or might not be using 2-byte instructions. Therefore I assume maintainers would prefer to keep the current behavior even though it produces a wrong result in some cases.Therefore I'm not really sure what to suggest. For now I think I'm going to work around this by having my program immediately subtract 4 from the program counter on entry into my interrupt hook. That should work for now because Unicorn unconditionally adds 4 regardless of the exception type or instruction length, but I would be broken if a future Unicorn release would change to only add two to
pc
for a fault on a 2-byte instruction. 🤔Is it reasonable for me to assume that the current behavior will never change in future? Although not ideal, I'd be satisfied with this just being documented that on RISC-V the interrupt hook is always called with the program counter set four bytes too high, as long as I can rely on that remaining true in future.
Thanks again!
1 The RISC-V Instruction Set Manual: Volume II: Privileged Architecture, version 20240411, section 3.1.14
The text was updated successfully, but these errors were encountered: