diff --git a/src/arch/riscv/isa.cc b/src/arch/riscv/isa.cc index 54499610da..84d21b6bd0 100644 --- a/src/arch/riscv/isa.cc +++ b/src/arch/riscv/isa.cc @@ -782,7 +782,27 @@ ISA::setMiscReg(RegIndex idx, RegVal val) break; case MISCREG_SENVCFG: { - setMiscRegNoEffect(idx, val + 1); + // panic on write to bitfields that aren't implemented in gem5 + SENVCFG panic_mask = 0; + panic_mask.pmm = 3; + + SENVCFG wpri_mask = 0; + wpri_mask.wpri_1 = ~wpri_mask.wpri_1; + wpri_mask.wpri_2 = ~wpri_mask.wpri_2; + wpri_mask.wpri_3 = ~wpri_mask.wpri_3; + + if ((panic_mask & val) != 0) { + panic("Tried to write to an unimplemented bitfield in the " + "senvcfg CSR!\nThe attempted write was:\n %" PRIu64 "\n", + val); + } + + if ((wpri_mask & val) != 0) { + warn("Ignoring write to WPRI bit(s) in senvcfg CSR.\n" + "The attempted write was:\n %" PRIu64 "\n", val); + } else { + setMiscRegNoEffect(idx, val); + } } break; case MISCREG_TSELECT: diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa index 1bf2338129..bc92f17112 100644 --- a/src/arch/riscv/isa/decoder.isa +++ b/src/arch/riscv/isa/decoder.isa @@ -1003,16 +1003,84 @@ decode QUADRANT default Unknown::unknown() { 0x2: decode FUNCT12 { format CBMOp { 0x0: cbo_inval({{ - Mem = 0; - }}, mem_flags=[INVALIDATE, DST_POC]); + SENVCFG senvcfg = xc->readMiscReg(MISCREG_SENVCFG); + auto pm = (PrivilegeMode)xc->readMiscReg( + MISCREG_PRV); + + if (pm == PRV_U) { + if (senvcfg.cbie == 0) { + return std::make_shared( + "Can't execute cbo.clean in current " + "privilege mode!", machInst); + } + else if (senvcfg.cbie == 1){ //flush + Mem = 0; + } + else if (senvcfg.cbie == 3) { // invalidate + Mem = 0; + } else { //sebvcfg.cbie == 2, reserved + return std::make_shared( + "Invalid value for senvcfg.cbie!", + machInst); + } + } else if (pm == PRV_M){ // all invalidate + Mem = 0; + } else if (pm == PRV_S) { + // whether it's a flush or invalidate depends on + // menvcfg (01 and 11 respectively) + Mem = 0; + } + }}, mem_flags = [INVALIDATE, DST_POC]); + // mem_flags might need a conditional to add CLEAN + // in certain cases; unsure of syntax for that + 0x1: cbo_clean({{ - Mem = 0; + SENVCFG senvcfg = xc->readMiscReg(MISCREG_SENVCFG); + auto pm = (PrivilegeMode)xc->readMiscReg( + MISCREG_PRV); + + if (pm == PRV_U && !senvcfg.cbcfe){ + return std::make_shared( + "Can't execute cbo.clean in current " + "privilege mode!", machInst); + // the specification has more conditions/privilege + // modes to check, but menvcfg and henvcfg are not + // implemented + } else { + Mem = 0; + } }}, mem_flags=[CLEAN, DST_POC]); 0x2: cbo_flush({{ - Mem = 0; + SENVCFG senvcfg = xc->readMiscReg(MISCREG_SENVCFG); + auto pm = (PrivilegeMode)xc->readMiscReg( + MISCREG_PRV); + + if (pm == PRV_U && !senvcfg.cbcfe){ + return std::make_shared( + "Can't execute cbo.flush in current " + "privilege mode!", machInst); + // the specification has more conditions/privilege + // modes to check, but menvcfg and henvcfg are not + // implemented + } else { + Mem = 0; + } }}, mem_flags=[CLEAN, INVALIDATE, DST_POC]); 0x4: cbo_zero({{ - Mem = 0; + SENVCFG senvcfg = xc->readMiscReg(MISCREG_SENVCFG); + auto pm = (PrivilegeMode)xc->readMiscReg( + MISCREG_PRV); + + if (pm == PRV_U && !senvcfg.cbze){ + return std::make_shared( + "Can't execute cbo.zero in current " + "privilege mode!", machInst); + // the specification has more conditions/privilege + // modes to check, but menvcfg and henvcfg are not + // implemented + } else { + Mem = 0; + } }}, mem_flags=[CACHE_BLOCK_ZERO]); } } diff --git a/src/arch/riscv/regs/misc.hh b/src/arch/riscv/regs/misc.hh index 64c656f3c4..ebab200259 100644 --- a/src/arch/riscv/regs/misc.hh +++ b/src/arch/riscv/regs/misc.hh @@ -1265,6 +1265,20 @@ BitUnion64(INTERRUPT) Bitfield<0> usi; EndBitUnion(INTERRUPT) + +// From the RISCV specification version 20240411, volume 2, +// section 10.1.10, page 98 +BitUnion64(SENVCFG) + Bitfield<63,34> wpri_1; + Bitfield<33,32> pmm; + Bitfield<31,8> wpri_2; + Bitfield<7> cbze; + Bitfield<6> cbcfe; + Bitfield<5,4> cbie; + Bitfield<3,1> wpri_3; + Bitfield<0> fiom; +EndBitUnion(SENVCFG) + const off_t MXL_OFFSETS[enums::Num_RiscvType] = { [RV32] = (sizeof(uint32_t) * 8 - 2), [RV64] = (sizeof(uint64_t) * 8 - 2),