📄 sa_mmu.c
字号:
/*search instruction cache */ cache = mmu_cache_search (state, I_CACHE (), va); if (cache) { update_cache (state, va, data, datatype, cache, I_CACHE (), real_va); } if (MMU_Disabled) { //mem_write_word(state, va, data); if (datatype == ARM_BYTE_TYPE) mem_write_byte (state, va, data); else if (datatype == ARM_HALFWORD_TYPE) mem_write_halfword (state, va, data); else if (datatype == ARM_WORD_TYPE) mem_write_word (state, va, data); else { printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype); skyeye_exit (-1); } return 0; } /*align check */ //if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { d_msg ("align\n"); return ALIGNMENT_FAULT; } //else va &= ~(WORD_SIZE - 1); /*tlb translate */ fault = translate (state, va, D_TLB (), &tlb); if (fault) { d_msg ("translate\n"); return fault; } /*tlb check access */ fault = check_access (state, va, tlb, 0); if (fault) { d_msg ("check_access\n"); return fault; } /*search main cache */ cache = mmu_cache_search (state, MAIN_D_CACHE (), va); if (cache) { update_cache (state, va, data, datatype, cache, MAIN_D_CACHE (), real_va); } else { /*search mini cache */ cache = mmu_cache_search (state, MINI_D_CACHE (), va); if (cache) { update_cache (state, va, data, datatype, cache, MINI_D_CACHE (), real_va); } } if (!cache) { b = tlb_b_flag (tlb); pa = tlb_va_to_pa (tlb, va); if (b) { if (MMU_WBEnabled) { if (datatype == ARM_WORD_TYPE) mmu_wb_write_bytes (state, WB (), pa, &data, 4); else if (datatype == ARM_HALFWORD_TYPE) mmu_wb_write_bytes (state, WB (), (pa | (real_va & 2)), &data, 2); else if (datatype == ARM_BYTE_TYPE) mmu_wb_write_bytes (state, WB (), (pa | (real_va & 3)), &data, 1); } else { if (datatype == ARM_WORD_TYPE) mem_write_word (state, pa, data); else if (datatype == ARM_HALFWORD_TYPE) mem_write_halfword (state, (pa | (real_va & 2)), data); else if (datatype == ARM_BYTE_TYPE) mem_write_byte (state, (pa | (real_va & 3)), data); } } else { mmu_wb_drain_all (state, WB ()); if (datatype == ARM_WORD_TYPE) mem_write_word (state, pa, data); else if (datatype == ARM_HALFWORD_TYPE) mem_write_halfword (state, (pa | (real_va & 2)), data); else if (datatype == ARM_BYTE_TYPE) mem_write_byte (state, (pa | (real_va & 3)), data); } } return 0;}static fault_tupdate_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype, cache_line_t * cache, cache_t * cache_t, ARMword real_va){ ARMword temp, offset; ARMword index = va_cache_index (va, cache_t); //cache->data[index] = data; if (datatype == ARM_WORD_TYPE) cache->data[index] = data; else if (datatype == ARM_HALFWORD_TYPE) { temp = cache->data[index]; offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ cache->data[index] = (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset); } else if (datatype == ARM_BYTE_TYPE) { temp = cache->data[index]; offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ cache->data[index] = (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset); } if (index < (cache_t->width >> (WORD_SHT + 1))) cache->tag |= TAG_FIRST_HALF_DIRTY; else cache->tag |= TAG_LAST_HALF_DIRTY; return 0;}ARMwordsa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value){ mmu_regnum_t creg = BITS (16, 19) & 15; ARMword data; switch (creg) { case MMU_ID:// printf("mmu_mrc read ID "); data = 0x41007100; /* v3 */ data = state->cpu->cpu_val; break; case MMU_CONTROL:// printf("mmu_mrc read CONTROL"); data = state->mmu.control; break; case MMU_TRANSLATION_TABLE_BASE:// printf("mmu_mrc read TTB "); data = state->mmu.translation_table_base; break; case MMU_DOMAIN_ACCESS_CONTROL:// printf("mmu_mrc read DACR "); data = state->mmu.domain_access_control; break; case MMU_FAULT_STATUS:// printf("mmu_mrc read FSR "); data = state->mmu.fault_status; break; case MMU_FAULT_ADDRESS:// printf("mmu_mrc read FAR "); data = state->mmu.fault_address; break; case MMU_PID: data = state->mmu.process_id; default: printf ("mmu_mrc read UNKNOWN - reg %d\n", creg); data = 0; break; }// printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); *value = data; return data;}voidsa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value){ int CRm, OPC_2; CRm = BITS (0, 3); OPC_2 = BITS (5, 7); if (OPC_2 == 0 && CRm == 7) { mmu_cache_invalidate_all (state, I_CACHE ()); mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); mmu_cache_invalidate_all (state, MINI_D_CACHE ()); return; } if (OPC_2 == 0 && CRm == 5) { mmu_cache_invalidate_all (state, I_CACHE ()); return; } if (OPC_2 == 0 && CRm == 6) { mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); mmu_cache_invalidate_all (state, MINI_D_CACHE ()); return; } if (OPC_2 == 1 && CRm == 6) { mmu_cache_invalidate (state, MAIN_D_CACHE (), value); mmu_cache_invalidate (state, MINI_D_CACHE (), value); return; } if (OPC_2 == 1 && CRm == 0xa) { mmu_cache_clean (state, MAIN_D_CACHE (), value); mmu_cache_clean (state, MINI_D_CACHE (), value); return; } if (OPC_2 == 4 && CRm == 0xa) { mmu_wb_drain_all (state, WB ()); return; } err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);}static voidsa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value){ int CRm, OPC_2; CRm = BITS (0, 3); OPC_2 = BITS (5, 7); if (OPC_2 == 0 && CRm == 0x7) { mmu_tlb_invalidate_all (state, I_TLB ()); mmu_tlb_invalidate_all (state, D_TLB ()); return; } if (OPC_2 == 0 && CRm == 0x5) { mmu_tlb_invalidate_all (state, I_TLB ()); return; } if (OPC_2 == 0 && CRm == 0x6) { mmu_tlb_invalidate_all (state, D_TLB ()); return; } if (OPC_2 == 1 && CRm == 0x6) { mmu_tlb_invalidate_entry (state, D_TLB (), value); return; } err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);}static voidsa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value){ int CRm, OPC_2; CRm = BITS (0, 3); OPC_2 = BITS (5, 7); if (OPC_2 == 0x0 && CRm == 0x0) { mmu_rb_invalidate_all (RB ()); return; } if (OPC_2 == 0x2) { int idx = CRm & 0x3; int type = ((CRm >> 2) & 0x3) + 1; if ((idx < 4) && (type < 4)) mmu_rb_load (state, RB (), idx, type, value); return; } if ((OPC_2 == 1) && (CRm < 4)) { mmu_rb_invalidate_entry (RB (), CRm); return; } err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);}static voidsa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value){ mmu_regnum_t creg = BITS (16, 19) & 15; if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) { switch (creg) { case MMU_CONTROL:// printf("mmu_mcr wrote CONTROL "); state->mmu.control = (value | 0x70) & 0xFFFD; break; case MMU_TRANSLATION_TABLE_BASE:// printf("mmu_mcr wrote TTB "); state->mmu.translation_table_base = value & 0xFFFFC000; break; case MMU_DOMAIN_ACCESS_CONTROL:// printf("mmu_mcr wrote DACR "); state->mmu.domain_access_control = value; break; case MMU_FAULT_STATUS: state->mmu.fault_status = value & 0xFF; break; case MMU_FAULT_ADDRESS: state->mmu.fault_address = value; break; case MMU_CACHE_OPS: sa_mmu_cache_ops (state, instr, value); break; case MMU_TLB_OPS: sa_mmu_tlb_ops (state, instr, value); break; case MMU_SA_RB_OPS: sa_mmu_rb_ops (state, instr, value); break; case MMU_SA_DEBUG: break; case MMU_SA_CP15_R15: break; case MMU_PID: //2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu state->mmu.process_id = value & 0x7e000000; break; default: printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); break; } }}//teawater add for arm2x86 2005.06.24-------------------------------------------static intsa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr){ fault_t fault; tlb_entry_t *tlb; virt_addr = mmu_pid_va_map (virt_addr); if (MMU_Enabled) { /*align check */ if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { d_msg ("align\n"); return ALIGNMENT_FAULT; } else virt_addr &= ~(WORD_SIZE - 1); /*translate tlb */ fault = translate (state, virt_addr, I_TLB (), &tlb); if (fault) { d_msg ("translate\n"); return fault; } /*check access */ fault = check_access (state, virt_addr, tlb, 1); if (fault) { d_msg ("check_fault\n"); return fault; } } if (MMU_Disabled) { *phys_addr = virt_addr; } else { *phys_addr = tlb_va_to_pa (tlb, virt_addr); } return (0);}//AJ2D--------------------------------------------------------------------------/*sa mmu_ops_t*/mmu_ops_t sa_mmu_ops = { sa_mmu_init, sa_mmu_exit, sa_mmu_read_byte, sa_mmu_write_byte, sa_mmu_read_halfword, sa_mmu_write_halfword, sa_mmu_read_word, sa_mmu_write_word, sa_mmu_load_instr, sa_mmu_mcr, sa_mmu_mrc,//teawater add for arm2x86 2005.06.24------------------------------------------- sa_mmu_v2p_dbct,//AJ2D--------------------------------------------------------------------------};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -