Skip to content

hpcp: gate counter enables on combinational cnt_mode_dis_pre#54

Open
flaviens wants to merge 1 commit into
XUANTIE-RV:mainfrom
flaviens:fix/hpcp-perfcounter-priv-disable-window
Open

hpcp: gate counter enables on combinational cnt_mode_dis_pre#54
flaviens wants to merge 1 commit into
XUANTIE-RV:mainfrom
flaviens:fix/hpcp-perfcounter-priv-disable-window

Conversation

@flaviens
Copy link
Copy Markdown

@flaviens flaviens commented Jun 1, 2026

Hi!

The per-counter enables in ct_hpcp_top.v (mcycle_en, minstret_en, mhpmcnt3_en..mhpmcnt18_en, the four L2 counter enables, and the exported hpcp_xx_cnt_en) gate on the registered cnt_mode_dis. That register lags the combinational cnt_mode_dis_pre by one cycle, and cnt_mode_dis_pre already reflects the new privilege mode and the pmdm/pmds/pmdu bits on a privilege-transition cycle. So the first cycle after a transition into a disabled mode still increments the counters: every entry into a disabled mode over-counts by one event and every exit under-counts by one.

Drive the 23 enables from cnt_mode_dis_pre so the per-mode disable takes effect on the transition cycle. The registered cnt_mode_dis is retained for the clock-gating term at line 1086 (cnt_mode_dis_pre ^ cnt_mode_dis), which keeps the block clocked across the transition cycle and is unchanged. The change is one operand per line on 23 lines and adds no flop.

Security relevance: a deployment that uses pmdm/pmds/pmdu to keep higher-privilege events out of a counter a lower-privilege reader can sample no longer fully seals those events across a privilege boundary, leaking about one bit per transition.

The per-counter enables in ct_hpcp_top.v (mcycle_en, minstret_en, mhpmcnt3_en..mhpmcnt18_en, the four L2 counter enables, and the exported hpcp_xx_cnt_en) gate on the registered cnt_mode_dis. That register lags the combinational cnt_mode_dis_pre by one cycle, and cnt_mode_dis_pre already reflects the new privilege mode and the pmdm/pmds/pmdu bits on a privilege-transition cycle. So the first cycle after a transition into a disabled mode still increments the counters: every entry into a disabled mode over-counts by one event and every exit under-counts by one.

Drive the 23 enables from cnt_mode_dis_pre so the per-mode disable takes effect on the transition cycle. The registered cnt_mode_dis is retained for the clock-gating term at line 1086 (cnt_mode_dis_pre ^ cnt_mode_dis), which keeps the block clocked across the transition cycle and is unchanged. The change is one operand per line on 23 lines and adds no flop.

Security relevance: a deployment that uses pmdm/pmds/pmdu to keep higher-privilege events out of a counter a lower-privilege reader can sample no longer fully seals those events across a privilege boundary, leaking about one bit per transition. A Yosys SAT miter and a Verilator reproducer are available on request.
Copilot AI review requested due to automatic review settings June 1, 2026 04:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant