tlb.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 1,443 行 · 第 1/3 页
CC
1,443 行
} break; case ASI_DMMU: switch (va) { case 0x0: temp = tag_access; pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: pkt->set(sfsr); break; case 0x20: pkt->set(sfar); break; case 0x30: pkt->set(tag_access); break; case 0x80: pkt->set(tc->readMiscReg(MISCREG_MMU_PART_ID)); break; default: goto doMmuReadError; } break; case ASI_DMMU_TSB_PS0_PTR_REG: pkt->set(MakeTsbPtr(Ps0, tag_access, c0_tsb_ps0, c0_config, cx_tsb_ps0, cx_config)); break; case ASI_DMMU_TSB_PS1_PTR_REG: pkt->set(MakeTsbPtr(Ps1, tag_access, c0_tsb_ps1, c0_config, cx_tsb_ps1, cx_config)); break; case ASI_IMMU_TSB_PS0_PTR_REG: pkt->set(MakeTsbPtr(Ps0, itb->tag_access, itb->c0_tsb_ps0, itb->c0_config, itb->cx_tsb_ps0, itb->cx_config)); break; case ASI_IMMU_TSB_PS1_PTR_REG: pkt->set(MakeTsbPtr(Ps1, itb->tag_access, itb->c0_tsb_ps1, itb->c0_config, itb->cx_tsb_ps1, itb->cx_config)); break; case ASI_SWVR_INTR_RECEIVE: pkt->set(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); break; case ASI_SWVR_UDB_INTR_R: temp = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp); pkt->set(temp); break; default:doMmuReadError: panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", (uint32_t)asi, va); } pkt->makeAtomicResponse(); return tc->getCpuPtr()->ticks(1);}TickDTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt){ uint64_t data = gtoh(pkt->get<uint64_t>()); Addr va = pkt->getAddr(); ASI asi = (ASI)pkt->req->getAsi(); Addr ta_insert; Addr va_insert; Addr ct_insert; int part_insert; int entry_insert = -1; bool real_insert; bool ignore; int part_id; int ctx_id; PageTableEntry pte; DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", (uint32_t)asi, va, data); ITB * itb = tc->getITBPtr(); switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); tc->setMiscReg(MISCREG_MMU_LSU_CTRL, data); break; case ASI_MMU: switch (va) { case 0x8: tc->setMiscReg(MISCREG_MMU_P_CONTEXT, data); break; case 0x10: tc->setMiscReg(MISCREG_MMU_S_CONTEXT, data); break; default: goto doMmuWriteError; } break; case ASI_QUEUE: assert(mbits(data,13,6) == data); tc->setMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD + (va >> 4) - 0x3c, data); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); c0_tsb_ps0 = data; break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); c0_tsb_ps1 = data; break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); c0_config = data; break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); itb->c0_tsb_ps0 = data; break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); itb->c0_tsb_ps1 = data; break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); itb->c0_config = data; break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); cx_tsb_ps0 = data; break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); cx_tsb_ps1 = data; break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); cx_config = data; break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); itb->cx_tsb_ps0 = data; break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); itb->cx_tsb_ps1 = data; break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); itb->cx_config = data; break; case ASI_SPARC_ERROR_EN_REG: case ASI_SPARC_ERROR_STATUS_REG: warn("Ignoring write to SPARC ERROR regsiter\n"); break; case ASI_HYP_SCRATCHPAD: case ASI_SCRATCHPAD: tc->setMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); break; case ASI_IMMU: switch (va) { case 0x18: itb->sfsr = data; break; case 0x30: sext<59>(bits(data, 59,0)); itb->tag_access = data; break; default: goto doMmuWriteError; } break; case ASI_ITLB_DATA_ACCESS_REG: entry_insert = bits(va, 8,3); case ASI_ITLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); ta_insert = itb->tag_access; va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); break; case ASI_DTLB_DATA_ACCESS_REG: entry_insert = bits(va, 8,3); case ASI_DTLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); ta_insert = tag_access; va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert); break; case ASI_IMMU_DEMAP: ignore = false; ctx_id = -1; part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); switch (bits(va,5,4)) { case 0: ctx_id = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); break; case 1: ignore = true; break; case 3: ctx_id = 0; break; default: ignore = true; } switch(bits(va,7,6)) { case 0: // demap page if (!ignore) tc->getITBPtr()->demapPage(mbits(va,63,13), part_id, bits(va,9,9), ctx_id); break; case 1: //demap context if (!ignore) tc->getITBPtr()->demapContext(part_id, ctx_id); break; case 2: tc->getITBPtr()->demapAll(part_id); break; default: panic("Invalid type for IMMU demap\n"); } break; case ASI_DMMU: switch (va) { case 0x18: sfsr = data; break; case 0x30: sext<59>(bits(data, 59,0)); tag_access = data; break; case 0x80: tc->setMiscReg(MISCREG_MMU_PART_ID, data); break; default: goto doMmuWriteError; } break; case ASI_DMMU_DEMAP: ignore = false; ctx_id = -1; part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); switch (bits(va,5,4)) { case 0: ctx_id = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); break; case 1: ctx_id = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); break; case 3: ctx_id = 0; break; default: ignore = true; } switch(bits(va,7,6)) { case 0: // demap page if (!ignore) demapPage(mbits(va,63,13), part_id, bits(va,9,9), ctx_id); break; case 1: //demap context if (!ignore) demapContext(part_id, ctx_id); break; case 2: demapAll(part_id); break; default: panic("Invalid type for IMMU demap\n"); } break; case ASI_SWVR_INTR_RECEIVE: int msb; // clear all the interrupts that aren't set in the write while(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data) { msb = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data); tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb); } break; case ASI_SWVR_UDB_INTR_W: tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()-> post_interrupt(bits(data,5,0),0); break; default:doMmuWriteError: panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); } pkt->makeAtomicResponse(); return tc->getCpuPtr()->ticks(1);}#endifvoidDTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs){ uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0); ITB * itb = tc->getITBPtr(); ptrs[0] = MakeTsbPtr(Ps0, tag_access, c0_tsb_ps0, c0_config, cx_tsb_ps0, cx_config); ptrs[1] = MakeTsbPtr(Ps1, tag_access, c0_tsb_ps1, c0_config, cx_tsb_ps1, cx_config); ptrs[2] = MakeTsbPtr(Ps0, tag_access, itb->c0_tsb_ps0, itb->c0_config, itb->cx_tsb_ps0, itb->cx_config); ptrs[3] = MakeTsbPtr(Ps1, tag_access, itb->c0_tsb_ps1, itb->c0_config, itb->cx_tsb_ps1, itb->cx_config);}uint64_tDTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config){ uint64_t tsb; uint64_t config; if (bits(tag_access, 12,0) == 0) { tsb = c0_tsb; config = c0_config; } else { tsb = cX_tsb; config = cX_config; } uint64_t ptr = mbits(tsb,63,13); bool split = bits(tsb,12,12); int tsb_size = bits(tsb,3,0); int page_size = (ps == Ps0) ? bits(config, 2,0) : bits(config,10,8); if (ps == Ps1 && split) ptr |= ULL(1) << (13 + tsb_size); ptr |= (tag_access >> (9 + page_size * 3)) & mask(12+tsb_size, 4); return ptr;}voidTLB::serialize(std::ostream &os){ SERIALIZE_SCALAR(size); SERIALIZE_SCALAR(usedEntries); SERIALIZE_SCALAR(lastReplaced); // convert the pointer based free list into an index based one int *free_list = (int*)malloc(sizeof(int) * size); int cntr = 0; std::list<TlbEntry*>::iterator i; i = freeList.begin(); while (i != freeList.end()) { free_list[cntr++] = ((size_t)*i - (size_t)tlb)/ sizeof(TlbEntry); i++; } SERIALIZE_SCALAR(cntr); SERIALIZE_ARRAY(free_list, cntr); SERIALIZE_SCALAR(c0_tsb_ps0); SERIALIZE_SCALAR(c0_tsb_ps1); SERIALIZE_SCALAR(c0_config); SERIALIZE_SCALAR(cx_tsb_ps0); SERIALIZE_SCALAR(cx_tsb_ps1); SERIALIZE_SCALAR(cx_config); SERIALIZE_SCALAR(sfsr); SERIALIZE_SCALAR(tag_access); for (int x = 0; x < size; x++) { nameOut(os, csprintf("%s.PTE%d", name(), x)); tlb[x].serialize(os); }}voidTLB::unserialize(Checkpoint *cp, const std::string §ion){ int oldSize; paramIn(cp, section, "size", oldSize); if (oldSize != size) panic("Don't support unserializing different sized TLBs\n"); UNSERIALIZE_SCALAR(usedEntries); UNSERIALIZE_SCALAR(lastReplaced); int cntr; UNSERIALIZE_SCALAR(cntr); int *free_list = (int*)malloc(sizeof(int) * cntr); freeList.clear(); UNSERIALIZE_ARRAY(free_list, cntr); for (int x = 0; x < cntr; x++) freeList.push_back(&tlb[free_list[x]]); UNSERIALIZE_SCALAR(c0_tsb_ps0); UNSERIALIZE_SCALAR(c0_tsb_ps1); UNSERIALIZE_SCALAR(c0_config); UNSERIALIZE_SCALAR(cx_tsb_ps0); UNSERIALIZE_SCALAR(cx_tsb_ps1); UNSERIALIZE_SCALAR(cx_config); UNSERIALIZE_SCALAR(sfsr); UNSERIALIZE_SCALAR(tag_access); lookupTable.clear(); for (int x = 0; x < size; x++) { tlb[x].unserialize(cp, csprintf("%s.PTE%d", section, x)); if (tlb[x].valid) lookupTable.insert(tlb[x].range, &tlb[x]); }}voidDTB::serialize(std::ostream &os){ TLB::serialize(os); SERIALIZE_SCALAR(sfar);}voidDTB::unserialize(Checkpoint *cp, const std::string §ion){ TLB::unserialize(cp, section); UNSERIALIZE_SCALAR(sfar);}/* end namespace SparcISA */ }SparcISA::ITB *SparcITBParams::create(){ return new SparcISA::ITB(this);}SparcISA::DTB *SparcDTBParams::create(){ return new SparcISA::DTB(this);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?