Skip to content

Fix DTLB two-stage fault priority - #3570

Open
124107157-KV wants to merge 1 commit into
openhwfoundation:masterfrom
124107157-KV:fix/3426-dtlb-stage-fault-priority
Open

124107157-KV wants to merge 1 commit into
openhwfoundation:masterfrom
124107157-KV:fix/3426-dtlb-stage-fault-priority

Conversation

@124107157-KV

Copy link
Copy Markdown
Contributor
  • I have searched for similar pull requests
  • I am a human engaging in an interpersonal interaction. During this interaction, my words are my own and are not generated. If relevant, I provide links to my sources.

Why is this PR needed?

Under two-stage address translation, the DTLB-hit path can report a different exception cause from the page-table-walker path for the same memory access.

When both the VS-stage leaf PTE and the final G-stage leaf PTE deny an access, the page-table-walker encounters the VS-stage failure first and reports the corresponding normal page fault. On a DTLB hit, however, the current LSU exception logic checks the G-stage failure before the VS-stage failure.

For a store denied by both stages, this can make the exception depend only on DTLB residency:

  • DTLB miss: STORE_PAGE_FAULT, cause 15
  • DTLB hit: STORE_GUEST_PAGE_FAULT, cause 23

The load path has the same ordering issue.

An identical access using identical page-table state should not produce a different architectural exception merely because the translation is already cached in the DTLB.

This change makes the DTLB-hit path consistent with the existing page-table-walker behavior.

Fixes #3426

What does this PR change?

Update the DTLB-hit exception selection in core/cva6_mmu/cva6_mmu.sv so that the G-stage guest-page-fault path is taken only when the corresponding VS-stage checks have succeeded.

For stores, the G-stage fault condition is now gated by the VS-stage checks covering:

  • write permission
  • privilege/access checks
  • canonical-address validation
  • dirty-bit state

Therefore, when both stages deny the same store, the VS-stage STORE_PAGE_FAULT is selected first. If the VS-stage checks pass and the G-stage denies the store, STORE_GUEST_PAGE_FAULT is still reported as before.

The same ordering is applied to loads. A G-stage load fault is selected only when the VS-stage access and canonical-address checks do not already require LOAD_PAGE_FAULT.

The patch also adds a directed regression which exercises the same two-stage mapping twice:

  1. with a cold DTLB, so the page-table walker determines the fault;
  2. with a populated DTLB, so the DTLB-hit path determines the fault.

Both cases must report the same exception cause.

Verification

Directed #3426 regression

Command used:

cd verif/sim

python3 cva6.py \
  --testlist=../tests/testlist_gstage_prio.yaml \
  --test rv64h-p-gstage-prio \
  --iss_yaml cva6.yaml \
  --target cv64a6_imafdch_sv39 \
  --iss=veri-testharness,spike

Result after the fix:

[PASSED]: 94 matched
7 PASSED, 0 FAILED

The test uses a two-stage translation where the VS-stage and G-stage mappings both deny the tested store and checks both the DTLB-miss and DTLB-hit cases.

After the fix, the CVA6 execution agrees with Spike for the tested sequence.

Existing HLVX G-stage regression

The existing HLVX G-stage regression was also run because this change modifies logic adjacent to the G-stage load permission handling.

Command used:

cd verif/sim

python3 cva6.py \
  --testlist=../tests/testlist_hlvx_gstage.yaml \
  --iss_yaml cva6.yaml \
  --target cv64a6_imafdch_sv39 \
  --iss=veri-testharness,spike

Result:

[PASSED]: 5250 matched
[PASSED]: 5250 matched
9 PASSED, 0 FAILED

Additional checks

The modified RTL was formatted using verible-verilog-format.

The final patch was checked with:

git diff --check upstream/master..HEAD

No whitespace errors were reported.

The branch contains one signed-off commit on top of the upstream master used for this change.

Files changed

core/cva6_mmu/cva6_mmu.sv

Adjust the DTLB-hit store and load exception conditions so that a G-stage guest-page fault is selected only when the corresponding VS-stage checks have passed.

verif/tests/custom/gstage_prio/gstage_prio_repro.S

Add a directed regression for the two-stage VS/G-stage fault-priority case.

The regression compares the exception produced by:

  • a cold DTLB access handled through the PTW;
  • the same access after the translation has been installed in the DTLB.

verif/tests/testlist_gstage_prio.yaml

Add the directed regression to a dedicated CVA6 test list.

Limitations

This change intentionally follows the fault ordering already used by CVA6's page-table-walker path: when both the VS-stage and the final G-stage deny the same access, the VS-stage failure is reported first.

The RISC-V specification discussion concerning VS-stage versus G-stage fault priority is tracked separately in riscv/riscv-isa-manual#3094.

If that architectural clarification eventually specifies a different priority, the PTW and DTLB-hit paths should be updated together so that exception behavior remains independent of TLB residency.

Signed-off-by: 124107157-KV <124107157@umail.ucc.ie>
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.

[BUG] cva6_mmu: identical two-stage access reports cause 15 on a DTLB miss and cause 23 on a DTLB hit

1 participant