Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/csr_regfile.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,10 @@ module csr_regfile
// we are in vector mode, this implementation requires the additional
// alignment constraint of 64 * 4 bytes
if (DirVecOnly) mtvec_d = {csr_wdata[CVA6Cfg.XLEN-1:8], 7'b0, DirVecOnly};
// Machine-mode instruction fetches use physical addresses. Legalize
// mtvec to the implemented physical address width so its CSR-visible
// value matches the address that can actually be fetched.
mtvec_d = CVA6Cfg.XLEN'(CVA6Cfg.PLEN'(mtvec_d));
end
riscv::CSR_MCOUNTEREN: begin
if (CVA6Cfg.RVU) mcounteren_d = {{CVA6Cfg.XLEN - 32{1'b0}}, csr_wdata[31:0]};
Expand Down
61 changes: 61 additions & 0 deletions verif/tests/custom/issues/mtvec-warl-rv64.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright 2026 Keerthivasan
#
# Licensed under the Solderpad Hardware Licence, Version 2.0.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
#
# Regression test for CVA6 issue #3458.
#
# mtvec is WARL. If an mtvec value contains address bits that the
# implementation cannot use for instruction fetch, the implementation may
# legalize the value on write. If the value is instead retained on readback,
# trap dispatch must consume the same architectural base.
#
# The current bug retains a high-tagged value in mtvec, while the instruction
# fetch path ultimately uses the low physical-address alias.

.section .text
.align 2

.equ HIGH_TAG, 0x1000000000000000

.globl main

main:
# Construct an mtvec value whose low portion names a real executable
# trap handler while bit 60 is outside the implemented physical-address
# width of cv64a6_imafdc_sv39.
la t0, low_trap_entry
li t1, HIGH_TAG
or s0, t0, t1

# Write and immediately read back mtvec.
csrw mtvec, s0
csrr s1, mtvec

# Legalization is a valid WARL implementation choice.
# If the unsupported tag was removed, the CSR and fetch behavior are
# coherent and this test passes.
bne s1, s0, pass_mtvec_legalized

# If the tagged value was retained, trap dispatch must not silently
# consume the low alias.
ecall_site:
ecall

# ECALL must trap and must never retire here.
li a0, 41
j finish

.align 2
low_trap_entry:
# Reaching this handler while mtvec readback retained HIGH_TAG reproduces
# issue #3458: software sees the tagged base but hardware dispatched to
# its low physical alias.
li a0, 42
j finish

pass_mtvec_legalized:
li a0, 0

finish:
jal exit
21 changes: 21 additions & 0 deletions verif/tests/testlist_issues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,24 @@ testlist:
when MRET or SRET returns below M-mode.
iterations: 1
asm_tests: <path_var>/custom/issues/xret-mprv-clear-rv64.S

- test: mtvec-warl-rv64
<<: *common_test_config
description: >
Check that mtvec CSR readback and machine-mode trap dispatch remain
coherent when software writes address bits outside the implemented
physical-address width.
iterations: 1
asm_tests: <path_var>/custom/issues/mtvec-warl-rv64.S
gcc_opts: >-
-static
-misa-spec=2.2
-mcmodel=medany
-fvisibility=hidden
-nostdlib
-nostartfiles
../tests/custom/common/crt.S
-I../tests/custom/env
-I../tests/custom/common
-T ../../config/gen_from_riscv_config/linker/link.ld
-lgcc
Loading