📄 helper.c
字号:
/* Lookup l2 entry. */ table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc); desc = ldl_phys(table); switch (desc & 3) { case 0: /* Page translation fault. */ code = 7; goto do_fault; case 1: /* 64k page. */ phys_addr = (desc & 0xffff0000) | (address & 0xffff); ap = (desc >> (4 + ((address >> 13) & 6))) & 3; break; case 2: /* 4k page. */ phys_addr = (desc & 0xfffff000) | (address & 0xfff); ap = (desc >> (4 + ((address >> 13) & 6))) & 3; break; case 3: /* 1k page. */ if (type == 1) { /* Page translation fault. */ code = 7; goto do_fault; } phys_addr = (desc & 0xfffffc00) | (address & 0x3ff); ap = (desc >> 4) & 3; break; default: /* Never happens, but compiler isn't smart enough to tell. */ abort(); } code = 15; } *prot = check_ap(env, ap, domain, access_type, is_user); if (!*prot) { /* Access permission fault. */ goto do_fault; } *phys_ptr = phys_addr; } return 0;do_fault: return code | (domain << 4);}int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int access_type, int is_user, int is_softmmu){ uint32_t phys_addr; int prot; int ret; ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot); if (ret == 0) { /* Map a single [sub]page. */ phys_addr &= ~(uint32_t)0x3ff; address &= ~(uint32_t)0x3ff; return tlb_set_page (env, address, phys_addr, prot, is_user, is_softmmu); } if (access_type == 2) { env->cp15.c5_insn = ret; env->cp15.c6_insn = address; env->exception_index = EXCP_PREFETCH_ABORT; } else { env->cp15.c5_data = ret; env->cp15.c6_data = address; env->exception_index = EXCP_DATA_ABORT; } return 1;}target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr){ uint32_t phys_addr; int prot; int ret; ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot); if (ret != 0) return -1; return phys_addr;}void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val){ uint32_t op2; op2 = (insn >> 5) & 7; switch ((insn >> 16) & 0xf) { case 0: /* ID codes. */ goto bad_reg; case 1: /* System configuration. */ switch (op2) { case 0: env->cp15.c1_sys = val; /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(env, 1); break; case 2: env->cp15.c1_coproc = val; /* ??? Is this safe when called from within a TB? */ tb_flush(env); default: goto bad_reg; } break; case 2: /* MMU Page table control. */ env->cp15.c2 = val; break; case 3: /* MMU Domain access control. */ env->cp15.c3 = val; break; case 4: /* Reserved. */ goto bad_reg; case 5: /* MMU Fault status. */ switch (op2) { case 0: env->cp15.c5_data = val; break; case 1: env->cp15.c5_insn = val; break; default: goto bad_reg; } break; case 6: /* MMU Fault address. */ switch (op2) { case 0: env->cp15.c6_data = val; break; case 1: env->cp15.c6_insn = val; break; default: goto bad_reg; } break; case 7: /* Cache control. */ /* No cache, so nothing to do. */ break; case 8: /* MMU TLB control. */ switch (op2) { case 0: /* Invalidate all. */ tlb_flush(env, 0); break; case 1: /* Invalidate single TLB entry. */#if 0 /* ??? This is wrong for large pages and sections. */ /* As an ugly hack to make linux work we always flush a 4K pages. */ val &= 0xfffff000; tlb_flush_page(env, val); tlb_flush_page(env, val + 0x400); tlb_flush_page(env, val + 0x800); tlb_flush_page(env, val + 0xc00);#else tlb_flush(env, 1);#endif break; default: goto bad_reg; } break; case 9: /* Cache lockdown. */ switch (op2) { case 0: env->cp15.c9_data = val; break; case 1: env->cp15.c9_insn = val; break; default: goto bad_reg; } break; case 10: /* MMU TLB lockdown. */ /* ??? TLB lockdown not implemented. */ break; case 11: /* TCM DMA control. */ case 12: /* Reserved. */ goto bad_reg; case 13: /* Process ID. */ switch (op2) { case 0: env->cp15.c9_data = val; break; case 1: env->cp15.c9_insn = val; break; default: goto bad_reg; } break; case 14: /* Reserved. */ goto bad_reg; case 15: /* Implementation specific. */ /* ??? Internal registers not implemented. */ break; } return;bad_reg: /* ??? For debugging only. Should raise illegal instruction exception. */ cpu_abort(env, "Unimplemented cp15 register read\n");}uint32_t helper_get_cp15(CPUState *env, uint32_t insn){ uint32_t op2; op2 = (insn >> 5) & 7; switch ((insn >> 16) & 0xf) { case 0: /* ID codes. */ switch (op2) { default: /* Device ID. */ return env->cp15.c0_cpuid; case 1: /* Cache Type. */ return 0x1dd20d2; case 2: /* TCM status. */ return 0; } case 1: /* System configuration. */ switch (op2) { case 0: /* Control register. */ return env->cp15.c1_sys; case 1: /* Auxiliary control register. */ if (arm_feature(env, ARM_FEATURE_AUXCR)) return 1; goto bad_reg; case 2: /* Coprocessor access register. */ return env->cp15.c1_coproc; default: goto bad_reg; } case 2: /* MMU Page table control. */ return env->cp15.c2; case 3: /* MMU Domain access control. */ return env->cp15.c3; case 4: /* Reserved. */ goto bad_reg; case 5: /* MMU Fault status. */ switch (op2) { case 0: return env->cp15.c5_data; case 1: return env->cp15.c5_insn; default: goto bad_reg; } case 6: /* MMU Fault address. */ switch (op2) { case 0: return env->cp15.c6_data; case 1: /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't do any harm. */ return env->cp15.c6_insn; default: goto bad_reg; } case 7: /* Cache control. */ /* ??? This is for test, clean and invaidate operations that set the Z flag. We can't represent N = Z = 1, so it also clears clears the N flag. Oh well. */ env->NZF = 0; return 0; case 8: /* MMU TLB control. */ goto bad_reg; case 9: /* Cache lockdown. */ switch (op2) { case 0: return env->cp15.c9_data; case 1: return env->cp15.c9_insn; default: goto bad_reg; } case 10: /* MMU TLB lockdown. */ /* ??? TLB lockdown not implemented. */ return 0; case 11: /* TCM DMA control. */ case 12: /* Reserved. */ goto bad_reg; case 13: /* Process ID. */ switch (op2) { case 0: return env->cp15.c13_fcse; case 1: return env->cp15.c13_context; default: goto bad_reg; } case 14: /* Reserved. */ goto bad_reg; case 15: /* Implementation specific. */ /* ??? Internal registers not implemented. */ return 0; }bad_reg: /* ??? For debugging only. Should raise illegal instruction exception. */ cpu_abort(env, "Unimplemented cp15 register read\n"); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -