cva6
cva6 copied to clipboard
rdcycle in M-mode
Let's say I have an execution of rdcycle (accessing the cycle register, addr 0xc00) in M-mode.
if ((riscv::priv_lvl_t'(priv_lvl_o & csr_addr.csr_decode.priv_lvl) != csr_addr.csr_decode.priv_lvl)) begin
privilege_violation = 1'b1;
In this case
csr_addr.csr_decode.priv_lvl = PRIV_LVL_U (2'b00)
and
priv_lvl_o = PRIV_LVL_M (2'b11)
resulting in a privilege violation.
Is this the expected behaviour or is M-mode expected to access all registers?
In addition... from the specs When the CY, TM, IR, or HPMn bit in the mcounteren register is clear, attempts to read the cycle, time, instret, or hpmcountern register while executing in S-mode or U-mode will cause an illegal instruction exception. When one of these bits is set, access to the corresponding register is permitted in the next implemented privilege mode (S-mode if implemented, otherwise U-mode).
In the code this is implemented as
if (csr_addr_i inside {[riscv::CSR_CYCLE:riscv::CSR_HPM_COUNTER_31]}) begin
unique case (csr_addr.csr_decode.priv_lvl)
riscv::PRIV_LVL_M: privilege_violation = 1'b0;
riscv::PRIV_LVL_S: privilege_violation = ~mcounteren_q[csr_addr_i[4:0]];
riscv::PRIV_LVL_U: privilege_violation = ~mcounteren_q[csr_addr_i[4:0]] & ~scounteren_q[csr_addr_i[4:0]];
endcase
end
so the check is done by reading the priv_lvl set by the instruction, non the privilege level of the core.
Why not doing
unique case (priv_lvl_o)
instead?
If you read the line carefully it performs a bitwise AND (&). This means in your scenario what is actually happening is this:
2'b11 AND 2'b00 =? 2'b00
This statement evaluates to true and does not lead to a privilege violation.
The second comment was already found and fixed in #698 (actually with the exact same solution that you propose).
Hi @suppamax, this Issue is ~1.5 years old and it seems from @Moschn's comments that it has been resolved. Can you confirm?
Confirmed