fix(RVH): check HLVX final physical execute permission - #1040
Conversation
| if (paddr_type == MEM_TYPE_READ_EXEC) { | ||
| paddr_t paddr = va2pa(s, vaddr, len, type); | ||
| return paddr_read(paddr, len, paddr_type, type, cpu.mode, vaddr); | ||
| } |
There was a problem hiding this comment.
Do we need a separate check here? If this is HLVX, hld_st will be true in has_two_stage_translation(), so it will not take the fast path anyway. Is it sufficient to just make sure paddr_type is passed correctly?
There was a problem hiding this comment.
Yes, this code is indeed redundant. HLVX will not take this path. I will streamline the code to ensure there are no unnecessary logical elements.
|
|
||
| struct Decode; | ||
| word_t hosttlb_read(struct Decode *s, vaddr_t vaddr, int len, int type); | ||
| word_t hosttlb_read(struct Decode *s, vaddr_t vaddr, int len, int type, int paddr_type); |
There was a problem hiding this comment.
It still feels a bit hard to distinguish them this way. Would it make sense to rename them to access_type and trap_type for better clarity?
Also, I think we should add some comments somewhere to explicitly explain the difference between these two types. At the moment, is HLVX the only case where they differ, or are there other instructions that also use different semantics for access checking vs. trap classification?
There was a problem hiding this comment.
Good suggestion. I will try to distinguish these two types and add comments to explain clearly the differences and various uses of them.
a7b2cbd to
848ab41
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes HLVX final physical permission handling so HLVX loads still report load access faults while requiring execute permission in PMP/PMA checks.
Changes:
- Adds
MEM_TYPE_READ_EXECto represent HLVX physical reads requiring both read and execute permissions. - Splits physical access permission type from trap classification through virtual/host TLB read paths.
- Updates RISC-V PMP/PMA permission checks to enforce R+X for HLVX reads.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/memory/vaddr.c |
Propagates separate physical access type and trap type through virtual reads. |
src/memory/paddr.c |
Documents and asserts the new read-execute physical access type. |
src/memory/host-tlb.c |
Passes separate access and trap types through host TLB reads. |
src/isa/riscv64/system/mmu.c |
Enforces R+X permission for MEM_TYPE_READ_EXEC in PMP/PMA checks. |
include/memory/host-tlb.h |
Updates host TLB read prototype. |
include/isa.h |
Adds the new memory access type enum value. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // or EX_IAF). For most accesses they are the same value. Some special cases: | ||
| // - MEM_TYPE_IFETCH_READ: PTW reads a PTE on behalf of ifetch. | ||
| // type = IFETCH_READ (checks R), trap_type = IFETCH_READ (raises EX_IAF). | ||
| // - MEM_TYPE_WRITE_READ: PTW reads a PTE on behalf of store/AMO. | ||
| // type = WRITE_READ (checks R), trap_type = WRITE_READ (raises EX_SAF). | ||
| // - MEM_TYPE_READ_EXEC: HLVX load. | ||
| // type = READ_EXEC (checks R+X), trap_type = READ (raises EX_LAF). | ||
| // PTW types encode both roles in one value (raise_read_access_fault recognizes | ||
| // them directly). HLVX is the only case where type and trap_type are different | ||
| // values, because MEM_TYPE_READ_EXEC encodes the access semantics while the | ||
| // trap must still be a load fault. |
There was a problem hiding this comment.
Fine. I'll chage my expression a little.
848ab41 to
f1e1fa4
Compare
NEMU Performance Results - XS Interpreter
NEMU Performance Results - XS Ref Shared Object
|
The RISC-V HLVX instructions are loads for exception reporting, but their target address must also satisfy execute permission checks at the final physical level. NEMU already modeled this during page-table permission checks by using the global HLVX state when checking PTE permissions. The original code has a bug in the final physical PMP and PMA checks. The translated HLVX access reached paddr_read as a normal read, so PMP and PMA checked only read permission. A region with R=1 and X=0 could be read by HLVX, which made the directed HLVX PMA test miss the expected load access fault. Fix this by adding a MEM_TYPE_READ_EXEC access type for the final physical read. HLVX requires two distinct values for permission checking vs. trap classification: the PTW and page-fault logic must see MEM_TYPE_READ (since isa_mmu_translate uses type to select fault class and index internal arrays), while the final PMP/PMA check must see MEM_TYPE_READ_EXEC (requiring both R and X). The intermediate- layer functions (hosttlb_read, vaddr_mmu_read, vaddr_read_cross_page) therefore carry both values, named "type" for the permission-check type and "trap_type" for the fault-classification type, matching the convention already used by paddr_read. This has been verified using the workload provided at OpenXiangShan/XiangShan#5995. After the XiangShan cores and NEMU jointly fixed this bug, enabling the difftest can successfully pass the test.
f1e1fa4 to
7937dba
Compare
NEMU Performance Results - XS Interpreter
NEMU Performance Results - XS Ref Shared Object
|
The RISC-V HLVX instructions are loads for exception reporting, but their target address must also satisfy execute permission checks. NEMU already modeled this during page-table permission checks by using the global HLVX state when checking PTE permissions.
The original code has a bug in the final physical PMP and PMA checks. The translated HLVX access reached paddr_read as a normal read, so PMP and PMA checked only read permission. A region with R=1 and X=0 could be read by HLVX, which made the directed HLVX PMA test miss the expected load access fault.
Fix this by adding a MEM_TYPE_READ_EXEC access type for the final physical read. Keep the trap classification as read, require both read and execute permission in PMP and PMA checks.
This has been verified using the workload provided at OpenXiangShan/XiangShan#5995. After the XiangShan cores and NEMU jointly fixed this bug, enabling the difftest can successfully pass the test.