riscv: Expose privilege level as pseudo-register "priv" #1989
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Unlike some other architectures, RISC-V does not expose the current privilege mode in any architecturally-defined register. That is intentional to make it easier to implement virtualization in software, but a Unicorn caller operates outside of the emulated hart and so it can and should be able to observe and change the current privilege mode in order to properly emulate certain behaviors of a real CPU.
This PR therefore now exposes a new pseudo-register using the name "priv", defined to match the virtual register "priv" defined in the RISC-V Debug Specification, section 4.10.1. This design assumes that the Unicorn API is providing an abstraction similar to that of a debugger and so it's reasonable to take design cues from the Debug specification, rather than inventing something entirely Unicorn-specific.
The register read/write is currently implemented directly inside the Unicorn code because QEMU doesn't have explicit support for the CSRs from the debug specification. If a future QEMU release supports "dcsr" then this implementation could potentially change to wrap reading and writing that CSR and then projecting the "prv" and "v" bitfields into the correct locations for the virtual register, but for now I prioritize pragmatism since Unicorn previously offered no way to directly get/set the privilege mode from outside the emulated hart.
I've updated all of the bindings that already had the RISC-V register constants, but some of them do not currently have any defined and so I left them alone: vb6 and haskell. Of the remaining ones I only know how to test the rust bindings, and I've confirmed that this works when called from my own Rust-based Unicorn client that motivated this addition.
(I discovered a need for this while I was investigating over in #1988, but this is an orthogonal change and so submitted as a separate PR.)