#2387·unicorn

RISC-V: U-mode hpmcounter* reads retire even with mcounteren=0

Author: carlosqwqqwqCreated Aug 12, 2026Updated Sep 7, 2026

RISC-V: U-mode hpmcounter* reads retire even with mcounteren=0

Rechecked revision

The five reports were rechecked against the public Unicorn dev branch at 938efd13aeab73155f31cf707a2094c6ccaa36dd.

Problem

mcounteren gates S/U-mode reads of cycle/time/instret and hpmcounter3..31 regardless of the privileged-spec version. mcountinhibit controls counting, which is a separate behavior. Unicorn's ctr CSR predicate returns success for every counter CSR on newer privileged-spec versions, so a U-mode hpmcounter3 read retires with mcounteren=0.

Public reproducer

The self-contained witness and runner are available at https://github.com/carlosqwqqwq/unicorn-riscv-repros/tree/main/u009. After building the public dev checkout, run:

bash
python3 -m pip install -r https://raw.githubusercontent.com/carlosqwqqwq/unicorn-riscv-repros/main/requirements.txt
LIBUNICORN_PATH=/path/to/unicorn/build ./u009/run.sh

The affected path reaches the terminal ebreak; the corrected path returns UC_ERR_EXCEPTION on the U-mode counter read.

Expected behavior

The access must trap when mcounteren=0; M-mode counter access remains available. QEMU and native RISC-V controls reject the same U-mode access.

Root cause and proposed fix

qemu/target/riscv/csr.c:ctr() has an early-success branch keyed only on the privileged-spec version. Removing that branch makes the existing mcounteren/scounteren checks apply to every supported version.

The proposed change is limited to the CSR predicate and is accompanied by a focused unit test in PR #2392.