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 &section){    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 &section){    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 + -
显示快捷键?