From f6e1fbaef71a6b5c4c25090017c22155673ce810 Mon Sep 17 00:00:00 2001 From: Aditya Badole Date: Fri, 22 Dec 2023 13:06:57 +0800 Subject: [PATCH] Prepare for release: - Clean up code - Remove part related to address translation - Add comments - Fix some bugs - Update RcUpdate command Change-Id: I5a9ae0cd3945bf562b8608a8f01e3305da6c8aa5 --- configs/capstone/fast-forward.py | 2 +- src/arch/riscvcapstone/RiscvMMU.py | 7 +- src/arch/riscvcapstone/RiscvTLB.py | 6 - src/arch/riscvcapstone/isa.cc | 41 +- src/arch/riscvcapstone/isa/decoder.isa | 592 ++++++------------ src/arch/riscvcapstone/isa/formats/calls.isa | 2 + src/arch/riscvcapstone/isa/formats/rnode.isa | 193 +++--- src/arch/riscvcapstone/mmu.hh | 42 +- .../riscvcapstone/o3/CapstoneBaseO3CPU.py | 4 - src/arch/riscvcapstone/o3/commit.cc | 68 +- src/arch/riscvcapstone/o3/cpu.cc | 19 +- src/arch/riscvcapstone/o3/cpu.hh | 9 - src/arch/riscvcapstone/o3/dyn_inst.cc | 14 +- src/arch/riscvcapstone/o3/dyn_inst.hh | 53 +- src/arch/riscvcapstone/o3/iew.cc | 3 +- src/arch/riscvcapstone/o3/lsq.cc | 3 - src/arch/riscvcapstone/o3/ncq.hh | 14 +- src/arch/riscvcapstone/o3/ncq_unit.cc | 13 +- src/arch/riscvcapstone/o3/ncq_unit.hh | 12 +- src/arch/riscvcapstone/o3/node_commands.cc | 81 ++- src/arch/riscvcapstone/o3/node_commands.hh | 38 +- src/arch/riscvcapstone/o3/thread_context.hh | 6 - src/arch/riscvcapstone/pagetable_walker.cc | 16 +- src/arch/riscvcapstone/pagetable_walker.hh | 4 - src/arch/riscvcapstone/pmp.cc | 4 +- src/arch/riscvcapstone/process.cc | 24 +- src/arch/riscvcapstone/regs/misc.hh | 6 +- src/arch/riscvcapstone/remote_gdb.cc | 16 - src/arch/riscvcapstone/tlb.cc | 29 +- src/arch/riscvcapstone/tlb.hh | 4 - src/cpu/checker/thread_context.hh | 7 - src/cpu/o3/thread_context.hh | 8 - src/cpu/simple_thread.hh | 7 - src/cpu/thread_context.hh | 4 - 34 files changed, 497 insertions(+), 854 deletions(-) diff --git a/configs/capstone/fast-forward.py b/configs/capstone/fast-forward.py index 6472a2fa68..8d1b0d56e2 100644 --- a/configs/capstone/fast-forward.py +++ b/configs/capstone/fast-forward.py @@ -96,7 +96,7 @@ class L2Cache(Cache): tgts_per_mshr = 12 # prefetcher = TaggedPrefetcher(degree=1, prefetch_on_access=True) -system = System() +system = System(mmap_using_noreserve=True) system.clk_domain = SrcClockDomain() system.clk_domain.clock = '1GHz' diff --git a/src/arch/riscvcapstone/RiscvMMU.py b/src/arch/riscvcapstone/RiscvMMU.py index f8e50b631f..62f278cd78 100644 --- a/src/arch/riscvcapstone/RiscvMMU.py +++ b/src/arch/riscvcapstone/RiscvMMU.py @@ -49,13 +49,10 @@ class RiscvMMU(BaseMMU): itb = RiscvTLB(entry_type="instruction") dtb = RiscvTLB(entry_type="data") - pma_checker = Param.PMAChecker(PMAChecker(), "PMA Checker") - pmp = Param.PMP(PMP(), "Physical Memory Protection Unit") @classmethod def walkerPorts(cls): - return ["mmu.itb.walker.port", "mmu.dtb.walker.port"] + return [] def connectWalkerPorts(self, iport, dport): - self.itb.walker.port = iport - self.dtb.walker.port = dport + pass diff --git a/src/arch/riscvcapstone/RiscvTLB.py b/src/arch/riscvcapstone/RiscvTLB.py index 563cfda709..8e7892d333 100644 --- a/src/arch/riscvcapstone/RiscvTLB.py +++ b/src/arch/riscvcapstone/RiscvTLB.py @@ -43,9 +43,6 @@ class RiscvPagetableWalker(ClockedObject): system = Param.System(Parent.any, "system object") num_squash_per_cycle = Param.Unsigned(4, "Number of outstanding walks that can be squashed per cycle") - # Grab the pma_checker from the MMU - pma_checker = Param.PMAChecker(Parent.any, "PMA Checker") - pmp = Param.PMP(Parent.any, "PMP") class RiscvTLB(BaseTLB): type = 'RiscvTLB' @@ -55,6 +52,3 @@ class RiscvTLB(BaseTLB): size = Param.Int(64, "TLB size") walker = Param.RiscvPagetableWalker(\ RiscvPagetableWalker(), "page table walker") - # Grab the pma_checker from the MMU - pma_checker = Param.PMAChecker(Parent.any, "PMA Checker") - pmp = Param.PMP(Parent.any, "Physical Memory Protection Unit") diff --git a/src/arch/riscvcapstone/isa.cc b/src/arch/riscvcapstone/isa.cc index c849a1ecc8..0d4c0863d8 100644 --- a/src/arch/riscvcapstone/isa.cc +++ b/src/arch/riscvcapstone/isa.cc @@ -248,10 +248,6 @@ void ISA::clear() miscRegFile[MISCREG_TSELECT] = 1; // NMI is always enabled. miscRegFile[MISCREG_NMIE] = 1; - - //probably need to set cinit here - //don't. do it in CPU instead - //else include hell awaits } bool @@ -404,7 +400,6 @@ ISA::setMiscRegNoEffect(int misc_reg, RegVal val) void ISA::setMiscReg(int misc_reg, RegVal val) { - //maybe set this to update only when correct cwrld if (misc_reg >= MISCREG_CYCLE && misc_reg <= MISCREG_HPMCOUNTER31) { // Ignore writes to HPM counters for now warn("Ignoring write to %s.\n", CSRData.at(misc_reg).name); @@ -420,44 +415,12 @@ ISA::setMiscReg(int misc_reg, RegVal val) case MISCREG_PMPCFG0: case MISCREG_PMPCFG2: { - // PMP registers should only be modified in M mode - assert(readMiscRegNoEffect(MISCREG_PRV).intVal() == PRV_M); - - // Specs do not seem to mention what should be - // configured first, cfg or address regs! - // qemu seems to update the tables when - // pmp addr regs are written (with the assumption - // that cfg regs are already written) - - for (int i=0; i < sizeof(val); i++) { - - uint8_t cfg_val = (val >> (8*i)) & 0xff; - auto mmu = dynamic_cast - (tc->getMMUPtr()); - - // Form pmp_index using the index i and - // PMPCFG register number - // Note: MISCREG_PMPCFG2 - MISCREG_PMPCFG0 = 1 - // 8*(misc_reg-MISCREG_PMPCFG0) will be useful - // if a system contains more than 16 PMP entries - uint32_t pmp_index = i+(8*(misc_reg-MISCREG_PMPCFG0)); - mmu->getPMP()->pmpUpdateCfg(pmp_index,cfg_val); - } - - setMiscRegNoEffect(misc_reg, val); + panic("pmp unsupported."); } break; case MISCREG_PMPADDR00 ... MISCREG_PMPADDR15: { - // PMP registers should only be modified in M mode - assert(readMiscRegNoEffect(MISCREG_PRV).intVal() == PRV_M); - - auto mmu = dynamic_cast - (tc->getMMUPtr()); - uint32_t pmp_index = misc_reg-MISCREG_PMPADDR00; - mmu->getPMP()->pmpUpdateAddr(pmp_index, val); - - setMiscRegNoEffect(misc_reg, val); + panic("pmp unsupported."); } break; diff --git a/src/arch/riscvcapstone/isa/decoder.isa b/src/arch/riscvcapstone/isa/decoder.isa index 34a5ac037c..24b8df228a 100644 --- a/src/arch/riscvcapstone/isa/decoder.isa +++ b/src/arch/riscvcapstone/isa/decoder.isa @@ -124,21 +124,7 @@ decode QUADRANT default Unknown::unknown() { "immediate = 0", machInst); } } - using namespace gem5::RiscvcapstoneISA::o3; - - DynInst* dyn_inst = dynamic_cast(xc); - assert(dyn_inst); - - if(Rc1_trv.getTag()) { - Rc1_trv.setTag(false); - NodeID node_id = Rc1_trv.getRegVal().capVal().nodeId(); - dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, -1)); - } - - int64_t tmp = Rc1_trv.getRegVal().intVal(); - tmp = tmp + imm; - Rc1_trv.getRegVal().intVal() = tmp; - Rc1_trv = Rc1_trv; + Rc1_sd = Rc1_sd + imm; }}); 0x1: c_addiw({{ imm = CIMM5; @@ -160,20 +146,7 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared( "source reg x0", machInst); } - - using namespace gem5::RiscvcapstoneISA::o3; - - DynInst* dyn_inst = dynamic_cast(xc); - assert(dyn_inst); - - if(Rc1_trv.getTag()) { - Rc1_trv.setTag(false); - NodeID node_id = Rc1_trv.getRegVal().capVal().nodeId(); - dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, -1)); - } - - Rc1_trv.getRegVal().intVal() = imm; - Rc1_trv = Rc1_trv; + Rc1_sd = imm; }}); 0x3: decode RC1 { 0x2: c_addi16sp({{ @@ -203,19 +176,7 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared( "immediate = 0", machInst); } - using namespace gem5::RiscvcapstoneISA::o3; - - DynInst* dyn_inst = dynamic_cast(xc); - assert(dyn_inst); - - if(Rc1_trv.getTag()) { - Rc1_trv.setTag(false); - NodeID node_id = Rc1_trv.getRegVal().capVal().nodeId(); - dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, -1)); - } - - Rc1_trv.getRegVal().intVal() = imm; - Rc1_trv = Rc1_trv; + Rc1_sd = imm; }}); } } @@ -415,21 +376,18 @@ decode QUADRANT default Unknown::unknown() { 0x16: decode FUNCT3 { 0x1: decode FUNCT7 { format ROp { - //format CIOp 0x4: lcc ({{ using namespace gem5::RiscvcapstoneISA::o3; if(!Rs1_trv.getTag()) { return std::make_shared("Unexpected operand type (24)", machInst); } - //todo: there probably be a cleaner way of doing this - uint64_t res; bool except = false; Cap cap_val = Rs1_trv.getRegVal().capVal(); CapType t = cap_val.type(); switch(CIIMM5) { - case 0: break; //validity field - query then result? + case 0: break; //validity field - query then result case 1: res = static_cast(cap_val.type()); break; case 2: if(t == CapType::SEALED) { except = true; @@ -471,7 +429,6 @@ decode QUADRANT default Unknown::unknown() { DynInst *dyn_inst = dynamic_cast(xc); assert(dyn_inst); - //todo: set Rs1 to cnull if(!(Rs1_trv.getTag() && !Rs2_trv.getTag())) { return std::make_shared("Unexpected operand type (24)", machInst); } @@ -485,32 +442,32 @@ decode QUADRANT default Unknown::unknown() { uint64_t cursor = rs1_cap.cursor(); rs1_cap.setCursor(cursor + Rs2_trv.getRegVal().intVal()); - Rs1_trv.getRegVal().rawCapVal() = (uint128_t)rs1_cap; + + ConstTaggedRegVal temp_regval; + temp_regval.setTag(true); + temp_regval.getRegVal().rawCapVal() = (uint128_t)rs1_cap; - ConstTaggedRegVal temp; - temp.getRegVal().rawCapVal() = (uint128_t)rs1_cap; - temp.setTag(true); + Rd_trv = temp_regval; if(RS1 != RD) { //movc semantics - //rs1 still retains the original cap - if(rs1_cap.type() != CapType::NONLIN) + if(rs1_cap.type() != CapType::NONLIN) { Rs1_trv.setTag(false); - else { + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); + } else { uint64_t node_id = rs1_cap.nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } Rs1_trv = Rs1_trv; + } else { + Rs1_trv = temp_regval; } - - Rd_trv = temp; }}); 0x5: scc ({{ using namespace gem5::RiscvcapstoneISA::o3; DynInst *dyn_inst = dynamic_cast(xc); assert(dyn_inst); - //todo: set Rs1 to cnull if(!(Rs1_trv.getTag() && !Rs2_trv.getTag())) { return std::make_shared("Unexpected operand type (24)", machInst); } @@ -529,14 +486,16 @@ decode QUADRANT default Unknown::unknown() { if(RS1 != RD) { //movc semantics - //rs1 still retains the original cap - if(rs1_cap.type() != CapType::NONLIN) + if(rs1_cap.type() != CapType::NONLIN) { Rs1_trv.setTag(false); - else { + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); + } else { uint64_t node_id = rs1_cap.nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } Rs1_trv = Rs1_trv; + } else { + Rs1_trv = temp; } Rd_trv = temp; @@ -577,7 +536,6 @@ decode QUADRANT default Unknown::unknown() { Rd_trv = Rd_trv; }}); 0x3: delin ({{ - //todo: update captype also in node using namespace gem5::RiscvcapstoneISA::o3; if(!Rd_trv.getTag()) { @@ -619,10 +577,13 @@ decode QUADRANT default Unknown::unknown() { if(RS1 != RD) { Rs1_trv.setTag(false); + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); } Rs1_trv = Rs1_trv; }}); - 0x7: seal ({{ + } + format SealOp { + 0x7: seal ({{ //execute using namespace gem5::RiscvcapstoneISA::o3; if(!Rs1_trv.getTag()) { @@ -643,13 +604,28 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("Illegal operand value (29)", machInst); } + Addr EA = rs1_cap.start() + sizeof(RegVal); + + Fault fault = dyn_inst->initiateGetTag(EA); + if(fault != NoFault) + return fault; + }}, {{ //comp_code + bool tag_res = dyn_inst->getTagQueryRes(0); + if(!tag_res) { + return std::make_shared( + "Illegal operand value (29)", machInst); + } + + Cap rs1_cap = Rs1_trv.getRegVal().capVal(); rs1_cap.setType(CapType::SEALED); rs1_cap.setAsync(CapAsync::SYNC); Rs1_trv.getRegVal().rawCapVal() = (uint128_t)rs1_cap; Rd_trv = Rs1_trv; - if(RS1 != RD) + if(RS1 != RD) { Rs1_trv.setTag(false); + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); + } Rs1_trv = Rs1_trv; }}); } @@ -659,8 +635,6 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("Unexpected operand type (24)", machInst); } - //todo: write cnull to Rs1 - using namespace gem5::RiscvcapstoneISA::o3; DynInst* dyn_inst = dynamic_cast(xc); @@ -676,6 +650,7 @@ decode QUADRANT default Unknown::unknown() { dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } else { Rs1_trv.setTag(false); + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); } Rs1_trv = Rs1_trv; @@ -707,16 +682,13 @@ decode QUADRANT default Unknown::unknown() { return std::make_shared("Illegal operand value (29)", machInst); } - //do I need a query here? NodeID node_id = rs1_cap.nodeId(); - Fault fault = dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); - if(fault != NoFault) - return fault; auto& node_controller = dyn_inst->getNodeController(); NodeID to_allocate = node_controller.tryAllocate(); - fault = dyn_inst->initiateNodeCommand(new NodeAllocate(node_id, to_allocate, false)); + // node controller checks for the validity of the parent node + Fault fault = dyn_inst->initiateNodeCommand(new NodeAllocate(node_id, to_allocate, false)); if(fault != NoFault) return fault; @@ -725,12 +697,12 @@ decode QUADRANT default Unknown::unknown() { ConstTaggedRegVal temp; temp.setTag(true); - rd_cap.setBound(split_addr, end); + rd_cap.setAddresses(split_addr, end, split_addr); rd_cap.setNodeId(to_allocate); temp.getRegVal().rawCapVal() = (uint128_t)rd_cap; Rd_trv = temp; - rs1_cap.setBound(start, split_addr); + rs1_cap.setAddresses(start, split_addr, start); Rs1_trv.getRegVal().rawCapVal() = (uint128_t)rs1_cap; Rs1_trv = Rs1_trv; } @@ -742,16 +714,15 @@ decode QUADRANT default Unknown::unknown() { Rs1_trv.setTag(false); - if(1) { //if Rs1.valid == 1 - //todo: Rs1.valid = 0 - using namespace gem5::RiscvcapstoneISA::o3; + // whether the node ID is already valid or not + // is checked by the node controller + using namespace gem5::RiscvcapstoneISA::o3; - DynInst* dyn_inst = dynamic_cast(xc); - assert(dyn_inst); + DynInst* dyn_inst = dynamic_cast(xc); + assert(dyn_inst); - uint64_t node_id = Rs1_trv.getRegVal().capVal().nodeId(); - dyn_inst->initiateNodeCommand(new NodeDrop(node_id)); - } + uint64_t node_id = Rs1_trv.getRegVal().capVal().nodeId(); + dyn_inst->initiateNodeCommand(new NodeDrop(node_id)); Rs1_trv = Rs1_trv; }}); @@ -771,16 +742,11 @@ decode QUADRANT default Unknown::unknown() { NodeID node_id = Rs1_trv.getRegVal().capVal().nodeId(); - //do I need this query? if execution has been correct, this node should be - //valid right? - Fault fault = dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); - if(fault != NoFault) - return fault; - auto& node_controller = dyn_inst->getNodeController(); NodeID to_allocate = node_controller.tryAllocate(); - fault = dyn_inst->initiateNodeCommand(new NodeAllocate(node_id, to_allocate)); + // node controller checks whether node_id is valid + Fault fault = dyn_inst->initiateNodeCommand(new NodeAllocate(node_id, to_allocate)); if(fault != NoFault) return fault; @@ -835,9 +801,8 @@ decode QUADRANT default Unknown::unknown() { Rs1_trv.getRegVal().rawCapVal() = (uint128_t)rs1_cap; Rs1_trv = Rs1_trv; - }}); + }}, IsSerializeBefore, IsNonSpeculative, IsSerializeAfter); } - //format CIOp format ROp { 0x2: tighten ({{ using namespace gem5::RiscvcapstoneISA::o3; @@ -867,28 +832,29 @@ decode QUADRANT default Unknown::unknown() { } rs1_cap.setPerm(temp); - Rd_trv = Rs1_trv; - Rd_trv.getRegVal().rawCapVal() = (uint128_t)rs1_cap; + ConstTaggedRegVal temp_regval; + temp_regval.setTag(true); + temp_regval.getRegVal().rawCapVal() = (uint128_t)rs1_cap; if(RS1 != RD) { //movc semantics - //rs1 still retains the original cap - if(rs1_cap.type() != CapType::NONLIN) + if(rs1_cap.type() != CapType::NONLIN) { Rs1_trv.setTag(false); - else { + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); + } else { uint64_t node_id = rs1_cap.nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } Rs1_trv = Rs1_trv; + } else { + Rs1_trv = temp_regval; } + + Rd_trv = temp_regval; }}); } format Calls { - 0x20: call ({{ //execute - if(!dyn_inst->isSecureWorld()) { - return std::make_shared("Illegal instruction (2)", machInst); - } - + 0x40: call ({{ //execute if(!Rs1_trv.getTag()) return std::make_shared("Unexpected operand type (24)", machInst); @@ -914,12 +880,10 @@ decode QUADRANT default Unknown::unknown() { Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); pc_cap.setCursor(npc); // prepare the PC cap to save - //todo: clear Rs1 ra_trv = Rs1_trv; Cap rs1_cap = Rs1_trv.getRegVal().capVal(); uint128_t pc_mem_load, ceh_mem_load, csp_mem_load; - //need to fix rescheduled call? like a rescheduled load memcpy(&pc_mem_load, dyn_inst->getMemReadRes(0), sizeof(pc_mem_load)); memcpy(&ceh_mem_load, dyn_inst->getMemReadRes(1), sizeof(ceh_mem_load)); @@ -958,15 +922,13 @@ decode QUADRANT default Unknown::unknown() { rs1_cap.setReg(RD); rs1_cap.setAsync(CapAsync::SYNC); ra_trv.getRegVal().rawCapVal() = (uint128_t)rs1_cap; + + Rs1_trv.setTag(false); + Rs1_trv = Rs1_trv; }}); } format Return { - 0x21: returni ({{ //execute - if(!dyn_inst->isSecureWorld()) { - return std::make_shared("Illegal instruction (2)", machInst); - } - - //rs1 != 0 check?? + 0x41: returni ({{ //execute if(!Rs1_trv.getTag() || Rs2_trv.getTag()) { return std::make_shared("Unexpected operand type (24)", machInst); } @@ -1040,12 +1002,10 @@ decode QUADRANT default Unknown::unknown() { pc_cap.setCursor(Rs2_trv.getRegVal().intVal()); // prepare the PC cap to save uint128_t pc_mem_load, ceh_mem_load, csp_mem_load; - //need to fix rescheduled call? like a rescheduled load memcpy(&pc_mem_load, dyn_inst->getMemReadRes(0), sizeof(pc_mem_load)); memcpy(&ceh_mem_load, dyn_inst->getMemReadRes(1), sizeof(ceh_mem_load)); memcpy(&csp_mem_load, dyn_inst->getMemReadRes(2), sizeof(csp_mem_load)); - //also assert tag results maybe? Addr EA = rs1_cap.start(); @@ -1091,10 +1051,8 @@ decode QUADRANT default Unknown::unknown() { pc_cap.setCursor(Rs2_trv.getRegVal().intVal()); // prepare the PC cap to save uint128_t pc_mem_load; - //need to fix rescheduled call? like a rescheduled load memcpy(&pc_mem_load, dyn_inst->getMemReadRes(0), sizeof(pc_mem_load)); - //also assert tag results maybe? Addr cur_addr = rs1_cap.start() + 2 * sizeof(RegVal); @@ -1149,115 +1107,65 @@ decode QUADRANT default Unknown::unknown() { ConstTaggedRegVal tagged_val(v, tag); dyn_inst->setTaggedRegOperand(this, reg_idx, tagged_val); } - } - - Rs1_trv.setTag(false); - Rs1_trv = Rs1_trv; - }}); - } - format CapEnter { - 0x42: capenter ({{ - if(dyn_inst->isSecureWorld()) { - return std::make_shared("Illegal instruction (0)", machInst); - } - - if(!(Rs1_trv.getTag())) { - return std::make_shared("Unexpected operand type (24)", machInst); - } - - Cap rs1_cap = Rs1_trv.getRegVal().capVal(); - - if(rs1_cap.type() != CapType::SEALED) { - return std::make_shared("Unexpected capability type (26)", machInst); - } - - NodeID node_id = rs1_cap.nodeId(); - dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); - - if(rs1_cap.async() == CapAsync::SYNC) { - Addr cur_addr = rs1_cap.start(); - - RegVal dummy; - for(int i = 0; i < 3; i++, cur_addr += sizeof(RegVal)) { - initiateMemRead(xc, traceData, cur_addr, dummy, Request::Flags()); - dyn_inst->initiateGetTag(cur_addr); - } - } else { //upon exception or interrupt - Addr cur_addr = rs1_cap.start(); - - RegVal dummy; - for(int i = 0; i < 33; i++, cur_addr += sizeof(RegVal)) { - initiateMemRead(xc, traceData, cur_addr, dummy, Request::Flags()); - dyn_inst->initiateGetTag(cur_addr); - } - } - }}, {{ - Cap rs1_cap = Rs1_trv.getRegVal().capVal(); - CPU *cpu = dynamic_cast(dyn_inst->cpu); + } else { //upon interrupt + assert(dyn_inst->memReadN == 33); - if(rs1_cap.async() == CapAsync::SYNC) { + RiscvcapstoneISAInst::PCState pc_state; + set(pc_state, xc->pcState()); + uint64_t npc = pc_state.npc(); Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - uint64_t pc = pc_cap.cursor(); - - cpu->normal_pc[dyn_inst->threadNumber] = PC; - cpu->normal_sp[dyn_inst->threadNumber] = sp_trv; + pc_cap.setCursor(Rs2_trv.getRegVal().intVal()); // prepare the PC cap to save - uint128_t pc_mem_load, ceh_mem_load, csp_mem_load; - //need to fix rescheduled call? like a rescheduled load - //it's serializing, why would it be rescheduled + uint128_t pc_mem_load, ceh_mem_load; memcpy(&pc_mem_load, dyn_inst->getMemReadRes(0), sizeof(pc_mem_load)); memcpy(&ceh_mem_load, dyn_inst->getMemReadRes(1), sizeof(ceh_mem_load)); - memcpy(&csp_mem_load, dyn_inst->getMemReadRes(2), sizeof(csp_mem_load)); - //also assert tag results maybe? - Cap pc_cap_new(pc_mem_load); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap_new, dyn_inst->threadNumber); - - NPC = pc_cap_new.cursor(); - - ConstTaggedRegVal ceh; - ceh.setTag(true); - ceh.getRegVal().rawCapVal() = ceh_mem_load; - dyn_inst->setTaggedMiscReg(CAPMISCREG_CEH, ceh); + Addr cur_addr = rs1_cap.start(); - sp_trv.getRegVal().rawCapVal() = csp_mem_load; - sp_trv.setTag(true); - sp_trv = sp_trv; + ConstTaggedRegVal ceh = dyn_inst->readTaggedMiscReg(CAPMISCREG_CEH); + Cap ceh_cap = ceh.getRegVal().capVal(); - ConstTaggedRegVal temp_cra; - temp_cra.setTag(true); - rs1_cap.setType(CapType::EXIT); - rs1_cap.setCursor(rs1_cap.start()); - temp_cra.getRegVal().rawCapVal() = (uint128_t)rs1_cap; - ra_trv = temp_cra; + ConstTaggedRegVal cih = dyn_inst->readTaggedMiscReg(CAPMISCREG_CIH); - cpu->switch_reg[dyn_inst->threadNumber] = RS1; - cpu->exit_reg[dyn_inst->threadNumber] = RD; - } else { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - uint64_t pc = pc_cap.cursor(); + Fault fault = writeMemTimingLE(xc, traceData, (uint128_t)pc_cap, cur_addr, Request::Flags(), nullptr); + if (fault != NoFault) + return fault; + fault = writeMemTimingLE(xc, traceData, (uint128_t)ceh_cap, cur_addr + sizeof(RegVal), Request::Flags(), nullptr); + if (fault != NoFault) + return fault; - cpu->normal_pc[dyn_inst->threadNumber] = PC; - cpu->normal_sp[dyn_inst->threadNumber] = sp_trv; + rs1_cap.setType(CapType::SEALED); + rs1_cap.setAsync(CapAsync::SYNC); - uint128_t pc_mem_load, ceh_mem_load; - //need to fix rescheduled call? like a rescheduled load - //it's serializing, why would it be rescheduled + cih.getRegVal().rawCapVal() = (uint128_t)rs1_cap; + dyn_inst->setTaggedMiscReg(CAPMISCREG_CIH, cih); - memcpy(&pc_mem_load, dyn_inst->getMemReadRes(0), sizeof(pc_mem_load)); - memcpy(&ceh_mem_load, dyn_inst->getMemReadRes(1), sizeof(ceh_mem_load)); - //also assert tag results maybe? + ceh.getRegVal().rawCapVal() = ceh_mem_load; + dyn_inst->setTaggedMiscReg(CAPMISCREG_CEH, ceh); Cap pc_cap_new(pc_mem_load); dyn_inst->cpu->getIEWObject().setPCCap(pc_cap_new, dyn_inst->threadNumber); - NPC = pc_cap_new.cursor(); + //write context + for(int i = 0; i < NumIntArchRegs; i ++, cur_addr += sizeof(RegVal)) { + ConstTaggedRegVal v; + v = dyn_inst->getTaggedRegOperand(this, i); - ConstTaggedRegVal ceh; - ceh.setTag(true); - ceh.getRegVal().rawCapVal() = ceh_mem_load; - dyn_inst->setTaggedMiscReg(CAPMISCREG_CEH, ceh); + // store value + // DPRINTFN("Write context x%d %llx\n", i, v.getRegVal().intVal()); + fault = writeMemTimingLE(xc, traceData, v.getRegVal(), cur_addr, + Request::Flags(), nullptr); + if(fault != NoFault) { + return fault; + } + // store tag + //DPRINTFN("Set tag %d %d\n", i, v.getTag()); + fault = dyn_inst->initiateSetTag(cur_addr, v.getTag()); + if(fault != NoFault) { + return fault; + } + } for(int reg_idx = 0; reg_idx < NumIntArchRegs; reg_idx ++) { RegVal& v = *(RegVal*)(dyn_inst->getMemReadRes(reg_idx + 2)); @@ -1269,82 +1177,10 @@ decode QUADRANT default Unknown::unknown() { ConstTaggedRegVal tagged_val(v, tag); dyn_inst->setTaggedRegOperand(this, reg_idx, tagged_val); } - - rs1_cap.setType(CapType::UNINIT); - rs1_cap.setCursor(rs1_cap.start()); - - ConstTaggedRegVal temp_switch_cap; - temp_switch_cap.setTag(true); - temp_switch_cap.getRegVal().rawCapVal() = (uint128_t)rs1_cap; - dyn_inst->setTaggedMiscReg(CAPMISCREG_SWITCH_CAP, temp_switch_cap); - - cpu->switch_reg[dyn_inst->threadNumber] = RS1; - cpu->exit_reg[dyn_inst->threadNumber] = RD; } - cpu->cwrld[dyn_inst->threadNumber] = 1; - }}); - } - format CapExit { - 0x43: capexit ({{ - //i don't need comp code do i? - CPU *cpu = dynamic_cast(dyn_inst->cpu); - - if(!dyn_inst->isSecureWorld()) { - return std::make_shared("Illegal instruction (2)", machInst); - } - - if(!Rs1_trv.getTag() || Rs2_trv.getTag()) { - return std::make_shared("Unexpected operand type (24)", machInst); - } - - Cap rs1_cap = Rs1_trv.getRegVal().capVal(); - - if(rs1_cap.type() != CapType::EXIT) { - return std::make_shared("Unexpected capability type (26)", machInst); - } - - NodeID node_id = rs1_cap.nodeId(); - dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); - - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(Rs2_trv.getRegVal().intVal()); // prepare the PC cap to save - - ConstTaggedRegVal ceh = dyn_inst->readTaggedMiscReg(CAPMISCREG_CEH); - Cap ceh_cap = ceh.getRegVal().capVal(); - - Addr EA = rs1_cap.start(); - - //todo: load the cap from the mem location and update refcount - //also, update refcount for pc, ceh and csp - Fault fault = writeMemTimingLE(xc, traceData, (uint128_t)pc_cap, EA, Request::Flags(), nullptr); - if (fault != NoFault) - return fault; - fault = writeMemTimingLE(xc, traceData, (uint128_t)ceh_cap, EA + sizeof(RegVal), Request::Flags(), nullptr); - if (fault != NoFault) - return fault; - fault = writeMemTimingLE(xc, traceData, sp_trv.getRegVal().rawCapVal(), EA + 2*sizeof(RegVal), Request::Flags(), nullptr); - if (fault != NoFault) - return fault; - - sp_trv = cpu->normal_sp[dyn_inst->threadNumber]; - NPC = cpu->normal_pc[dyn_inst->threadNumber] + 4; - - rs1_cap.setType(CapType::SEALED); - rs1_cap.setAsync(CapAsync::SYNC); - unsigned reg_idx = cpu->switch_reg[dyn_inst->threadNumber]; - ConstTaggedRegVal tagged_val; - tagged_val.setTag(true); - tagged_val.getRegVal().rawCapVal() = (uint128_t)rs1_cap; - dyn_inst->setTaggedRegOperand(this, reg_idx, tagged_val); - - //use a different variable here or this is okay? - tagged_val.setTag(false); - tagged_val.getRegVal().intVal() = 0; - reg_idx = cpu->exit_reg[dyn_inst->threadNumber]; - dyn_inst->setTaggedRegOperand(this, reg_idx, tagged_val); - - cpu->cwrld[dyn_inst->threadNumber] = 0; + Rs1_trv.setTag(false); + Rs1_trv = Rs1_trv; }}); } } @@ -1354,7 +1190,6 @@ decode QUADRANT default Unknown::unknown() { DynInst *dyn_inst = dynamic_cast(xc); assert(dyn_inst); - //todo: set Rs1 to cnull if(!(Rs1_trv.getTag())) { return std::make_shared("Unexpected operand type (24)", machInst); } @@ -1376,14 +1211,16 @@ decode QUADRANT default Unknown::unknown() { if(RS1 != RD) { //movc semantics - //rs1 still retains the original cap - if(rs1_cap.type() != CapType::NONLIN) + if(rs1_cap.type() != CapType::NONLIN) { Rs1_trv.setTag(false); - else { + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); + } else { uint64_t node_id = rs1_cap.nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } Rs1_trv = Rs1_trv; + } else { + Rs1_trv = temp; } Rd_trv = temp; @@ -1391,6 +1228,7 @@ decode QUADRANT default Unknown::unknown() { } format RNodeMemOp { 0x3: ldc ({{ //ea_code + // rescheduled load shouldn't issue a tag load again if(dyn_inst->tagQueryN == 0) { Fault fault = dyn_inst->initiateGetTag(EA); if(fault != NoFault) @@ -1444,10 +1282,6 @@ decode QUADRANT default Unknown::unknown() { DynInst* dyn_inst = dynamic_cast(xc); assert(dyn_inst); - if(!dyn_inst->isSecureWorld()) { - return std::make_shared("Illegal instruction (2)", machInst); - } - if(!Rs1_trv.getTag()) { return std::make_shared("Unexpected operand type (24)", machInst); } @@ -1463,22 +1297,23 @@ decode QUADRANT default Unknown::unknown() { temp.getRegVal().rawCapVal() = (uint128_t)pc_cap; temp.setTag(true); - dyn_inst->cpu->getIEWObject().setPCCap(rs1_cap, - dyn_inst->threadNumber); + dyn_inst->cpu->getIEWObject().setPCCap(rs1_cap, dyn_inst->threadNumber); NPC = rs1_cap.cursor() + imm; - //write cnull to rs1 if(RS1 != RD) { if(rs1_cap.type() != CapType::NONLIN) { Rs1_trv.setTag(false); + memset(&Rs1_trv, 0, sizeof(Rs1_trv)); } else { NodeID node_id = Rs1_trv.getRegVal().capVal().nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } + Rs1_trv = Rs1_trv; + } else { + Rs1_trv = temp; } - Rs1_trv = Rs1_trv; Rd_trv = temp; }}, IsUncondControl); 0x6: cbnz ({{ @@ -1487,15 +1322,10 @@ decode QUADRANT default Unknown::unknown() { DynInst* dyn_inst = dynamic_cast(xc); assert(dyn_inst); - if(!dyn_inst->isSecureWorld()) { - return std::make_shared("Illegal instruction (2)", machInst); - } - if(!(Rd_trv.getTag() && !Rs1_trv.getTag())) { return std::make_shared("Unexpected operand type (24)", machInst); } - //should I set PC or NPC hmmm if(Rs1_trv.getRegVal().intVal() != 0) { Cap rd_cap = Rd_trv.getRegVal().capVal(); int64_t imm = sext<12>(IMM12); @@ -1505,9 +1335,9 @@ decode QUADRANT default Unknown::unknown() { NPC = rd_cap.cursor(); - //write cnull to rd if(rd_cap.type() != CapType::NONLIN) { Rd_trv.setTag(false); + memset(&Rd_trv, 0, sizeof(Rd_trv)); } else { NodeID node_id = rd_cap.nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); @@ -1531,11 +1361,10 @@ decode QUADRANT default Unknown::unknown() { if (fault != NoFault) return fault; }}, {{ //comp_code - //todo: optimization: update loaded cap refcount only if nodeid != Rs2.nodeid - - if(Rs2_trv.getRegVal().capVal().type() != CapType::NONLIN) + if(Rs2_trv.getRegVal().capVal().type() != CapType::NONLIN) { Rs2_trv.setTag(false); - else { + memset(&Rs2_trv, 0, sizeof(Rs2_trv)); + } else { NodeID node_id = Rs2_trv.getRegVal().capVal().nodeId(); dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); } @@ -1579,6 +1408,21 @@ decode QUADRANT default Unknown::unknown() { } break; } + case CCSR_CIH: + { + ConstTaggedRegVal reg_val = dyn_inst->readTaggedMiscReg(FUNCT12); + if(!reg_val.getTag()) { + reg_val = Rs1_trv; + if(Rs1_trv.getRegVal().capVal().type() != CapType::NONLIN) + Rs1_trv.setTag(false); + else { + NodeID node_id = Rs1_trv.getRegVal().capVal().nodeId(); + dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, 1)); + } + Rs1_trv = Rs1_trv; + } + break; + } default: return std::make_shared("Illegal operand value (29)", machInst); } @@ -1623,54 +1467,46 @@ decode QUADRANT default Unknown::unknown() { format ROp { 0x4: capcreate ({{ Rd_trv.setTag(true); - Rd_trv = Rd_trv; // just to make the dumb parser happy + Rd_trv = Rd_trv; }}); 0x5: captype ({{ using namespace gem5::RiscvcapstoneISA::o3; assert(Rd_trv.getTag()); - //using CapType = gem5::RiscvcapstoneISA::o3::CapType; CapType temp = static_cast(Rs1); assert(temp >= CapType::LIN && temp <= CapType::EXIT); - //Rd_trv.getRegVal().val.cap.setType(temp); Cap rd_cap = Rd_trv.getRegVal().capVal(); rd_cap.setType(temp); Rd_trv.getRegVal().rawCapVal() = (uint128_t)rd_cap; - Rd_trv = Rd_trv; // just to make the dumb parser happy + Rd_trv = Rd_trv; }}); 0x6: capnode ({{ assert(Rd_trv.getTag()); using namespace gem5::RiscvcapstoneISA::o3; - //Rd_trv.getRegVal().val.cap.setNodeId(static_cast(Rs1)); Cap rd_cap = Rd_trv.getRegVal().capVal(); rd_cap.setNodeId(Rs1); Rd_trv.getRegVal().rawCapVal() = (uint128_t)rd_cap; - Rd_trv = Rd_trv; // just to make the dumb parser happy + Rd_trv = Rd_trv; }}); 0x7: capperm ({{ using namespace gem5::RiscvcapstoneISA::o3; assert(Rd_trv.getTag()); - //using CapPerm = gem5::RiscvcapstoneISA::o3::CapPerm; CapPerm temp = static_cast(Rs1); assert(temp >= CapPerm::NA && temp <= CapPerm::RWX); - //Rd_trv.getRegVal().val.cap.setPerm(temp); Cap rd_cap = Rd_trv.getRegVal().capVal(); rd_cap.setPerm(temp); Rd_trv.getRegVal().rawCapVal() = (uint128_t)rd_cap; - Rd_trv = Rd_trv; // just to make the dumb parser happy + Rd_trv = Rd_trv; }}); 0x8: capbound ({{ using namespace gem5::RiscvcapstoneISA::o3; assert(Rd_trv.getTag()); //DPRINTFN("Set capability bound to (%llx, %llx)\n", Rs1, Rs2); - //Rd_trv.getRegVal().val.cap.setAddresses(Rs1, Rs2, Rs1); Cap rd_cap = Rd_trv.getRegVal().capVal(); rd_cap.setAddresses(Rs1, Rs2, Rs1); Rd_trv.getRegVal().rawCapVal() = (uint128_t)rd_cap; - Rd_trv = Rd_trv; // just to make the dumb parser happy + Rd_trv = Rd_trv; }}); 0x9: capprint ({{ - //const RegVal& reg_val = Rs1_trv.getRegVal(); - //if(Rs1_trv.getTag()) { gem5::RiscvcapstoneISA::o3::Cap rs1_cap = Rs1_trv.getRegVal().capVal(); DPRINTFN("x%u capability (tag = %u) = (%llx, %llx), %llx, perm = %u, type = %u, node = %llu\n", RS1, @@ -1680,10 +1516,7 @@ decode QUADRANT default Unknown::unknown() { static_cast(rs1_cap.perm()), static_cast(rs1_cap.type()), rs1_cap.nodeId()); - //} else { - // DPRINTFN("%c", Rs1_trv.getRegVal().intVal()); - //} - }}, IsSerializing, IsNonSpeculative, IsSerializeAfter); + }}, IsSerializeBefore, IsNonSpeculative, IsSerializeAfter); 0x13: justprint ({{ std::cout << Rs1_ud << ' '; }}); @@ -1692,12 +1525,12 @@ decode QUADRANT default Unknown::unknown() { DynInst *dyn_inst = dynamic_cast(xc); assert(dyn_inst); dyn_inst->printRegs(); - }}, IsSerializing, IsNonSpeculative, IsSerializeAfter); + }}, IsSerializeBefore, IsNonSpeculative, IsSerializeAfter); 0x1e: getrand ({{ srand(time(NULL)); //std::cout << Rs2_ud << ' '; Rd_ud = rand() % Rs2_ud; - }}, IsSerializing, IsNonSpeculative, IsSerializeAfter); + }}, IsSerializeBefore, IsNonSpeculative, IsSerializeAfter); } format TagAccessStore { 0xa: tagset ({{ @@ -1717,16 +1550,6 @@ decode QUADRANT default Unknown::unknown() { dyn_inst->getTagQueryRes(0)); }}); } - format ROp { - 0xc: cssetworld ({{ - Rs1_ud; - //0xe: csseteh - //0xf: csonnormaleh - }}); - 0xd: csonpartition ({{ - Rs1_ud; - }}); - } format RNodeOp { 0x11: printnode ({{ using namespace gem5::RiscvcapstoneISA::o3; @@ -1736,7 +1559,7 @@ decode QUADRANT default Unknown::unknown() { NodeID node_id = Rs1_ud; dyn_inst->initiateNodeCommand(new NodeQueryDbg(node_id)); - }}, IsSerializing, IsNonSpeculative); + }}, IsSerializeBefore, IsSerializeAfter, IsNonSpeculative); } } //End Capstone Test Ops @@ -1921,13 +1744,7 @@ decode QUADRANT default Unknown::unknown() { format IOp { 0x0: addi({{ - if(Rs1_trv.getTag()) { - return std::make_shared( - "addi: Can't perform this op on a capability!", machInst); - } - Rd_trv.getRegVal().intVal() = Rs1_trv.getRegVal().intVal() + imm; - - Rd_trv = Rd_trv; + Rd_sd = Rs1_sd + imm; }}); 0x2: slti({{ Rd = (Rs1_sd < imm) ? 1 : 0; @@ -1989,13 +1806,7 @@ decode QUADRANT default Unknown::unknown() { 0x06: decode FUNCT3 { format IOp { 0x0: addiw({{ - if(Rs1_trv.getTag()) { - return std::make_shared( - "addiw: Can't perform this op on a capability!", machInst); - } - Rs1_trv.getRegVal().intVal() = (int32_t)(Rs1_trv.getRegVal().intVal() + imm); - - Rs1_trv = Rs1_trv; + Rd_sw = (int32_t)(Rs1_sw + imm); }}, int32_t); 0x1: decode FS3 { 0x0: slliw({{ @@ -2498,20 +2309,7 @@ decode QUADRANT default Unknown::unknown() { } 0x0d: UOp::lui({{ - using namespace gem5::RiscvcapstoneISA::o3; - - DynInst* dyn_inst = dynamic_cast(xc); - assert(dyn_inst); - - if(Rd_trv.getTag()) { - Rd_trv.setTag(false); - NodeID node_id = Rd_trv.getRegVal().capVal().nodeId(); - dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, -1)); - } - - Rd_trv.getRegVal().intVal() = (uint64_t)(sext<20>(imm) << 12); - - Rd_trv = Rd_trv; + Rd = (uint64_t)(sext<20>(imm) << 12); }}); 0x0e: decode FUNCT3 { @@ -3234,11 +3032,9 @@ decode QUADRANT default Unknown::unknown() { format BOp { 0x0: beq({{ if (Rs1 == Rs2) { - if(dyn_inst->isSecureWorld()) { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(PC + imm); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); + pc_cap.setCursor(PC + imm); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); NPC = PC + imm; } else { NPC = NPC; @@ -3246,11 +3042,9 @@ decode QUADRANT default Unknown::unknown() { }}, IsDirectControl, IsCondControl); 0x1: bne({{ if (Rs1 != Rs2) { - if(dyn_inst->isSecureWorld()) { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(PC + imm); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); + pc_cap.setCursor(PC + imm); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); NPC = PC + imm; } else { NPC = NPC; @@ -3258,11 +3052,9 @@ decode QUADRANT default Unknown::unknown() { }}, IsDirectControl, IsCondControl); 0x4: blt({{ if (Rs1_sd < Rs2_sd) { - if(dyn_inst->isSecureWorld()) { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(PC + imm); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); + pc_cap.setCursor(PC + imm); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); NPC = PC + imm; } else { NPC = NPC; @@ -3270,11 +3062,9 @@ decode QUADRANT default Unknown::unknown() { }}, IsDirectControl, IsCondControl); 0x5: bge({{ if (Rs1_sd >= Rs2_sd) { - if(dyn_inst->isSecureWorld()) { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(PC + imm); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); + pc_cap.setCursor(PC + imm); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); NPC = PC + imm; } else { NPC = NPC; @@ -3282,11 +3072,9 @@ decode QUADRANT default Unknown::unknown() { }}, IsDirectControl, IsCondControl); 0x6: bltu({{ if (Rs1 < Rs2) { - if(dyn_inst->isSecureWorld()) { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(PC + imm); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); + pc_cap.setCursor(PC + imm); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); NPC = PC + imm; } else { NPC = NPC; @@ -3294,11 +3082,9 @@ decode QUADRANT default Unknown::unknown() { }}, IsDirectControl, IsCondControl); 0x7: bgeu({{ if (Rs1 >= Rs2) { - if(dyn_inst->isSecureWorld()) { - Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); - pc_cap.setCursor(PC + imm); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); + pc_cap.setCursor(PC + imm); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); NPC = PC + imm; } else { NPC = NPC; @@ -3317,22 +3103,15 @@ decode QUADRANT default Unknown::unknown() { Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); ConstTaggedRegVal temp_regval; - if(dyn_inst->isSecureWorld()) { - pc_cap.setCursor(NPC); - temp_regval.setTag(true); - temp_regval.getRegVal().rawCapVal() = (uint128_t)pc_cap; - } else { - temp_regval.setTag(false); - temp_regval.getRegVal().intVal() = NPC; - } + pc_cap.setCursor(NPC); + temp_regval.setTag(true); + temp_regval.getRegVal().rawCapVal() = (uint128_t)pc_cap; NPC = (imm + Rs1) & (~0x1); Rd_trv = temp_regval; - if(dyn_inst->isSecureWorld()) { - pc_cap.setCursor(NPC); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + pc_cap.setCursor(NPC); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); }}, IsIndirectControl, IsUncondControl); } @@ -3340,22 +3119,15 @@ decode QUADRANT default Unknown::unknown() { Cap pc_cap = dyn_inst->cpu->getIEWObject().getPCCap(dyn_inst->threadNumber); ConstTaggedRegVal temp_regval; - if(dyn_inst->isSecureWorld()) { - pc_cap.setCursor(NPC); - temp_regval.setTag(true); - temp_regval.getRegVal().rawCapVal() = (uint128_t)pc_cap; - } else { - temp_regval.setTag(false); - temp_regval.getRegVal().intVal() = NPC; - } + pc_cap.setCursor(NPC); + temp_regval.setTag(true); + temp_regval.getRegVal().rawCapVal() = (uint128_t)pc_cap; NPC = PC + imm; Rd_trv = temp_regval; - if(dyn_inst->isSecureWorld()) { - pc_cap.setCursor(NPC); - dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); - } + pc_cap.setCursor(NPC); + dyn_inst->cpu->getIEWObject().setPCCap(pc_cap, dyn_inst->threadNumber); }}, IsDirectControl, IsUncondControl); 0x1c: decode FUNCT3 { diff --git a/src/arch/riscvcapstone/isa/formats/calls.isa b/src/arch/riscvcapstone/isa/formats/calls.isa index a676a6c63c..44ab8fab06 100644 --- a/src/arch/riscvcapstone/isa/formats/calls.isa +++ b/src/arch/riscvcapstone/isa/formats/calls.isa @@ -76,6 +76,7 @@ def template CallsConstructor {{ flags[IsIndirectControl] = true; flags[IsUncondControl] = true; flags[IsNonSpeculative] = true; + flags[IsSerializeBefore] = true; flags[IsSerializeAfter] = true; hasNodeOp = true; } @@ -178,6 +179,7 @@ def template ReturnConstructor {{ flags[IsIndirectControl] = true; flags[IsUncondControl] = true; flags[IsNonSpeculative] = true; + flags[IsSerializeBefore] = true; flags[IsSerializeAfter] = true; hasNodeOp = true; } diff --git a/src/arch/riscvcapstone/isa/formats/rnode.isa b/src/arch/riscvcapstone/isa/formats/rnode.isa index 4ab8f4409d..15b3aecfd4 100644 --- a/src/arch/riscvcapstone/isa/formats/rnode.isa +++ b/src/arch/riscvcapstone/isa/formats/rnode.isa @@ -138,58 +138,42 @@ def template RNodeMemExecute {{ CPU *o3cpu = dynamic_cast(dyn_inst->getCpuPtr()); assert(o3cpu); - bool cwrld = o3cpu->cwrld[dyn_inst->threadNumber]; - uint64_t emode = o3cpu->readMiscReg(MISCREG_EMODE, dyn_inst->threadNumber); - if(cwrld || (!cwrld && emode)) { - if(!Rs1.getTag()) { - return std::make_shared("Unexpected operand type (24)", machInst); - } - - Cap rs1_cap = Rs1.getRegVal().capVal(); - - if(rs1_cap.type() == CapType::UNINIT || - rs1_cap.type() == CapType::SEALED || - rs1_cap.type() == CapType::REV || - (rs1_cap.type() == CapType::SEALEDRET && rs1_cap.async() != CapAsync::SYNC)) { - return std::make_shared("Unexpected capability type (26)", machInst); - } - - if((rs1_cap.type() == CapType::LIN || rs1_cap.type() == CapType::NONLIN) && - !rs1_cap.hasReadPerm()) { - return std::make_shared("Insufficient capability permissions (27)", machInst); - } - } else { //integer encoding mode - if(Rs1.getTag()) { - return std::make_shared("Unexpected operand type (24)", machInst); - } + if(!Rs1.getTag()) { + return std::make_shared("Unexpected operand type (24)", machInst); } - Addr EA; + Cap rs1_cap = Rs1.getRegVal().capVal(); - if(cwrld || (!cwrld && emode)) { - Cap rs1_cap = Rs1.getRegVal().capVal(); - EA = rs1_cap.cursor() + imm; + if(rs1_cap.type() == CapType::UNINIT || + rs1_cap.type() == CapType::SEALED || + rs1_cap.type() == CapType::REV || + (rs1_cap.type() == CapType::SEALEDRET && rs1_cap.async() != CapAsync::SYNC)) { + return std::make_shared("Unexpected capability type (26)", machInst); + } - if(!capInBoundForMemAcc(rs1_cap, EA, sizeof(Mem))) { - return std::make_shared( - "Capability out of bound (28)", machInst); - } + if((rs1_cap.type() == CapType::LIN || rs1_cap.type() == CapType::NONLIN) && + !rs1_cap.hasReadPerm()) { + return std::make_shared("Insufficient capability permissions (27)", machInst); + } - //DPRINTFN("MemReads count = %d, tag query count = %d\n", - //dyn_inst->memReadN, dyn_inst->tagQueryN); + Addr EA; - NodeID node_id = rs1_cap.nodeId(); - if(dyn_inst->nodeQueryN == 0) - dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); - } else { - EA = Rs1.getRegVal().intVal() + imm; + EA = rs1_cap.cursor() + imm; - if(dyn_inst->addrInSecRegion(EA, sizeof(Mem))) { - return std::make_shared( - "Load access fault (5)", machInst); - } + if(!capInBoundForMemAcc(rs1_cap, EA, sizeof(Mem))) { + return std::make_shared( + "Capability out of bound (28)", machInst); } + //DPRINTFN("MemReads count = %d, tag query count = %d\n", + //dyn_inst->memReadN, dyn_inst->tagQueryN); + + NodeID node_id = rs1_cap.nodeId(); + + // if this is a rescheduled load, it shouldn't issue a node command again + if(dyn_inst->nodeQueryN == 0) + dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); + if ((EA & (sizeof(Mem) - 1)) != 0) { return std::make_shared( "Load address misaligned (4)", machInst); @@ -215,13 +199,6 @@ def template RNodeMemCompleteAcc {{ %(op_decl)s; %(op_rd)s; - - if(Rd.getTag()) { - Cap rd_cap = Rd.getRegVal().capVal(); - NodeID node_id = rd_cap.nodeId(); - dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, -1)); - } - %(memacc_code)s; %(op_wb)s; return NoFault; @@ -276,62 +253,44 @@ def template RNodeStoreExecute {{ CPU *o3cpu = dynamic_cast(dyn_inst->getCpuPtr()); assert(o3cpu); - bool cwrld = o3cpu->cwrld[dyn_inst->threadNumber]; - uint64_t emode = o3cpu->readMiscReg(MISCREG_EMODE, dyn_inst->threadNumber); - if(cwrld || (!cwrld && emode)) { - if(!Rs1.getTag()) { - return std::make_shared( - "Unexpected operand type (24)", machInst); - } - - Cap rs1_cap = Rs1.getRegVal().capVal(); - - if(rs1_cap.type() == CapType::SEALED || rs1_cap.type() == CapType::REV || - (rs1_cap.type() == CapType::SEALEDRET && rs1_cap.async() != CapAsync::SYNC)) { - return std::make_shared( - "Unexpected capability type (26)", machInst); - } - - if((rs1_cap.type() == CapType::LIN || rs1_cap.type() == CapType::NONLIN) && - !rs1_cap.hasWritePerm()) { - return std::make_shared( - "Insufficient capability permissions (27)", machInst); - } - } else { //integer encoding mode - if(Rs1.getTag()) { - return std::make_shared( - "Unexpected operand type (24)", machInst); - } + if(!Rs1.getTag()) { + DPRINTFN("no cap!!!!!!\n"); + return std::make_shared( + "Unexpected operand type (24)", machInst); + } + + Cap rs1_cap = Rs1.getRegVal().capVal(); + + if(rs1_cap.type() == CapType::SEALED || rs1_cap.type() == CapType::REV || + (rs1_cap.type() == CapType::SEALEDRET && rs1_cap.async() != CapAsync::SYNC)) { + return std::make_shared( + "Unexpected capability type (26)", machInst); + } + + if((rs1_cap.type() == CapType::LIN || rs1_cap.type() == CapType::NONLIN) && + !rs1_cap.hasWritePerm()) { + return std::make_shared( + "Insufficient capability permissions (27)", machInst); } %(check_code)s; Addr EA; int64_t offset = sext<12>(IMM5 | (IMM7 << 5)); - if(cwrld || (!cwrld && emode)) { - Cap rs1_cap = Rs1.getRegVal().capVal(); - EA = rs1_cap.cursor() + offset; + EA = rs1_cap.cursor() + offset; - if(rs1_cap.type() == CapType::UNINIT && offset) { - return std::make_shared( - "Illegal operand value (29)", machInst); - } - - if(!capInBoundForMemAcc(rs1_cap, EA, sizeof(Mem))) { - return std::make_shared( - "Capability out of bound (28)", machInst); - } - - NodeID node_id = rs1_cap.nodeId(); - dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); - } else { - EA = Rs1.getRegVal().intVal() + offset; + if(rs1_cap.type() == CapType::UNINIT && offset) { + return std::make_shared( + "Illegal operand value (29)", machInst); + } - if(dyn_inst->addrInSecRegion(EA, sizeof(Mem))) { - return std::make_shared( - "Store/AMO access fault (7)", machInst); - } + if(!capInBoundForMemAcc(rs1_cap, EA, sizeof(Mem))) { + return std::make_shared( + "Capability out of bound (28)", machInst); } + + NodeID node_id = rs1_cap.nodeId(); + dyn_inst->initiateNodeCommand(new NodeQuery(node_id)); if(EA & (sizeof(Mem) - 1)) return std::make_shared( @@ -372,14 +331,12 @@ def template RNodeStoreMemCompleteAcc {{ dyn_inst->initiateNodeCommand(new NodeRcUpdate(node_id, -1)); } - if(Rs1.getTag()) { - Cap rs1_cap = Rs1.getRegVal().capVal(); + Cap rs1_cap = Rs1.getRegVal().capVal(); - if(rs1_cap.type() == CapType::UNINIT) - rs1_cap.setCursor(rs1_cap.cursor() + sizeof(Mem)); + if(rs1_cap.type() == CapType::UNINIT) + rs1_cap.setCursor(rs1_cap.cursor() + sizeof(Mem)); - Rs1.getRegVal().rawCapVal() = (uint128_t)rs1_cap; - } + Rs1.getRegVal().rawCapVal() = (uint128_t)rs1_cap; %(comp_code)s; @@ -406,3 +363,33 @@ def template RNodeStoreMemDeclare {{ using %(base_class)s::generateDisassembly; }; }}; + +def format SealOp(ea_code, memacc_code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'RegNodeOp', + {'ea_code': ea_code, + 'memacc_code': memacc_code}, opt_flags) + header_output = RNodeMemDeclare.subst(iop) + decoder_output = RNodeMemConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = (SealExecute.subst(iop) + + RNodeMemCompleteAcc.subst(iop)) +}}; + +def template SealExecute {{ + Fault + %(class_name)s::execute(ExecContext *xc, + Trace::InstRecord *traceData) const + { + + using namespace gem5::RiscvcapstoneISA::o3; + + DynInst* dyn_inst = dynamic_cast(xc); + assert(dyn_inst); + + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + return NoFault; + } +}}; diff --git a/src/arch/riscvcapstone/mmu.hh b/src/arch/riscvcapstone/mmu.hh index 448d50eca1..ad1cdae9b3 100644 --- a/src/arch/riscvcapstone/mmu.hh +++ b/src/arch/riscvcapstone/mmu.hh @@ -57,10 +57,8 @@ namespace RiscvcapstoneISA { class MMU : public BaseMMU { public: - PMAChecker *pma; - MMU(const RiscvMMUParams &p) - : BaseMMU(p), pma(p.pma_checker) + : BaseMMU(p) {} TranslationGenPtr @@ -74,14 +72,9 @@ class MMU : public BaseMMU PrivilegeMode getMemPriv(ThreadContext *tc, BaseMMU::Mode mode) { - return static_cast(dtb)->getMemPriv(tc, mode); + return PrivilegeMode::PRV_U; } - Walker * - getDataWalker() - { - return static_cast(dtb)->getWalker(); - } Fault translateAtomic(const RequestPtr& req, ThreadContext* tc, Mode mode) override { DPRINTF(CapstoneMem, "translate (atomic) %llx\n", req->getVaddr()); @@ -91,23 +84,15 @@ class MMU : public BaseMMU void translateTiming(const RequestPtr& req, ThreadContext* tc, Translation* translation, Mode mode) override { - if(1) { - DPRINTF(CapstoneMem, "translate %llx\n", req->getVaddr()); - req->setPaddr(req->getVaddr()); // simply pass through - translation->finish(NoFault, req, tc, mode); - } else { - return getTlb(mode)->translateTiming(req, tc, translation, mode); - } + DPRINTF(CapstoneMem, "translate %llx\n", req->getVaddr()); + req->setPaddr(req->getVaddr()); // simply pass through + translation->finish(NoFault, req, tc, mode); } Fault translateFunctional(const RequestPtr& req, ThreadContext* tc, Mode mode) override { - if(1) { - req->setPaddr(req->getVaddr()); // simply pass through + req->setPaddr(req->getVaddr()); // simply pass through - return NoFault; - } else { - return getTlb(mode)->translateFunctional(req, tc, mode); - } + return NoFault; } void flushAll() override {} @@ -117,19 +102,8 @@ class MMU : public BaseMMU } void - takeOverFrom(BaseMMU *old_mmu) override - { - MMU *ommu = dynamic_cast(old_mmu); - BaseMMU::takeOverFrom(ommu); - pma->takeOverFrom(ommu->pma); - - } + takeOverFrom(BaseMMU *old_mmu) override {} - PMP * - getPMP() - { - return static_cast(dtb)->pmp; - } }; } // namespace RiscvcapstoneISA diff --git a/src/arch/riscvcapstone/o3/CapstoneBaseO3CPU.py b/src/arch/riscvcapstone/o3/CapstoneBaseO3CPU.py index 90703cc7c5..c05bf788ac 100644 --- a/src/arch/riscvcapstone/o3/CapstoneBaseO3CPU.py +++ b/src/arch/riscvcapstone/o3/CapstoneBaseO3CPU.py @@ -179,7 +179,3 @@ def support_take_over(cls): ncqSize = Param.Unsigned(32, "Size of the node command queue") tcache_port = RequestPort('tag cache port') - - secure_base = Param.Unsigned(0, "Secure Memory Base Address") - secure_end = Param.Unsigned(0, "Secure Memory End Address") - diff --git a/src/arch/riscvcapstone/o3/commit.cc b/src/arch/riscvcapstone/o3/commit.cc index bccceb6e31..16e4c01eaf 100644 --- a/src/arch/riscvcapstone/o3/commit.cc +++ b/src/arch/riscvcapstone/o3/commit.cc @@ -1213,48 +1213,46 @@ Commit::commitHead(const DynInstPtr &head_inst, unsigned inst_num) } DPRINTF(Commit, "Issuing node commands for inst PC %s [sn:%u]\n", head_inst->pcState(), head_inst->seqNum); - // for (unsigned i = 0; i < nodeFromRename->size; i++) { - // DPRINTF(Commit, "NodeID: %u\n", nodeFromRename->cmds[i].first); - // if(nodeFromRename->insts[i]->seqNum == head_inst->seqNum) { - // NodeID node_id = nodeFromRename->cmds[i].first; - // int delta = nodeFromRename->cmds[i].second; - - // DPRINTF(Commit, "Doing RcUpdate for NodeID: %u, delta: %d\n", node_id, delta); - - // head_inst->initiateNodeCommand(new NodeRcUpdate(node_id, delta)); - // } - // } - //very, very hacked together - //seriously, there has to be a better way to do this. - //how would split change RC? need to check the spec + + /** + * Handle the case where a destination register being written to + * previously contained a capability. Move RcUpdate to commit from execute + * This helps to avoid issuing an RcUpdate in execute, + * Which in turn helps us avoid unnecessary register dependency + * as we don't need to wait for previous insts writing to Rd to commit + * if we're not going to read from Rd + */ std::string mnemonic = head_inst->staticInst->getName(); if(head_inst->fault == NoFault && head_inst->staticInst->opClass() != No_OpClass && mnemonic != "capperm" && mnemonic != "captype" && mnemonic != "capnode" && mnemonic != "capbound" && mnemonic != "stc" && - mnemonic != "std" && mnemonic != "stb" && - mnemonic != "sth" && mnemonic != "stw" && + mnemonic != "sd" && mnemonic != "sb" && + mnemonic != "sh" && mnemonic != "sw" && mnemonic != "capcreate" && mnemonic != "capprint" && - mnemonic != "scc" && mnemonic != "delin" && - mnemonic != "init" && mnemonic != "tighten" && - mnemonic != "shrink" && + mnemonic != "revoke" && mnemonic != "delin" && + mnemonic != "drop" && mnemonic != "shrink" && + mnemonic != "call" && mnemonic != "returni" && head_inst->numDestRegs() > 0) { - // if(iewStage->ncQueue.isFull(tid)) { - // DPRINTF(Commit, "[tid:%i] NCQ has become full.\n", tid); - // return false; - // } - - CPU* cpu = dynamic_cast(head_inst->getCpuPtr()); - PhysRegIdPtr prev_reg = head_inst->prevDestIdx(0); //FIXME: this may be 0, may not be 0 - if(!(prev_reg->classValue() == InvalidRegClass || prev_reg->classValue() == MiscRegClass)) { - TaggedRegVal tagged_reg = cpu->getWritableTaggedReg(prev_reg); - if(tagged_reg.getTag()) { - tagged_reg.setTag(false); - NodeID node_id = tagged_reg.getRegVal().capVal().nodeId(); - NodeCommandPtr cmd; - cpu->pushNodeCommand(head_inst, new NodeRcUpdate(head_inst, node_id, -1)); - cpu->setTaggedReg(prev_reg, tagged_reg); - DPRINTF(Commit, "Issued RcUpdate for nodeId = %u\n", node_id); + // these instructions can have RS1 == RD, and in that case, + // there should be no RcUpdate + if ((mnemonic == "cincoffset" || mnemonic == "cincoffsetimm" || mnemonic == "scc" || + mnemonic == "init" || mnemonic == "seal" || mnemonic == "tighten" || mnemonic == "movc") && + head_inst->destRegIdx(0) == head_inst->destRegIdx(1)); + else { + DPRINTF(Commit, "[sn:%d] %s rcupdate\n", head_inst->seqNum, mnemonic); + CPU* cpu = dynamic_cast(head_inst->getCpuPtr()); + PhysRegIdPtr prev_reg = head_inst->prevDestIdx(0); + if(!(prev_reg->classValue() == InvalidRegClass || prev_reg->classValue() == MiscRegClass)) { + TaggedRegVal tagged_reg = cpu->getWritableTaggedReg(prev_reg); + if(tagged_reg.getTag()) { + tagged_reg.setTag(false); + NodeID node_id = tagged_reg.getRegVal().capVal().nodeId(); + NodeCommandPtr cmd; + cpu->pushNodeCommand(head_inst, new NodeRcUpdate(head_inst, node_id, -1)); + cpu->setTaggedReg(prev_reg, tagged_reg); + DPRINTF(Commit, "Issued RcUpdate for nodeId = %u\n", node_id); + } } } } diff --git a/src/arch/riscvcapstone/o3/cpu.cc b/src/arch/riscvcapstone/o3/cpu.cc index 67fced2087..fffe513c44 100644 --- a/src/arch/riscvcapstone/o3/cpu.cc +++ b/src/arch/riscvcapstone/o3/cpu.cc @@ -114,8 +114,6 @@ CPU::CPU(const CapstoneBaseO3CPUParams ¶ms) globalSeqNum(1), system(params.system), lastRunningCycle(curCycle()), - secure_base(params.secure_base), - secure_end(params.secure_end), cpuStats(this) { fatal_if(FullSystem && params.numThreads > 1, @@ -520,12 +518,12 @@ CPU::printRegs() DPRINTFN("%s has value ", IntRegNames[i]); DPRINTFN("Capability (tag = %u) = (%llx, %llx), %llx, perm = %u, type = %u, node = %llu\n", - tmp.getTag(), - c.start(), c.end(), - c.cursor(), - static_cast(c.perm()), - static_cast(c.type()), - c.nodeId()); + tmp.getTag(), + c.start(), c.end(), + c.cursor(), + static_cast(c.perm()), + static_cast(c.type()), + c.nodeId()); } } @@ -563,16 +561,15 @@ CPU::startup() Cap *cap = new Cap; cap->setPerm(CapPerm::RWX); cap->setType(CapType::LIN); - cap->setBound(secure_base, secure_end); + cap->setBound(0x0, 0xFFFFFFFF); cap->setNodeId(0); + // allocate the node for the init capability iew.ncQueue.allocateInit(tid); ConstTaggedRegVal ctrv; ctrv.setTag(true); ctrv.getRegVal().rawCapVal() = (uint128_t)*cap; isa[tid]->setTaggedMiscReg(1, ctrv); //capmiscreg_cinit - - cwrld[tid] = 0; } } diff --git a/src/arch/riscvcapstone/o3/cpu.hh b/src/arch/riscvcapstone/o3/cpu.hh index bd9ec23fad..a3d43a479c 100644 --- a/src/arch/riscvcapstone/o3/cpu.hh +++ b/src/arch/riscvcapstone/o3/cpu.hh @@ -691,15 +691,6 @@ class CPU : public BaseCPU return iew; } - uint64_t cwrld[MaxThreads]; //secure world or normal world - uint64_t normal_pc[MaxThreads]; - ConstTaggedRegVal normal_sp[MaxThreads]; - uint64_t switch_reg[MaxThreads]; - uint64_t exit_reg[MaxThreads]; - - Addr secure_base; - Addr secure_end; - }; } // namespace RiscvcapstoneISA::o3 diff --git a/src/arch/riscvcapstone/o3/dyn_inst.cc b/src/arch/riscvcapstone/o3/dyn_inst.cc index b50f2f9314..5d16582bec 100644 --- a/src/arch/riscvcapstone/o3/dyn_inst.cc +++ b/src/arch/riscvcapstone/o3/dyn_inst.cc @@ -248,12 +248,6 @@ DynInst::~DynInst() } } - // for(int i = 0; i < MAX_QUERY_N; i++) { - // if(xyz[i] != nullptr) { - // delete xyz[i]; - // } - // } - delete traceData; fault = NoFault; @@ -398,6 +392,7 @@ DynInst::completeMemAcc(PacketPtr pkt) } } + // determine which memory access is complete if(pkt && pkt->isRead()) { int i; for (i = 0; i < memReadN && !pkt->matchAddr(memReads[i].addr, false); @@ -519,9 +514,8 @@ DynInst::completeMemRead(int idx, PacketPtr pkt) { * Need to create a new local Packet object as LSQUnit may delete * the original to free up space, before completeAcc can be called. */ - // lastPacket = pkt; - xyz[idx] = new Packet(pkt, false, true); - lastPacket = xyz[idx]; + readRes[idx] = new Packet(pkt, false, true); + lastPacket = readRes[idx]; // handle the packet here and move data to a separate buffer assert(pkt->getSize() <= MAX_REQUEST_SIZE); @@ -557,7 +551,7 @@ DynInst::checkQueryCompleted() { if(isQueryCompleted()) { if(fault == NoFault) { auto* rv_inst = dynamic_cast(staticInst.get()); - rv_inst->completeAcc(lastPacket, this, traceData); // FIXME: pass the packet somehow + rv_inst->completeAcc(lastPacket, this, traceData); setExecuted(); cpu->getIEWObject().checkMisprediction(dynamic_cast(this)); } diff --git a/src/arch/riscvcapstone/o3/dyn_inst.hh b/src/arch/riscvcapstone/o3/dyn_inst.hh index 0b2f00f4ba..394929724f 100644 --- a/src/arch/riscvcapstone/o3/dyn_inst.hh +++ b/src/arch/riscvcapstone/o3/dyn_inst.hh @@ -119,6 +119,7 @@ class DynInst : public ExecContext, public RefCounted ~DynInst(); + /** Helper to print all arch regs*/ void printRegs() { RiscvcapstoneISA::o3::CPU *o3cpu = dynamic_cast(cpu); assert(o3cpu != nullptr); @@ -160,7 +161,10 @@ class DynInst : public ExecContext, public RefCounted bool res_tag; }; - // note that here we only include the queries but not the updates + /** note that here we only include the queries but not the updates + * as only the queries are executed before the instruction is committed, + * and we need to know the query result before inst commit. + */ NodeCommandPtr nodeQueries[MAX_QUERY_N]; bool nodeQueryCompleted[MAX_QUERY_N]; int nodeQueryN = 0, completedNodeQueryN = 0; @@ -169,39 +173,42 @@ class DynInst : public ExecContext, public RefCounted bool tagQueryCompleted[MAX_QUERY_N]; int tagQueryN = 0, completedTagQueryN = 0; + /** keep track of memory accesses + * as an inst may issue multiple mem accesses + */ struct MemReadRecord { Addr addr; uint8_t data[MAX_REQUEST_SIZE]; }; MemReadRecord memReads[MAX_QUERY_N]; - PacketPtr xyz[MAX_QUERY_N]; + PacketPtr readRes[MAX_QUERY_N]; bool memReadCompleted[MAX_QUERY_N]; int memReadN = 0, completedMemReadN = 0; int memWriteN = 0; + // Holds the result of the last mem read. Is passed to completeAcc PacketPtr lastPacket = nullptr; - - - // NodeCommandPtr nodeCommands[MAX_QUERY_N]; - // bool nodeCommandCompleted[MAX_QUERY_N]; - // int nodeCommandN = 0, completedNodeCommandN = 0; + /** Get idx(th) tag query result. */ bool getTagQueryRes(int idx) const { assert(idx < tagQueryN); assert(tagQueryCompleted[idx]); return tagQueries[idx].res_tag; } + /** Whether all memory reads issued by an inst. are complete. */ bool isMemReadComplete() const { return memReadN == completedMemReadN; } + /** Total number of memory reads issued */ int getMemReadN() const { return memReadN; } + /** Get idx(th) mem read result. */ const uint8_t* getMemReadRes(int idx) const { assert(idx < memReadN); assert(memReadCompleted[idx]); @@ -218,7 +225,7 @@ class DynInst : public ExecContext, public RefCounted ResultReady, /// Instruction has its result CanIssue, /// Instruction can issue and execute Issued, /// Instruction has issued - Executed, /// Instruction has executed + Executed, /// Instruction has completed execution CanCommit, /// Instruction can commit AtCommit, /// Instruction has reached commit Committed, /// Instruction has committed @@ -237,7 +244,7 @@ class DynInst : public ExecContext, public RefCounted SerializeAfter, /// Needs to serialize instructions behind it SerializeHandled, /// Serialization has been handled NodeExecuted, - ExecuteCalled, + ExecuteCalled, /// Instruction execution has started NumStatus }; @@ -462,6 +469,7 @@ class DynInst : public ExecContext, public RefCounted ssize_t ncqIdx = -1; typename NCQUnit::NCQIterator ncqIt; + /** Tag queue index. */ ssize_t tqIdx = -1; typename BaseTagController::TQIterator tqIt; @@ -522,6 +530,7 @@ class DynInst : public ExecContext, public RefCounted Fault initiateMemAMO(Addr addr, unsigned size, Request::Flags flags, AtomicOpFunctorPtr amo_op) override; + /** Initiate one of the node commands. */ Fault initiateNodeCommand(NodeCommandPtr cmd); Fault initiateGetTag(Addr addr); @@ -878,7 +887,9 @@ class DynInst : public ExecContext, public RefCounted /** Returns whether or not this instruction is completed. */ bool isCompleted() const { return status[Completed]; } - + /** Check whether all tag queries and mem reads are completed. + * Node Commands are handled separately. + */ bool isQueryCompleted() const { return completedTagQueryN == tagQueryN && completedMemReadN == memReadN && @@ -1302,15 +1313,6 @@ class DynInst : public ExecContext, public RefCounted // storage (which is pretty hard to imagine they would have reason // to do). - void - updateMemReadRecord(Addr paddr) { - memReads[memReadN] = MemReadRecord { - .addr = paddr - }; - memReadCompleted[memReadN] = false; - ++ memReadN; - } - RegVal getRegOperand(const StaticInst *si, int idx) override { @@ -1355,7 +1357,6 @@ class DynInst : public ExecContext, public RefCounted if (reg->is(InvalidRegClass)) return; cpu->setReg(reg, val); - //TODO setResult } void @@ -1365,7 +1366,6 @@ class DynInst : public ExecContext, public RefCounted if (reg->is(InvalidRegClass)) return; cpu->setTaggedReg(reg, tagged_val); - //setResult(val); } @@ -1411,15 +1411,10 @@ class DynInst : public ExecContext, public RefCounted void completeMemRead(int idx, PacketPtr pkt); + /** Tracks whether the associated memreads and tag queries + * are completed, and if so, calls completeAcc on the inst + */ void checkQueryCompleted(); - - bool addrInSecRegion(Addr addr, uint64_t size) { - return (addr >= cpu->secure_base - size && addr < cpu->secure_end); - } - - bool isSecureWorld() { - return cpu->cwrld[threadNumber]; - } }; } // namespace RiscvcapstoneISA::o3 diff --git a/src/arch/riscvcapstone/o3/iew.cc b/src/arch/riscvcapstone/o3/iew.cc index 726dd9e986..bd723799b5 100644 --- a/src/arch/riscvcapstone/o3/iew.cc +++ b/src/arch/riscvcapstone/o3/iew.cc @@ -1271,7 +1271,7 @@ IEW::executeInsts() ThreadID thread_id = inst->threadNumber; CapPerm pc_perm = pcCaps[thread_id].perm(); - if(0 && cpu->cwrld[thread_id]) { + if(0) { if(!capInBound(pcCaps[thread_id], inst->pcState().instAddr()) || (pc_perm != CapPerm::RX && pc_perm != CapPerm::RWX)) { DPRINTF(IEW, "Cap %llx %llx %llx (perm = %d)\n", pcCaps[thread_id].start(), pcCaps[thread_id].end(), @@ -1283,7 +1283,6 @@ IEW::executeInsts() } } - // TODO: examine operand registers and update the reference counts // Execute instruction. diff --git a/src/arch/riscvcapstone/o3/lsq.cc b/src/arch/riscvcapstone/o3/lsq.cc index bffd8b9efb..683f064ed3 100644 --- a/src/arch/riscvcapstone/o3/lsq.cc +++ b/src/arch/riscvcapstone/o3/lsq.cc @@ -853,9 +853,6 @@ LSQ::pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data, if(isLoad) { if (!inst->loadEffAddrValid()) { inst->setLoadEffAddrs(request->getVaddr(), size); - //memReadRecord set needs to happen here - //*after* the addr translation - // inst->updateMemReadRecord(request->getPaddr()); } // otherwise, assume that the instruction has set the addresses in advance } else { diff --git a/src/arch/riscvcapstone/o3/ncq.hh b/src/arch/riscvcapstone/o3/ncq.hh index 6e70af8e5c..5df9a4104d 100644 --- a/src/arch/riscvcapstone/o3/ncq.hh +++ b/src/arch/riscvcapstone/o3/ncq.hh @@ -19,9 +19,11 @@ namespace o3 { class CPU; class IEW; - // TODO: also needs to be one per thread +// TODO: also needs to be one per thread class NCQ { public: + + // Node cache port for the NCQ class NcachePort : public RequestPort { private: NCQ* ncq; @@ -65,14 +67,22 @@ class NCQ { public: NCQ(CPU* cpu, IEW* iew, int queue_size, int thread_num); + + /** Insert instruction in the NCQ. The order of insts in the queue + * follows the program order. + */ void insertInstruction(const DynInstPtr& inst); void tick(); bool isFull(ThreadID thread_id); + /** Add a command to the NCQ's corresponding entry for inst. */ Fault pushCommand(const DynInstPtr& inst, NodeCommandPtr cmd); + /** Mark all commands before the given seq_num as being able to be committed. */ void commitBefore(InstSeqNum seq_num, ThreadID thread_id); + + /** This is where the node commands are actually executed. */ void writebackCommands(); void writebackCommands(ThreadID thread_id); @@ -94,6 +104,8 @@ class NCQ { bool handleCacheResp(PacketPtr pkt); QueryResult passedQuery(const DynInstPtr& inst) const; + + /** Remove NCQEntries with completed commands from the NCQ. */ void cleanupCommands(); void squash(const InstSeqNum& squashed_num, ThreadID thread_id); diff --git a/src/arch/riscvcapstone/o3/ncq_unit.cc b/src/arch/riscvcapstone/o3/ncq_unit.cc index c40914bc78..bfd4e26678 100644 --- a/src/arch/riscvcapstone/o3/ncq_unit.cc +++ b/src/arch/riscvcapstone/o3/ncq_unit.cc @@ -113,7 +113,7 @@ NCQUnit::cleanupCommands(){ void NCQUnit::writebackCommands(){ - // not doing lots of reordering right now + // not doing reordering right now for(NCQIterator it = ncQueue.begin(); it != ncQueue.end() && ncq->canSend(); ++ it) { //if(!it->inst->isNodeInitiated() || it->completed()) @@ -121,7 +121,6 @@ NCQUnit::writebackCommands(){ // not doing anything for instructions not yet executed continue; std::vector& commands = it->commands; - /** @todo maybe insert a seqNum only with commit commands */ DPRINTF(NCQ, "Instruction %u with %u commands (completed = %u)\n", it->inst->seqNum, commands.size(), it->completedCommands); for(NodeCommandIterator nc_it = commands.begin(); @@ -152,8 +151,11 @@ NCQUnit::writebackCommands(){ DPRINTF(NCQ, "Checking command dependencies\n"); - // check for dependencies - // the naive way. Bruteforce + /** check for dependencies the naive way. Bruteforce. + * Right now there's no reordering so dep_ready is + * always going to be false, unless our command is the first + * in the list + */ bool dep_ready = true; for(NCQIterator it_o = ncQueue.begin(); dep_ready && it_o != ncQueue.end(); @@ -212,8 +214,6 @@ NCQUnit::completeCommand(NodeCommandPtr node_command){ ++ inst->ncqIt->completedCommands; if(inst->ncqIt->completed() && inst->hasNodeWB()) { - //might need to add a check that if a command is from commit - //don't send the inst to commit as it's alr committed DPRINTF(NCQ, "Instruction %u can now be committed\n", inst->seqNum); inst->setNodeExecuted(); @@ -228,6 +228,7 @@ NCQUnit::handleCacheResp(PacketPtr pkt) { PacketRecord& packet_record = it->second; NodeCommandPtr node_cmd = packet_record.cmd; //check if it was a command issued by cpu and not an inst + //for the init cap if(!packet_record.inst && node_cmd == nullptr) { packetIssuers.erase(it); delete pkt; diff --git a/src/arch/riscvcapstone/o3/ncq_unit.hh b/src/arch/riscvcapstone/o3/ncq_unit.hh index 0d57133b36..16a3ca7182 100644 --- a/src/arch/riscvcapstone/o3/ncq_unit.hh +++ b/src/arch/riscvcapstone/o3/ncq_unit.hh @@ -54,7 +54,7 @@ struct NCQEntry { commands.clear(); } - // all commands have been finished + /** Whether all commands have been finished. */ bool completed() const { return completedCommands == commands.size(); } @@ -62,8 +62,7 @@ struct NCQEntry { /** * Node command queue unit for a single thread - * - * */ + */ class NCQUnit { private: struct PacketRecord { @@ -91,17 +90,20 @@ class NCQUnit { //NCQUnit(const NCQUnit&) = delete; Fault pushCommand(const DynInstPtr& inst, NodeCommandPtr cmd); void insertInstruction(const DynInstPtr& inst); - // commit all instructions before specified seq number void commitBefore(InstSeqNum seq_num); void writebackCommands(); + + /** Bookkeeping. Tracks completed commands in the NCQ. */ void completeCommand(NodeCommandPtr cmd_it); void tick(); bool isFull(); + /** Debug helper to print out the NCQ. */ void dumpNcQueue(); bool handleCacheResp(PacketPtr pkt); QueryResult passedQuery(const DynInstPtr& inst) const; + void cleanupCommands(); void squash(const InstSeqNum &squashed_num); @@ -110,7 +112,7 @@ class NCQUnit { return NoFault; } - // allocate the node for cinit, assumed 0 + // allocate the node for the init capability, assumed 0 void allocateInit(); }; diff --git a/src/arch/riscvcapstone/o3/node_commands.cc b/src/arch/riscvcapstone/o3/node_commands.cc index 36024a5134..2d493aeafa 100644 --- a/src/arch/riscvcapstone/o3/node_commands.cc +++ b/src/arch/riscvcapstone/o3/node_commands.cc @@ -14,6 +14,7 @@ namespace gem5 { namespace RiscvcapstoneISA { namespace o3 { +// Physical memory location where the first node (node ID 0) is to be stored. const Addr NODE_MEM_BASE_ADDR = 0x7d0000000ULL; inline Addr node_addr(NodeID node_id) { @@ -60,6 +61,10 @@ NodeCommand::createLoadNode(const NodeID& node_id) { return create_load_node(inst->requestorId(), node_id); } +/** + * Following are the internal state machines for each of the + * node commands. + */ PacketPtr NodeAllocate::transition() { DPRINTF(NodeCmd, "Node allocate transition for instruction %u (state = %u)\n", @@ -119,6 +124,9 @@ NodeAllocate::handleResp(PacketPtr pkt) { switch(state) { case NCAllocate_LOAD_PARENT: savedNode = pkt->getRaw(); + + assert(savedNode.isValid()); + parentDepth = savedNode.depth; nextNodeId = savedNode.next; savedNode.next = toAllocate; @@ -136,7 +144,7 @@ NodeAllocate::handleResp(PacketPtr pkt) { savedNode.depth = parentDepth + (asChild ? 1 : 0); savedNode.next = nextNodeId; savedNode.state = Node::VALID; - savedNode.counter = 1; // TODO: perhaps 1 + savedNode.counter = 1; state = NCAllocate_STORE; status = TO_RESUME; @@ -273,6 +281,8 @@ NodeRevoke::handleResp(PacketPtr pkt) { switch(state) { case NCRevoke_LOAD_ROOT: rootNode = pkt->getRaw(); + assert(rootNode.isValid()); + rootDepth = rootNode.depth; curNodeId = rootNode.next; @@ -333,21 +343,56 @@ NodeRcUpdate::handleResp(PacketPtr pkt) { case NCRcUpdate_LOAD: savedNode = pkt->getRaw(); savedNode.counter += delta; - //do I need to make the counter check against 1 here? - if(savedNode.counter == 0 && savedNode.state == 0) { - // add node to free list - // savedNode.state = Node::INVALID; - inst->getNodeController().freeNode(savedNode, nodeId); - } + prevNodeId = savedNode.prev; + nextNodeId = savedNode.next; - // note that we do not need to do anything - // with prev and next because they are invalid notes state = NCRcUpdate_STORE; status = TO_RESUME; + + if(savedNode.counter == 0) { + // add node to free list + if (savedNode.state == Node::INVALID) { + if(prevNodeId == NODE_ID_INVALID && + nextNodeId == NODE_ID_INVALID) { + inst->getNodeController().setRoot(NODE_ID_INVALID); + status = COMPLETED; + } if (prevNodeId == NODE_ID_INVALID) + state = NCRcUpdate_LOAD_NEXT; + else + state = NCRcUpdate_LOAD_PREV; + inst->getNodeController().freeNode(savedNode, nodeId); + } + } + break; case NCRcUpdate_STORE: status = COMPLETED; break; + case NCRcUpdate_LOAD_PREV: + savedNode = pkt->getRaw(); + savedNode.next = nextNodeId; + + state = NCRcUpdate_STORE_PREV; + status = TO_RESUME; + break; + case NCRcUpdate_STORE_PREV: + if (nextNodeId == NODE_ID_INVALID) + status = COMPLETED; + else { + state = NCRcUpdate_LOAD_NEXT; + status = TO_RESUME; + } + break; + case NCRcUpdate_LOAD_NEXT: + savedNode = pkt->getRaw(); + savedNode.prev = prevNodeId; + + state = NCRcUpdate_STORE_NEXT; + status = TO_RESUME; + break; + case NCRcUpdate_STORE_NEXT: + status = COMPLETED; + break; default: panic("unrecognised state in RcUpdate!"); } @@ -356,7 +401,7 @@ NodeRcUpdate::handleResp(PacketPtr pkt) { // when rc reaches 0 -// if the node if invalid: add the node to the free list +// if the node if invalid: add the node to the free list, and remove it from the rev tree // if the node is valid: no need to do anything PacketPtr NodeRcUpdate::transition() { @@ -368,6 +413,18 @@ NodeRcUpdate::transition() { case NCRcUpdate_STORE: pkt = createStoreNode(nodeId, savedNode); break; + case NCRcUpdate_LOAD_PREV: + pkt = createLoadNode(prevNodeId); + break; + case NCRcUpdate_STORE_PREV: + pkt = createStoreNode(prevNodeId, savedNode); + break; + case NCRcUpdate_LOAD_NEXT: + pkt = createLoadNode(nextNodeId); + break; + case NCRcUpdate_STORE_NEXT: + pkt = createStoreNode(nextNodeId, savedNode); + break; default: panic("unrecognised state in RcUpdate!"); } @@ -530,7 +587,7 @@ NodeDrop::handleResp(PacketPtr pkt) { switch(state) { case NCDrop_LOAD: savedNode = pkt->getRaw(); - assert(savedNode.isValid()); // TODO: actually need to handle this case + assert(savedNode.isValid()); prevNodeId = savedNode.prev; nextNodeId = savedNode.next; savedNode.invalidate(); @@ -545,7 +602,7 @@ NodeDrop::handleResp(PacketPtr pkt) { inst->getNodeController().setRoot(NODE_ID_INVALID); status = COMPLETED; } else if(prevNodeId == NODE_ID_INVALID) { - inst->getNodeController().setRoot(nodeId); //shouldn't this be nextNodeId? + inst->getNodeController().setRoot(nextNodeId); state = NCDrop_LOAD_RIGHT; status = TO_RESUME; } else { diff --git a/src/arch/riscvcapstone/o3/node_commands.hh b/src/arch/riscvcapstone/o3/node_commands.hh index 3892da378c..779ebbaa0f 100644 --- a/src/arch/riscvcapstone/o3/node_commands.hh +++ b/src/arch/riscvcapstone/o3/node_commands.hh @@ -18,7 +18,8 @@ class NCQ; struct NCQEntry; /** - * base class for all commands to node controller + * Base class for all commands to node controller. The commands + * help us manage/query the revocation tree. * */ struct NodeCommand { typedef enum { @@ -105,6 +106,12 @@ struct LockedNodeCommand : NodeCommand { PacketPtr createReleasePacket(); }; +/** + * The NodeQuery command helps to check the validity of a node. + * The result of the query is checked in the commit stage. This + * means that the command has to execute before the instruction + * is committed. +*/ struct NodeQuery : NodeCommand { NodeID nodeId; bool validityError = false; @@ -126,6 +133,9 @@ struct NodeQuery : NodeCommand { ~NodeQuery() {} }; +/** + * Debug command to dump info for a node. +*/ struct NodeQueryDbg : NodeCommand { NodeID nodeId; bool validityError = false; @@ -147,7 +157,11 @@ struct NodeQueryDbg : NodeCommand { ~NodeQueryDbg() {} }; - +/** + * The NodeRevoke command is called with a revocation capability. + * It invalidates all the nodes (in effect, the associated capabilities) + * in the subtree of the given node ID. +*/ struct NodeRevoke : NodeCommand { NodeID nodeId; NodeRevoke() : state(NCRevoke_LOAD_ROOT) {} @@ -179,6 +193,12 @@ struct NodeRevoke : NodeCommand { Node savedNode, rootNode; }; +/** + * The NodeRcUpdate command helps to keep the reference + * count values updated for a given node ID. If the RC values + * reaches 0 for a node ID, it removes that node from the revocation tree, + * and adds it to the free list (to be able to be allocated later). +*/ struct NodeRcUpdate : NodeCommand { NodeID nodeId; int delta; @@ -201,11 +221,18 @@ struct NodeRcUpdate : NodeCommand { enum { NCRcUpdate_LOAD, NCRcUpdate_STORE, + NCRcUpdate_LOAD_PREV, + NCRcUpdate_STORE_PREV, + NCRcUpdate_LOAD_NEXT, + NCRcUpdate_STORE_NEXT } state; - + NodeID prevNodeId, nextNodeId; Node savedNode; }; +/** + * Used to allocate a new node ID and add it to the revocation tree. +*/ struct NodeAllocate : NodeCommand { NodeID data; @@ -247,6 +274,11 @@ struct NodeAllocate : NodeCommand { Node savedNode; }; +/** + * The NodeDrop command notifies the implementation that we're + * not interested in the provided capability anymore. The controller + * removes this node from the revocation tree. + */ struct NodeDrop : NodeCommand { NodeID nodeId; diff --git a/src/arch/riscvcapstone/o3/thread_context.hh b/src/arch/riscvcapstone/o3/thread_context.hh index 5ae9bafa58..00531c75e3 100644 --- a/src/arch/riscvcapstone/o3/thread_context.hh +++ b/src/arch/riscvcapstone/o3/thread_context.hh @@ -203,12 +203,6 @@ class ThreadContext : public gem5::ThreadContext return cpu->readMiscReg(misc_reg, thread->threadId()); } - bool - cwrld() - { - return cpu->cwrld[thread->threadId()]; - } - /** Sets a misc. register. */ void setMiscRegNoEffect(RegIndex misc_reg, RegVal val) override; diff --git a/src/arch/riscvcapstone/pagetable_walker.cc b/src/arch/riscvcapstone/pagetable_walker.cc index 07e7178514..81bf869f2c 100644 --- a/src/arch/riscvcapstone/pagetable_walker.cc +++ b/src/arch/riscvcapstone/pagetable_walker.cc @@ -301,12 +301,7 @@ Walker::WalkerState::stepWalk(PacketPtr &write) // step 2: // Performing PMA/PMP checks on physical address of PTE - - walker->pma->check(read->req); - // Effective privilege mode for pmp checks for page table - // walks is S mode according to specs - fault = walker->pmp->pmpCheck(read->req, BaseMMU::Read, - RiscvcapstoneISA::PrivilegeMode::PRV_S, tc, entry.vaddr); + // skipped if (fault == NoFault) { // step 3: @@ -353,11 +348,7 @@ Walker::WalkerState::stepWalk(PacketPtr &write) // this read will eventually become write // if doWrite is True - - walker->pma->check(read->req); - - fault = walker->pmp->pmpCheck(read->req, - BaseMMU::Write, pmode, tc, entry.vaddr); + // skipped } // perform step 8 only if pmp checks pass @@ -524,12 +515,11 @@ Walker::WalkerState::recvPacket(PacketPtr pkt) vaddr = Addr(sext(vaddr)); Addr paddr = walker->tlb->translateWithTLB(vaddr, satp.asid, mode); req->setPaddr(paddr); - walker->pma->check(req); // do pmp check if any checking condition is met. // timingFault will be NoFault if pmp checks are // passed, otherwise an address fault will be returned. - timingFault = walker->pmp->pmpCheck(req, mode, pmode, tc); + // skipped // Let the CPU continue. translation->finish(timingFault, req, tc, mode); diff --git a/src/arch/riscvcapstone/pagetable_walker.hh b/src/arch/riscvcapstone/pagetable_walker.hh index 7d4afe4dae..4c6878e412 100644 --- a/src/arch/riscvcapstone/pagetable_walker.hh +++ b/src/arch/riscvcapstone/pagetable_walker.hh @@ -173,8 +173,6 @@ namespace RiscvcapstoneISA // The TLB we're supposed to load. TLB * tlb; System * sys; - PMAChecker * pma; - PMP * pmp; RequestorID requestorId; // The number of outstanding walks that can be squashed per cycle. @@ -205,8 +203,6 @@ namespace RiscvcapstoneISA Walker(const Params ¶ms) : ClockedObject(params), port(name() + ".port", this), funcState(this, NULL, NULL, true), tlb(NULL), sys(params.system), - pma(params.pma_checker), - pmp(params.pmp), requestorId(sys->getRequestorId(this)), numSquashable(params.num_squash_per_cycle), startWalkWrapperEvent([this]{ startWalkWrapper(); }, name()) diff --git a/src/arch/riscvcapstone/pmp.cc b/src/arch/riscvcapstone/pmp.cc index 7cbabb2cff..30abb92b72 100644 --- a/src/arch/riscvcapstone/pmp.cc +++ b/src/arch/riscvcapstone/pmp.cc @@ -247,9 +247,7 @@ PMP::shouldCheckPMP(RiscvcapstoneISA::PrivilegeMode pmode, bool cond3 = (mode != BaseMMU::Execute && (status.mprv) && (status.mpp != RiscvcapstoneISA::PrivilegeMode::PRV_M)); - bool secure_world = tc->cwrld(); - - return ((cond1 || cond2 || cond3) && /*!secure_world*/ 0); + return (cond1 || cond2 || cond3); } AddrRange diff --git a/src/arch/riscvcapstone/process.cc b/src/arch/riscvcapstone/process.cc index ee6302eb85..9ef584007c 100644 --- a/src/arch/riscvcapstone/process.cc +++ b/src/arch/riscvcapstone/process.cc @@ -84,24 +84,6 @@ RiscvProcess64::RiscvProcess64(const ProcessParams ¶ms, const Addr mmap_end = 0x400000000ULL; memState = std::make_shared(this, brk_point, stack_base, max_stack_size, next_thread_stack_base, mmap_end); - - // const Addr stack_base = 0x7FFFFFFFFFFFFFFFL; - // const Addr max_stack_size = 8 * 1024 * 1024; - // const Addr next_thread_stack_base = stack_base - max_stack_size; - // const Addr brk_point = roundUp(image.maxAddr(), PageBytes); - // const Addr mmap_end = 0x4000000000000000L; - // memState = std::make_shared(this, brk_point, stack_base, - // max_stack_size, next_thread_stack_base, mmap_end); - - // objFile->printSections(); - - std::pair cap_relocs, cap_table; - cap_relocs = objFile->getSec("__cap_relocs"); - cap_table = objFile->getSec(".captable"); - - cap_relocs_base = cap_relocs.first; - cap_relocs_count = cap_relocs.second / 40; //sizeof(cap_reloc_struct) - cap_table_size = cap_table.second; } RiscvProcess32::RiscvProcess32(const ProcessParams ¶ms, @@ -123,12 +105,8 @@ RiscvProcess64::initState() Process::initState(); argsInit(PageBytes); - for (ContextID ctx: contextIds) { + for (ContextID ctx: contextIds) system->threads[ctx]->setMiscRegNoEffect(MISCREG_PRV, PRV_U); - system->threads[ctx]->setRegFlat(RegId(IntRegClass, 12), cap_relocs_base); - system->threads[ctx]->setRegFlat(RegId(IntRegClass, 13), cap_relocs_count); - system->threads[ctx]->setRegFlat(RegId(IntRegClass, 14), cap_table_size); - } } void diff --git a/src/arch/riscvcapstone/regs/misc.hh b/src/arch/riscvcapstone/regs/misc.hh index 455bfb8544..c92f26492c 100644 --- a/src/arch/riscvcapstone/regs/misc.hh +++ b/src/arch/riscvcapstone/regs/misc.hh @@ -209,9 +209,9 @@ enum CapMiscRegIndex { //Capability CSRs CAPMISCREG_CEH = 0, + CAPMISCREG_CIH, CAPMISCREG_CINIT, CAPMISCREG_EPC, - CAPMISCREG_SWITCH_CAP, NUM_CAPMISCREGS }; @@ -391,9 +391,9 @@ enum CSRIndex //Capability CSRs enum CCSRIndex { CCSR_CEH = 0x000, //exception handler capability + CCSR_CIH = 0x001, //interrupt handler capability CCSR_CINIT = 0x002, //initial capability covering entire address space CCSR_EPC = 0x003, //Exception PC - CCSR_SWITCH_CAP = 0x004 //capability to store contexts on async world switch }; struct CSRMetadata { @@ -409,9 +409,9 @@ struct CCSRMetadata const std::map CCSRData = { {CCSR_CEH, {"ceh", CAPMISCREG_CEH}}, + {CCSR_CIH, {"cih", CAPMISCREG_CIH}}, {CCSR_CINIT, {"cinit", CAPMISCREG_CINIT}}, {CCSR_EPC, {"epc", CAPMISCREG_EPC}}, - {CCSR_SWITCH_CAP, {"switch_cap", CAPMISCREG_SWITCH_CAP}} }; const std::map CSRData = { diff --git a/src/arch/riscvcapstone/remote_gdb.cc b/src/arch/riscvcapstone/remote_gdb.cc index 850f10d416..66fd41f56a 100644 --- a/src/arch/riscvcapstone/remote_gdb.cc +++ b/src/arch/riscvcapstone/remote_gdb.cc @@ -166,22 +166,6 @@ RemoteGDB::acc(Addr va, size_t len) if (FullSystem) { panic("full system unsupported."); - /*MMU *mmu = static_cast(context()->getMMUPtr()); - unsigned logBytes; - Addr paddr = va; - - PrivilegeMode pmode = mmu->getMemPriv(context(), BaseMMU::Read); - SATP satp = context()->readMiscReg(MISCREG_SATP); - if (pmode != PrivilegeMode::PRV_M && - satp.mode != AddrXlateMode::BARE) { - Walker *walker = mmu->getDataWalker(); - Fault fault = walker->startFunctional( - context(), paddr, logBytes, BaseMMU::Read); - if (fault != NoFault) - return false; - } - return true; - */ } return context()->getProcessPtr()->pTable->lookup(va) != nullptr; diff --git a/src/arch/riscvcapstone/tlb.cc b/src/arch/riscvcapstone/tlb.cc index 7f1c510938..27868424b9 100644 --- a/src/arch/riscvcapstone/tlb.cc +++ b/src/arch/riscvcapstone/tlb.cc @@ -72,8 +72,7 @@ buildKey(Addr vpn, uint16_t asid) TLB::TLB(const Params &p) : BaseTLB(p), size(p.size), tlb(size), - lruSeq(0), stats(this), pma(p.pma_checker), - pmp(p.pmp) + lruSeq(0), stats(this) { for (size_t x = 0; x < size; x++) { tlb[x].trieHandle = NULL; @@ -369,16 +368,6 @@ TLB::translate(const RequestPtr &req, ThreadContext *tc, code = ExceptionCode::INST_ACCESS; fault = std::make_shared(req->getVaddr(), code); } - - if (!delayed && fault == NoFault) { - pma->check(req); - - // do pmp check if any checking condition is met. - // timingFault will be NoFault if pmp checks are - // passed, otherwise an address fault will be returned. - fault = pmp->pmpCheck(req, mode, pmode, tc); - } - return fault; } else { // In the O3 CPU model, sometimes a memory access will be speculatively @@ -432,22 +421,6 @@ TLB::translateFunctional(const RequestPtr &req, ThreadContext *tc, if (FullSystem) { panic("full system unsupported."); - /*MMU *mmu = static_cast(tc->getMMUPtr()); - - PrivilegeMode pmode = mmu->getMemPriv(tc, mode); - SATP satp = tc->readMiscReg(MISCREG_SATP); - if (pmode != PrivilegeMode::PRV_M && - satp.mode != AddrXlateMode::BARE) { - Walker *walker = mmu->getDataWalker(); - unsigned logBytes; - Fault fault = walker->startFunctional( - tc, paddr, logBytes, mode); - if (fault != NoFault) - return fault; - - Addr masked_addr = vaddr & mask(logBytes); - paddr |= masked_addr; - }*/ } else { Process *process = tc->getProcessPtr(); diff --git a/src/arch/riscvcapstone/tlb.hh b/src/arch/riscvcapstone/tlb.hh index 8df4760d69..f11160bb90 100644 --- a/src/arch/riscvcapstone/tlb.hh +++ b/src/arch/riscvcapstone/tlb.hh @@ -85,10 +85,6 @@ class TLB : public BaseTLB statistics::Formula accesses; } stats; - public: - PMAChecker *pma; - PMP *pmp; - public: typedef RiscvTLBParams Params; TLB(const Params &p); diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index d7e6154795..13828f58b2 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -290,13 +290,6 @@ class CheckerThreadContext : public ThreadContext return actualTC->readMiscReg(misc_reg); } - #ifdef TARGET_RISCVCapstone - bool cwrld() override - { - return 0; - } - #endif - void setMiscRegNoEffect(RegIndex misc_reg, RegVal val) override { diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 1ca0e3213c..ae37dc994d 100644 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -203,14 +203,6 @@ class ThreadContext : public gem5::ThreadContext return cpu->readMiscReg(misc_reg, thread->threadId()); } - #ifdef TARGET_RISCVCapstone - bool - cwrld() - { - return 0; - } - #endif - /** Sets a misc. register. */ void setMiscRegNoEffect(RegIndex misc_reg, RegVal val) override; diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index c0f99fb539..1de5b370ae 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -279,13 +279,6 @@ class SimpleThread : public ThreadState, public ThreadContext return isa->readMiscReg(misc_reg); } - #ifdef TARGET_RISCVCapstone - bool cwrld() override - { - return 0; - } - #endif - void setMiscRegNoEffect(RegIndex misc_reg, RegVal val) override { diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 41f9583f67..70601af432 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -283,10 +283,6 @@ class ThreadContext : public PCEventScope virtual RegVal readMiscReg(RegIndex misc_reg) = 0; - #ifdef TARGET_RISCVCapstone - virtual bool cwrld() = 0; - #endif - virtual void setMiscRegNoEffect(RegIndex misc_reg, RegVal val) = 0; virtual void setMiscReg(RegIndex misc_reg, RegVal val) = 0;