A detailed analysis of a K3 bug where mepc loses bit63 during instruction page faults on non-canonical addresses under Sv39, violating RISC-V Privileged Architecture requirements.
Test environment: K3 platform, S-mode, Sv39 paging. Execute a jalr to the non-canonical virtual address 0x8000000150009000.
Expected behavior (per RISC-V Privileged Architecture):The mepc value equals the PC after Sv39 canonicalization (sign-extending from bit38). This means K3 writes the "normalized" address into mepc rather than the original 64-bit architectural PC.
The RISC-V Privileged Architecture states:
> "When a trap is taken into M-mode, mepc is written with the virtual address of the instruction that was interrupted or that encountered the exception."This requires the full 64-bit virtual address. The mtval definition is consistent: it correctly stores the full faulting VA on K3, so mepc should match.
The WARL clause ("mepc is a WARL register that must be able to hold all valid virtual addresses... implementations may convert an invalid address into some other invalid address that mepc is capable of holding") does not excuse this behavior. That clause permits invalid-to-invalid conversion; K3 instead produces a "legally-formed" address that could be mistaken for a valid canonical address. The official RISC-V architecture compliance suite (SAIL model) confirms the expected behavior:For most application code this bug is invisible — non-canonical addresses are typically unreachable in well-behaved programs. However, for:
...the discrepancy between mepc and mtval can cause subtle failures in exception handlers that expect both registers to agree on the faulting address.
Until a silicon or microcode fix is available, trap handlers that need the full faulting address on K3 should prefer mtval over mepc for instruction-page-fault cases. Note that this is a K3-specific quirk and should be guarded by machine-specific detection.