#2402·unicorn

RISC-V: allow guest trap handlers to receive exceptions

Author: KreijstalCreated Aug 20, 2026Updated Aug 20, 2026

Unicorn does not perform RISC-V trap entry when an instruction raises an exception.

For example:

c
uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc);

uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL);
uc_mem_write(uc, 0x1000, "\x73\x00\x00\x00", 4); /* ecall */

uint64_t mtvec = 0x1800;
uc_reg_write(uc, UC_RISCV_REG_MTVEC, &mtvec);

uc_emu_start(uc, 0x1000, 0, 0, 1);

After an M-mode ecall, RISC-V requires:

pc     = 0x1800
mepc   = 0x1000
mcause = 11
mode   = M

Unicorn instead calls UC_HOOK_INTR, advances pc to 0x1004, and does not enter the handler at mtvec.

The reason is that cpu_handle_exception() handles the exception without calling QEMU's riscv_cpu_do_interrupt(). That function already implements the required CSR, privilege, and PC changes.

Could Unicorn provide an opt-in control such as:

c
uc_ctl_set_architectural_exceptions(uc, true);

For RISC-V, enabling it would call riscv_cpu_do_interrupt() and then call UC_HOOK_INTR with the original exception number. The default would stay unchanged for compatibility.

Should this be a generic control, with RISC-V as its first implementation, or a RISC-V-specific control?

I have a patch and unit test for both the existing default behavior and the opt-in behavior.

Related: #1805