1. MMU和Memory系统结构
图 0-1 ARM系统中MMU和Memory的系统结构
ARM系统中MMU和Memory的系统结构如图 0 1所示。不过具体的CPU在实现MMU时差别较大,可能对其做简化和扩展, SkyEye的MMU模拟实现基于此,在提供一个标准的接口基础上,分成与具体CPU类型无关的MMU模拟子模块和与具体CPU类型相关的MMU模拟子模块两个主要部分。
2. ARM 数据访问的基本流程图
ARM CPU进行数据访问的基本流程如图 0 2所示。
图 0-2 ARM CPU进行数据访问的基本流程
3. MMU的统一接口
数据结构
typedef struct mmu_state_t {
ARMwordcontrol;//CP15 control register
ARMwordtranslation_table_base;//CP15 translation table base register
ARMworddomain_access_control;//CP15 domain access control
register
ARMwordfault_status;//CP15 fault status register
ARMwordfault_address;//CP15 fault address register
ARMwordlast_domain;
//last access domain
ARMwordprocess_id;
//CP15 process id register
mmu_ops_tops;
union{
sa_mmu_tsa_mmu;
arm7100_mmu_t
arm7100_mmu;
}u;
} mmu_state_t;
typedef struct mmu_ops_s{
int (*init)(ARMul_State *state);/*initilization*/
void (*exit)(ARMul_State *state);/*free on exit*/
fault_t (*read_byte)(ARMul_State *state, ARMword va, ARMword *data);
fault_t (*write_byte)(ARMul_State *state, ARMword va, ARMword data);
fault_t (*read_halfword)(ARMul_State *state, ARMword va, ARMword *data);
fault_t (*write_halfword)(ARMul_State *state, ARMword va,ARMword data);
fault_t (*read_word)(ARMul_State *state, ARMword va,ARMword *data);
fault_t (*write_word)(ARMul_State *state, ARMword va,ARMword data);
fault_t (*load_instr)(ARMul_State *state, ARMword va, ARMword *instr);
void (*mcr)(ARMul_State *state, ARMword instr, ARMword val);
ARMword (*mrc)(ARMul_State *state, ARMword instr);
}mmu_ops_t;
数据结构ARMul_State中类型为mmu_state_t的mmu代表模拟中MMU的状态。mmu_state_t中的ops提供具体mmu的接口函数,同时包括一个联合结构u用于具体mmu实现的数据结构。
4. 与具体CPU类型无关的MMU模拟子模块
与具体CPU类型无关的MMU模拟子模块是实现MMU模拟的基础,它实现了TLB,TTW, 访问控制,CACHE, Write Buffer,Read Buffer等MMU要素的模拟,并且提供了较统一的接口,可以较灵活地组合实现具体MMU模拟。
TLB的实现(mmu/tlb.[ch])
TLB是一个表,它的表项包含地址映射信息和访问控制信息,地址转换信息只有在该表中查询不到时,才通过TTW在内存中查找。
数据结构
TLB 映射类型
typedef enum tlb_mapping_t {
TLB_INVALID = 0,
TLB_SMALLPAGE = 1,
TLB_LARGEPAGE = 2,
TLB_SECTION = 3
} tlb_mapping_t;
TLB 表项
typedef struct tlb_entry_t {
ARMwordvirt_addr;
//virtual address
ARMwordphys_addr; //physical address
ARMwordperms;
//access permission
ARMworddomain;
//access domain
tlb_mapping_tmapping;//tlb mapping type
} tlb_entry_t;
TLB 表
typedef struct tlb_s{
int num;/*num of tlb entry*/
int cycle;/*current tlb cycle,used for allocate tlb_entry*/
tlb_entry_t*entrys;
}tlb_t;
接口函数
int mmu_tlb_init(tlb_t *tlb_t, int num);
初始化TLB
void mmu_tlb_exit(tlb_t *tlb_t);
释放TLB
void mmu_tlb_invalidate_all(ARMul_State *state, tlb_t *tlb_t);
无效所有的tlb_entry
void mmu_tlb_invalidate_entry(ARMul_State *state, tlb_t *tlb_t, ARMword virt_addr);
无效包含指定virt_addr的tlb_entry.
tlb_entry_t * mmu_tlb_search(ARMul_State *state, tlb_t *tlb_t, ARMword virt_addr);
根据virt_addr查找tlb_entry
TTW的实现(mmu/tlb.[ch])
ARM系统中通过2级映射,实现了页式地址转换。
接口函数
fault_t translate(ARMul_State *state, ARMword virt_addr, tlb_t *tlb_t, tlb_entry_t **tlb)
{
/*首先查找TLB表,如果没有找到,执行TTW并更新TLB表*/
*tlb = mmu_tlb_search(state, tlb_t, virt_addr);/*查找tlb*/
if (!*tlb) {
/* 没有找到,进行TTW*/
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:
case 3:
return SECTION_TRANSLATION_FAULT;
case 1:
/*页式变换*/
{
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;
switch (l2desc & 3) {
case 0:
case 3:
state-mmu.last_domain = entry.domain;
return PAGE_TRANSLATION_FAULT;
case 1:
entry.mapping = TLB_LARGEPAGE; /*大页*/
break;
case 2:
entry.mapping = TLB_SMALLPAGE; /*小页*/
break;
}
}
break;
case 2:
/*段变换*/
entry.virt_addr = virt_addr;
entry.phys_addr = l1desc;
entry.perms = l1desc & 0x00000C0C;
entry.domain = (l1desc 5) & 0x0000000F;
entry.mapping = TLB_SECTION;
break;
}
entry.virt_addr &= tlb_masks[entry.mapping];
entry.phys_addr &= tlb_masks[entry.mapping];
/* 更新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;
}
访问控制的实现(mmu/tlb.[ch])
接口函数
fault_t check_access(ARMul_State *state, ARMword virt_addr,
tlb_entry_t *tlb, int read);
CACHE的实现(mmu/cache.[ch])
ARM系统中一般只实现组相联CACHE。组相联CACHE分成多组,一个组有包括多个CACHE line,一个32位地址可以由下图表示。
Tag Set Word 1 0
数据结构
Cache行
typedef struct cache_line_t{
ARMword tag;/* cache line align address |
bit2: last half dirty
bit1: first half dirty
bit0: cache valid flag
*/
ARMword pa;/*physical address*/
ARMword *data; /*array of cached data*/
}cache_line_t;
#define TAG_VALID_FLAG 0x00000001
#define TAG_FIRST_HALF_DIRTY 0x00000002
#define TAG_LAST_HALF_DIRTY0x00000004
Cache 组
typedef struct cache_set_s{
cache_line_t*lines;
int cycle;/*used for cache line allocation*/
}cache_set_t;
Cache 结构
typedef struct cache_s{
intwidth;/*bytes in a line*/
int way;/*way of set asscociate*/
intset;/*num of set*/
int w_mode;/*write back or write through*/
//int a_mode;/*alloc mode: random or round-bin*/
cache_set_t *sets;
}cache_t;
接口函数
/*Cache的初始化和释放*/
int mmu_cache_init(cache_t *cache_t, int width, int way, int set, int w_mode);
void mmu_cache_exit(cache_t *cache_t);
/*Cache 查找和分配*/
cache_line_t * mmu_cache_search(ARMul_State *state, cache_t *cache_t, ARMword va);
cache_line_t * mmu_cache_alloc(ARMul_State *state, cache_t *cache_t, ARMword va, ARMword pa