Skip to content

mstatus.MPP returns stale illegal value after misa.U is dynamically disabled #2267

@varunmadhavam

Description

@varunmadhavam

Title: mstatus.MPP returns stale illegal value after misa.U is dynamically disabled

Description:

When U-mode is dynamically disabled by clearing misa bit 20, mstatus.MPP can retain a stale value of 0 (User) that is no longer legal. A subsequent CSRR mstatus returns this stale value, violating the WARL contract.

Steps to reproduce:

# In M-mode, with U-mode initially enabled
csrr  t0, mstatus
li    t1, ~0x1800
and   t0, t0, t1        # clear MPP bits -> MPP=0 (User)
csrw  mstatus, t0       # accepted since U is enabled

csrr  t0, misa
li    t1, ~(1 << 20)    # clear U bit
and   t0, t0, t1
csrw  misa, t0          # disable U-mode

csrr  t3, mstatus       # read mstatus back
# MPP bits [12:11] are 0 (User) -- but User is no longer a legal value

Observed behavior:

CSRR mstatus returns MPP=0 (User) after U-mode has been disabled via misa. Spike does legalize MPP correctly on mstatus writes and during MRET via legalize_privilege(), but explicit reads of mstatus return the raw register value with no legalization.

Expected behavior per spec:

Section 2.3.3 (WARL): "guaranteeing to return a legal value whenever read."

Section 2.4 (CSR Field Modulation): "If a write to one CSR changes the set of legal values allowed for a field of a second CSR, then unless specified otherwise, the second CSR's field immediately gets an UNSPECIFIED value from among its new legal values."

When misa.U is cleared, MPP's legal set changes from {0, 3} to {3}. Per Section 2.4, MPP should immediately become a value from {3}. At minimum, per Section 2.3.3, a read of mstatus should never return MPP=0 when U-mode is disabled.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions