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

📄 tlb.c

📁 skyeye的开源代码
💻 C
字号:
#include <assert.h>#include "armdefs.h"ARMword tlb_masks[] = {	0x00000000,		/* TLB_INVALID */	0xFFFFF000,		/* TLB_SMALLPAGE */	0xFFFF0000,		/* TLB_LARGEPAGE */	0xFFF00000,		/* TLB_SECTION */	0xFFFFF000,		/*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */	0xFFFFFC00		/* TLB_TINYPAGE */};/* This function encodes table 8-2 Interpreting AP bits,   returning non-zero if access is allowed. */static intcheck_perms (ARMul_State * state, int ap, int read){	int s, r, user;	s = state->mmu.control & CONTROL_SYSTEM;	r = state->mmu.control & CONTROL_ROM;	//chy 2006-02-15 , should consider system mode, don't conside 26bit mode	user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);	switch (ap) {	case 0:		return read && ((s && !user) || r);	case 1:		return !user;	case 2:		return read || !user;	case 3:		return 1;	}	return 0;}fault_tcheck_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,	      int read){	int access;	state->mmu.last_domain = tlb->domain;	access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;	if ((access == 0) || (access == 2)) {		/* It's unclear from the documentation whether this		   should always raise a section domain fault, or if		   it should be a page domain fault in the case of an		   L1 that describes a page table.  In the ARM710T		   datasheets, "Figure 8-9: Sequence for checking faults"		   seems to indicate the former, while "Table 8-4: Priority		   encoding of fault status" gives a value for FS[3210] in		   the event of a domain fault for a page.  Hmm. */		return SECTION_DOMAIN_FAULT;	}	if (access == 1) {		/* client access - check perms */		int subpage, ap;		switch (tlb->mapping) {			/*ks 2004-05-09   			 *   only for XScale			 *   Extend Small Page(ESP) Format			 *   31-12 bits    the base addr of ESP			 *   11-10 bits    SBZ			 *   9-6   bits    TEX			 *   5-4   bits    AP			 *   3     bit     C			 *   2     bit     B			 *   1-0   bits    11			 * */		case TLB_ESMALLPAGE:	//xj			subpage = 0;			//printf("TLB_ESMALLPAGE virt_addr=0x%x  \n",virt_addr );			break;		case TLB_TINYPAGE:			subpage = 0;			//printf("TLB_TINYPAGE virt_addr=0x%x  \n",virt_addr );			break;		case TLB_SMALLPAGE:			subpage = (virt_addr >> 10) & 3;			break;		case TLB_LARGEPAGE:			subpage = (virt_addr >> 14) & 3;			break;		case TLB_SECTION:			subpage = 3;			break;		default:			assert (0);			subpage = 0;	/* cleans a warning */		}		ap = (tlb->perms >> (subpage * 2 + 4)) & 3;		if (!check_perms (state, ap, read)) {			if (tlb->mapping == TLB_SECTION) {				return SECTION_PERMISSION_FAULT;			}			else {				return SUBPAGE_PERMISSION_FAULT;			}		}	}	else {			/* access == 3 */		/* manager access - don't check perms */	}	return NO_FAULT;}fault_ttranslate (ARMul_State * state, ARMword virt_addr, tlb_t * tlb_t,	   tlb_entry_t ** tlb){	*tlb = mmu_tlb_search (state, tlb_t, virt_addr);	if (!*tlb) {		/* walk the translation tables */		ARMword l1addr, l1desc;		tlb_entry_t entry;		l1addr = state->mmu.translation_table_base & 0xFFFFC000;		l1addr = (l1addr | (virt_addr >> 18)) & ~3;		l1desc = mem_read_word (state, l1addr);		switch (l1desc & 3) {		case 0:			//SBZ			{				return PAGE_TRANSLATION_FAULT;			}		case 3:			/* fine page table */			// dcl 2006-01-08			{				ARMword l2addr, l2desc;				l2addr = l1desc & 0xFFFFF000;				l2addr = (l2addr |					  ((virt_addr & 0x000FFC00) >> 8)) &					~3;				l2desc = mem_read_word (state, l2addr);				entry.virt_addr = virt_addr;				entry.phys_addr = l2desc;				entry.perms = l2desc & 0x00000FFC;				entry.domain = (l1desc >> 5) & 0x0000000F;				switch (l2desc & 3) {				case 0:					state->mmu.last_domain = entry.domain;					return PAGE_TRANSLATION_FAULT;				case 3:					entry.mapping = TLB_TINYPAGE;					break;				case 1:					// this is untested					entry.mapping = TLB_LARGEPAGE;					break;				case 2:					// this is untested					entry.mapping = TLB_SMALLPAGE;					break;				}			}			break;		case 1:			/* coarse page table */			{				ARMword l2addr, l2desc;				l2addr = l1desc & 0xFFFFFC00;				l2addr = (l2addr |					  ((virt_addr & 0x000FF000) >> 10)) &					~3;				l2desc = mem_read_word (state, l2addr);				entry.virt_addr = virt_addr;				entry.phys_addr = l2desc;				entry.perms = l2desc & 0x00000FFC;				entry.domain = (l1desc >> 5) & 0x0000000F;				//printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr);				//chy 2003-09-02 for xscale				switch (l2desc & 3) {				case 0:					state->mmu.last_domain = entry.domain;					return PAGE_TRANSLATION_FAULT;				case 3:					if (!state->is_XScale) {						state->mmu.last_domain =							entry.domain;						return PAGE_TRANSLATION_FAULT;					};					//ks 2004-05-09 xscale shold use Extend Small Page					//entry.mapping = TLB_SMALLPAGE;					entry.mapping = TLB_ESMALLPAGE;	//xj					break;				case 1:					entry.mapping = TLB_LARGEPAGE;					break;				case 2:					entry.mapping = TLB_SMALLPAGE;					break;				}			}			break;		case 2:			/* section */			//printf("SKYEYE:WARNING: not implement section mapping incompletely\n");			//printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc);			//return SECTION_DOMAIN_FAULT;			//#if 0			entry.virt_addr = virt_addr;			entry.phys_addr = l1desc;			entry.perms = l1desc & 0x00000C0C;			entry.domain = (l1desc >> 5) & 0x0000000F;			entry.mapping = TLB_SECTION;			break;			//#endif		}		entry.virt_addr &= tlb_masks[entry.mapping];		entry.phys_addr &= tlb_masks[entry.mapping];		/* place entry in the tlb */		*tlb = &tlb_t->entrys[tlb_t->cycle];		tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num;		**tlb = entry;	}	state->mmu.last_domain = (*tlb)->domain;	return NO_FAULT;}intmmu_tlb_init (tlb_t * tlb_t, int num){	tlb_entry_t *e;	int i;	e = (tlb_entry_t *) malloc (sizeof (*e) * num);	if (e == NULL) {		err_msg ("malloc size %d\n", sizeof (*e) * num);		goto tlb_malloc_error;	}	tlb_t->entrys = e;	for (i = 0; i < num; i++, e++)		e->mapping = TLB_INVALID;	tlb_t->cycle = 0;	tlb_t->num = num;	return 0;      tlb_malloc_error:	return -1;}voidmmu_tlb_exit (tlb_t * tlb_t){	free (tlb_t->entrys);};voidmmu_tlb_invalidate_all (ARMul_State * state, tlb_t * tlb_t){	int entry;	for (entry = 0; entry < tlb_t->num; entry++) {		tlb_t->entrys[entry].mapping = TLB_INVALID;	}	tlb_t->cycle = 0;}voidmmu_tlb_invalidate_entry (ARMul_State * state, tlb_t * tlb_t, ARMword addr){	tlb_entry_t *tlb;	tlb = mmu_tlb_search (state, tlb_t, addr);	if (tlb) {		tlb->mapping = TLB_INVALID;	}}tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_t * tlb_t, ARMword virt_addr){	int entry;	for (entry = 0; entry < tlb_t->num; entry++) {		tlb_entry_t *tlb;		ARMword mask;		tlb = &(tlb_t->entrys[entry]);		if (tlb->mapping == TLB_INVALID) {			continue;		}		mask = tlb_masks[tlb->mapping];		if ((virt_addr & mask) == (tlb->virt_addr & mask)) {			return tlb;		}	}	return NULL;}

⌨️ 快捷键说明

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