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
11 changes: 10 additions & 1 deletion src/arch/riscv/isa.cc
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,15 @@ ISA::readMiscReg(int misc_reg)
DPRINTF(RiscvMisc, "Read IE value: %#lx.\n", ic->readIE());
return ic->readIE();
}
case MISCREG_MIDELEG:
{
// Note: old versions of bbl don't like HS_INTERRUPTS on mideleg.
// If your bootloader panics, keep this return as-is.
auto mideleg_val = readMiscRegNoEffect(MISCREG_MIDELEG);
return mideleg_val;
// MISA misa = readMiscRegNoEffect(MISCREG_ISA);
// return misa.rvh ? mideleg_val | HS_INTERRUPTS : mideleg_val;
}
case MISCREG_SEPC:
case MISCREG_MEPC:
{
Expand Down Expand Up @@ -921,4 +930,4 @@ operator<<(std::ostream &os, gem5::RiscvISA::PrivilegeMode pm)
return os << "PRV_M";
}
return os << "PRV_<invalid>";
}
}
178 changes: 150 additions & 28 deletions src/arch/riscv/isa/decoder.isa
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,8 @@ decode QUADRANT {
0x2: decode AMOFUNCT {
0x2: LoadReserved::lr_w({{
Rd_sd = Mem_sw;
}}, inst_flags=IsLoadReserved, mem_flags=LLSC);
}}, inst_flags=IsLoadReserved,
mem_flags=[LLSC, 'ARCH_BITS & XlateFlags::LR']);
0x3: StoreCond::sc_w({{
Mem_uw = Rs2_uw;
}}, {{
Expand Down Expand Up @@ -846,7 +847,8 @@ decode QUADRANT {
0x3: decode AMOFUNCT {
0x2: LoadReserved::lr_d({{
Rd_sd = Mem_sd;
}}, mem_flags=LLSC, inst_flags=IsLoadReserved);
}}, mem_flags=[LLSC, 'ARCH_BITS & XlateFlags::LR'],
inst_flags=IsLoadReserved);
0x3: StoreCond::sc_d({{
Mem = Rs2;
}}, {{
Expand Down Expand Up @@ -2040,13 +2042,6 @@ decode QUADRANT {
}}, IsDirectControl, IsUncondControl);

0x1c: decode FUNCT3 {
format LoadH {
0x04: decode HFUNCT2{
0x643: hlvx_hu({{
Rd = Mem_uh;
}},inst_flags = IsHInst);
}
}
format SystemOp {
0x0: decode FUNCT7 {
0x0: decode RS2 {
Expand Down Expand Up @@ -2154,6 +2149,47 @@ decode QUADRANT {
}
xc->tcBase()->getMMUPtr()->demapPage(Rs1, Rs2);
}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);

0xb: sinval_vvma({{
warn("sinval_vvma not implemented");
}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);
Comment on lines +2153 to +2155
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Implement sinval.vvma invalidation or trap

When a guest/OS uses sinval.vvma after updating page tables, this implementation only logs a warning and returns NoFault, so no TLB/translation invalidation occurs and no illegal-instruction trap is raised. That means stale translations can be reused, leading to accesses using old mappings or permissions after address-space changes (e.g., context switches or unmaps). If the invalidation isn’t implemented yet, this should at least raise an illegal instruction so software doesn’t continue with silently incorrect translations.

Useful? React with 👍 / 👎.


0xc: decode RS2{
0x0: sfence_w_inval({{
warn("sfence_w_inval not implemented");
}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);

0x1: sfence_inval_ir({{
warn("sfence_inval_ir not implemented");
}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);
}
Comment on lines +2153 to +2165
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid no-op invalidation instructions.

These paths only warn and continue, which can leave stale translations and break guest behavior. Either implement the invalidation or fail fast until it’s supported.

🛠️ Suggested fail-fast behavior until invalidation is implemented
-                    warn("sinval_vvma not implemented");
+                    return std::make_shared<IllegalInstFault>(
+                            "sinval_vvma not implemented", machInst);
...
-                        warn("sfence_w_inval not implemented");
+                        return std::make_shared<IllegalInstFault>(
+                                "sfence_w_inval not implemented", machInst);
...
-                        warn("sfence_inval_ir not implemented");
+                        return std::make_shared<IllegalInstFault>(
+                                "sfence_inval_ir not implemented", machInst);
...
-                        warn("hinval_vvma not implemented");
+                        return std::make_shared<IllegalInstFault>(
+                                "hinval_vvma not implemented", machInst);
...
-                            warn("hinval_gvma unimplemented");
+                            return std::make_shared<IllegalInstFault>(
+                                    "hinval_gvma not implemented", machInst);

Also applies to: 2189-2191, 2242-2244

🤖 Prompt for AI Agents
In `@src/arch/riscv/isa/decoder.isa` around lines 2153 - 2165, The decoder
currently maps sinval_vvma, sfence_w_inval, and sfence_inval_ir to no-op stubs
that only warn (leaving stale translations); change these paths to fail-fast
until proper invalidation is implemented by replacing the warn-only handlers
with a hard trap/unsupported-instruction error (or explicit throw/terminate) so
execution cannot continue with stale state; locate the cases for sinval_vvma,
sfence_w_inval, and sfence_inval_ir in the decoder and update their bodies to
return/raise an unrecoverable error (or call the existing unsupported/op-fail
helper) instead of just logging a warning.


0x11: hfence_vvma({{
auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
RegVal misa = xc->readMiscReg(MISCREG_ISA);

if ((misa & ISA_EXT_H_MASK) == 0) {
return std::make_shared<IllegalInstFault>(
"hfence needs RVH",
machInst);
}
if (xc->readMiscReg(MISCREG_VIRMODE) == 1) {
return std::make_shared<HVFault>();
}
if (pm < PRV_S) {
return std::make_shared<IllegalInstFault>(
"hfence needs at least S priv",
machInst);
}
xc->tcBase()->getMMUPtr()->demapPage(Rs1, Rs2);
return NoFault;

}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);

0x13: hinval_vvma({{
warn("hinval_vvma not implemented");
}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);

0x18: mret({{
if (xc->readMiscReg(MISCREG_PRV) != PRV_M) {
return std::make_shared<IllegalInstFault>(
Expand All @@ -2174,29 +2210,39 @@ decode QUADRANT {
xc->setMiscReg(MISCREG_VIRMODE,status_mpv);
}
}}, IsSerializeAfter, IsNonSpeculative, IsReturn);
0x31: priv({{
auto pm = (PrivilegeMode)xc->readMiscReg(
MISCREG_PRV);
auto vir = (PrivilegeMode)xc->readMiscReg(
MISCREG_VIRMODE);
STATUS status = xc->readMiscReg(MISCREG_STATUS);
xc->tcBase()->getMMUPtr()->demapPage(Rs1, Rs2);
0x31: decode FUNCT3 {
0x0: hfence_gvma({{
auto pm = (PrivilegeMode)xc->readMiscReg(
MISCREG_PRV);
STATUS status = xc->readMiscReg(MISCREG_STATUS);
RegVal misa = xc->readMiscReg(MISCREG_ISA);

if(vir){
panic("add priv vir code\n");
if ((misa & ISA_EXT_H_MASK) == 0) {
return std::make_shared<IllegalInstFault>(
"hfence needs RVH",
machInst);
}
if (xc->readMiscReg(MISCREG_VIRMODE) == 1) {
return std::make_shared<HVFault>();
}

}
if(pm == PRV_U){
return std::make_shared<IllegalInstFault>(
"h-priv pm == prv_u", machInst);
if (pm < PRV_S ||
(pm == PRV_S && status.tvm == 1)) {
return std::make_shared<IllegalInstFault>(
"hfence in U or TVM on",
machInst);
}
xc->tcBase()->getMMUPtr()->demapPage(Rs1, Rs2);
return NoFault;

}
if(!(pm == PRV_M ||(pm == PRV_S && !vir && status.tvm ==0))){
return std::make_shared<IllegalInstFault>(
"h-priv pm == prv_u", machInst);
}}, IsNonSpeculative, IsSerializeAfter, No_OpClass);
}

}
}},IsNonSpeculative, IsSerializeAfter, No_OpClass);
0x33: decode FUNCT3 {
0x0: hinval_gvma({{
warn("hinval_gvma unimplemented");
}}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
}
}
}
format CSROp {
Expand Down Expand Up @@ -2347,6 +2393,82 @@ decode QUADRANT {
}

}
0x4: decode FUNCT7{
0x30: decode RS2 {
0x0: HyperLoad::hlv_b({{
Rd_sd = Mem_sb;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x1: HyperLoad::hlv_bu({{
Rd = Mem_ub;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
}
0x31: HyperStore::hsv_b({{
Mem_ub = Rs2_ub;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x32: decode RS2 {
0x0: HyperLoad::hlv_h({{
Rd_sd = Mem_sh;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x1: HyperLoad::hlv_hu({{
Rd = Mem_uh;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x3: HyperLoad::hlvx_hu({{
Rd = Mem_uh;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT',
'ARCH_BITS & XlateFlags::HLVX'
]);
}
0x33: HyperStore::hsv_h({{
Mem_uh = Rs2_uh
}}, mem_flags=[
Comment on lines +2432 to +2434
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix missing semicolon in hsv_h store.

This will break generated C++.

🐛 Proposed fix
-                        Mem_uh = Rs2_uh
+                        Mem_uh = Rs2_uh;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
0x33: HyperStore::hsv_h({{
Mem_uh = Rs2_uh
}}, mem_flags=[
0x33: HyperStore::hsv_h({{
Mem_uh = Rs2_uh;
}}, mem_flags=[
🤖 Prompt for AI Agents
In `@src/arch/riscv/isa/decoder.isa` around lines 2432 - 2434, The store in
HyperStore::hsv_h has a missing semicolon after the assignment "Mem_uh = Rs2_uh"
which breaks generated C++; update the hsv_h store block to terminate the
assignment with a semicolon (i.e., change "Mem_uh = Rs2_uh" to "Mem_uh =
Rs2_uh;") and keep the surrounding mem_flags array intact so the decoder.isa
block for HyperStore::hsv_h remains syntactically valid.

'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x34: decode RS2 {
0x0: HyperLoad::hlv_w({{
Rd_sd = Mem_sw;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x1: HyperLoad::hlv_wu({{
Rd = Mem_uw;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x3: HyperLoad::hlvx_wu({{
Rd = Mem_uw;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT',
'ARCH_BITS & XlateFlags::HLVX'
]);
}
0x35: HyperStore::hsv_w({{
Mem_uw = Rs2_uw;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x36: HyperLoad::hlv_d({{
Rd_sd = Mem_sd;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);
0x37: HyperStore::hsv_d({{
Mem_ud = Rs2_ud;
}}, mem_flags=[
'ARCH_BITS & XlateFlags::FORCE_VIRT'
]);

}
}

0x1e: M5Op::M5Op();
Expand Down
10 changes: 6 additions & 4 deletions src/arch/riscv/isa/formats/amo.isa
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,9 @@ def format LoadReserved(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
iop = InstObjParams(name, Name, 'LoadReservedMicro',
{'ea_code': ea_code, 'memacc_code': memacc_code,
'postacc_code': postacc_code}, inst_flags)
mem_flags = ['(Request::%s)' % flag for flag in mem_flags]
iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
'|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
'|'.join(mem_flags) + ';'

header_output += LRSCMicroDeclare.subst(iop)
decoder_output += LRSCMicroConstructor.subst(iop)
Expand All @@ -533,8 +534,9 @@ def format StoreCond(memacc_code, postacc_code={{ }}, ea_code={{EA = Rs1;}},
iop = InstObjParams(name, Name, 'StoreCondMicro',
{'ea_code': ea_code, 'memacc_code': memacc_code,
'postacc_code': postacc_code}, inst_flags)
mem_flags = ['(Request::%s)' % flag for flag in mem_flags]
iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
'|'.join(['Request::%s' % flag for flag in mem_flags]) + ';'
'|'.join(mem_flags) + ';'

header_output += LRSCMicroDeclare.subst(iop)
decoder_output += LRSCMicroConstructor.subst(iop)
Expand Down Expand Up @@ -564,9 +566,9 @@ def format AtomicMemOp(memacc_code, amoop_code, postacc_code={{ }},
'postacc_code': postacc_code,
'amoop_code': amoop_code},
rmw_inst_flags)

rmw_mem_flags = ['(Request::%s)' % flag for flag in rmw_mem_flags]
rmw_iop.constructor += '\n\tmemAccessFlags = memAccessFlags | ' + \
'|'.join(['Request::%s' % flag for flag in rmw_mem_flags]) + ';'
'|'.join(rmw_mem_flags) + ';'

header_output += AtomicMemOpRMWDeclare.subst(rmw_iop)
decoder_output += AtomicMemOpRMWConstructor.subst(rmw_iop)
Expand Down
Loading