⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlb.cc

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 CC
字号:
#include <string.h>#include "koala.hh"// Reset the Translation Lookaside Buffer.voidKoala::dump_tlb(){    for (size_t i = 0; i < tlb_size; ++i) {	    log("TLB [%d]: 0x%016x : 0x%016x-0x%016x",		i, tlb[i].hi, tlb[i].lo[0], tlb[i].lo[1]);    }}	voidKoala::reset_tlb(){    // Clear the TLB map.    memset(tlb_map, 0, sizeof(tlb_map));    // Add all TLB entries to the last (otherwise unused) TLB chain.    for (size_t i = 0; i < tlb_size; ++i) {	tlb[i].asid = invalid_asid;	tlb[i].index = i;	tlb[i].hash  = tlb_map_size;	if (tlb_map[tlb_map_size])	    tlb_map[tlb_map_size]->prev = &tlb[i];	tlb[i].next = tlb_map[tlb_map_size];	tlb[i].prev = 0;	tlb_map[tlb_map_size] = &tlb[i];    }}// Set a TLB entry from PageMask, EntryHi, EntryLo0 and EntryLo1.voidKoala::set_tlb_entry(int n){    int hash = tlb_hash(cp0[EntryHi]);    if ((unsigned int)n >= tlb_size)	return;    // msg("TLB Insert: EntryHi = %016lx, EntryLo0 = %016lx, EntryLo1 = %016lx, PageMask = %016lx",    //		cp0[EntryHi], cp0[EntryLo0], cp0[EntryLo1], cp0[PageMask]);    // Remove entry from the current TLB hash chain.    if (tlb[n].next)	tlb[n].next->prev = tlb[n].prev;    if (tlb[n].prev)	tlb[n].prev->next = tlb[n].next;    else	tlb_map[tlb[n].hash] = tlb[n].next;    // Compute the page mask.    UInt64 pagemask = set_bits(cp0[PageMask], 12, 0);    // Set the new entry.    tlb[n].hi     = cp0[EntryHi];    tlb[n].lo[0]  = cp0[EntryLo0];    tlb[n].lo[1]  = cp0[EntryLo1];    tlb[n].mask   = ~pagemask;    tlb[n].oddbit = pagemask ^ (pagemask >> 1);    if (bit(cp0[EntryLo0], EntryLo_G) & bit(cp0[EntryLo1], EntryLo_G))	tlb[n].asid = global_asid;    else	tlb[n].asid = bits(cp0[EntryHi], 7, 0) /* asid */;    tlb[n].index  = n;    tlb[n].hash   = hash;    // Add the entry to the new TLB hash chain.    if (tlb_map[hash])	tlb_map[hash]->prev = &tlb[n];    tlb[n].next = tlb_map[hash];    tlb[n].prev = 0;    tlb_map[hash] = &tlb[n];}// The TLB lookup routine. MIPS TLBs are fully-associative, so we use a hash// table to look them up. Dynamic allocation of the TLB nodes isn't needed as// the number of entries is fixed. This is used only by translate_vaddr() and// the TLBP instruction. It returns a pointer to the TLB entry or 0 on a TLB// miss.Koala::TLBEntry *Koala::probe_tlb(VA va){    int hash = tlb_hash(va);    for (TLBEntry* e = tlb_map[hash]; e; e = e->next) {	if (asid_match(asid, e->asid) && va_match(va, e->hi, e->mask)) {	    return e;	}    }    return 0;}// Perform a full TLB lookup.//// WARNING: Both R4600/R4700 have a four-entry DTLB that use a pseudo-LRU// replacement (the least-recently used entry of the least-recenty used half// is selected for replacement). A DTLB miss results in one-cycle slip in the// A pipeline stage. This feature is currently not simulated.Koala::PAKoala::translate_vaddr(VA va, int type){    UInt32 region_type; // one of SR_UX, SR_SX or SR_KX    // Decode the virtual address.    if (vaddr_region(va) == vaddr_region(xkuseg)) {	// The user region is valid in every mode, but we still have	// to handle the 32/64 bit mode differences.	if (bits(va, 63, (mode & xmode) ? vaddr_width : 31)) {	    process_address_error(type, va);	    return 0; // shut up the compiler	}	else {	    // kuseg becomes an unmapped, uncached region if ERL is set.	    if (bit(cp0[SR], SR_ERL) && !bits(va, 63, 32))		return make_physical_address(va, uncached);	    // Proceed with the TLB lookup.	    region_type = SR_UX;	}    }    else if (vaddr_region(va) == vaddr_region(xksseg)) {	// The 64 bit supervisor segment is accessible only in the 64 bit	// supervisor or kernel mode.	if ((mode & (cmode|umode)) || bits(va, 61, vaddr_width)) {	    process_address_error(type, va);	    return 0; // shut up the compiler	}	else {	    // Proceed with the TLB lookup.	    region_type = SR_SX;	}    }    else if (vaddr_region(va) == vaddr_region(xkphys)) {	// The 64 bit unmapped segment; accessible only in 64 bit kernel mode.	// Bits paddr_width to 58 must be zero.	int ca = coherency_algorithm(va);	if ((mode & (cmode|umode|smode)) || bits(va, 58, paddr_width) ||	    ca < noncoherent_write_through || ca > update_on_write)	{	    process_address_error(type, va);	    return 0; // shut up the compiler	}	else {	    // The physical address is already encoded.	    return va;	}    }    else {	// This segment includes the 64 bit kernel segment and the	// compatibility segments. Only CKSSEG may be accessed in the	// supervisor mode; all others must be accessed in the kernel mode.	if (va >= ckseg0) {	    int region = vaddr_compat_region(va);	    if ((mode & (umode|smode)) &&		((mode & umode) || region != vaddr_compat_region(cksseg)))	    {		process_address_error(type, va);		return 0; // shut up the compiler	    }	    else if (region < vaddr_compat_region(cksseg)) {		// Access unmapped segments ckseg0 and ckseg1.		int ca = (region == vaddr_compat_region(ckseg1)) ? uncached :		    bits(cp0[Config], Config_K0_Last, Config_K0_First);		return make_physical_address(bits(va, 28, 0), ca);	    }	    else {		// One of ckseg3 or cksseg.		region_type =		    (region < vaddr_compat_region(ckseg3)) ? SR_SX : SR_KX;	    }	}	else if ((mode & xmode) == 0 || va >= xkseg_end) {	    // xkseg is accessible only in the 64 bit kernel mode.	    process_address_error(type, va);	    return 0; // shut up the compiler	}	else {	    // Proceed with the TLB lookup.	    region_type = SR_KX;	}    }    // Now, we are ready to probe the TLB.    TLBEntry *entry = probe_tlb(va);    if (!entry)	process_tlb_refill(type, va, bit(cp0[SR], region_type)); // TLB miss        // Filter TLB entries marked invalid.    UInt32 lo = (va & entry->oddbit) ? entry->lo[1] : entry->lo[0];    if (!bit(lo, EntryLo_V))	process_tlb_invalid(type, va); // TLB invalid.    // Fiter TLB entries marked read-only.    if (type == data_store && !bit(lo, EntryLo_D))	process_tlb_modified(va); // TLB Modified exception.    // Finally, retrieve the mapping.    UInt64 mask = entry->oddbit - 1;    PA pa = (va & mask) | ((PA(lo) << 6) & ~mask);    int ca = bits(lo, EntryLo_C_Last, EntryLo_C_First);    return make_physical_address(pa, ca);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -