diff options
Diffstat (limited to 'qemu/target-ppc/mmu_helper.c')
-rw-r--r-- | qemu/target-ppc/mmu_helper.c | 132 |
1 files changed, 51 insertions, 81 deletions
diff --git a/qemu/target-ppc/mmu_helper.c b/qemu/target-ppc/mmu_helper.c index 527c6adca..ff217941b 100644 --- a/qemu/target-ppc/mmu_helper.c +++ b/qemu/target-ppc/mmu_helper.c @@ -16,6 +16,8 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "cpu.h" #include "exec/helper-proto.h" #include "sysemu/kvm.h" @@ -23,28 +25,28 @@ #include "mmu-hash64.h" #include "mmu-hash32.h" #include "exec/cpu_ldst.h" +#include "exec/log.h" //#define DEBUG_MMU //#define DEBUG_BATS //#define DEBUG_SOFTWARE_TLB //#define DUMP_PAGE_TABLES -//#define DEBUG_SOFTWARE_TLB //#define FLUSH_ALL_TLBS #ifdef DEBUG_MMU -# define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0) +# define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0) #else # define LOG_MMU_STATE(cpu) do { } while (0) #endif #ifdef DEBUG_SOFTWARE_TLB -# define LOG_SWTLB(...) qemu_log(__VA_ARGS__) +# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) #else # define LOG_SWTLB(...) do { } while (0) #endif #ifdef DEBUG_BATS -# define LOG_BATS(...) qemu_log(__VA_ARGS__) +# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) #else # define LOG_BATS(...) do { } while (0) #endif @@ -162,7 +164,7 @@ static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0, if (ctx->raddr != (hwaddr)-1ULL) { /* all matches should have equal RPN, WIMG & PP */ if ((ctx->raddr & mmask) != (pte1 & mmask)) { - qemu_log("Bad RPN/WIMG/PP\n"); + qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n"); return -3; } } @@ -508,7 +510,7 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, /* Software TLB search */ ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); #if defined(DUMP_PAGE_TABLES) - if (qemu_log_enabled()) { + if (qemu_log_mask(CPU_LOG_MMU)) { hwaddr curaddr; uint32_t a0, a1, a2, a3; @@ -575,8 +577,8 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, /* eciwx or ecowx */ return -4; default: - qemu_log("ERROR: instruction should not need " - "address translation\n"); + qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need " + "address translation\n"); return -4; } if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) { @@ -658,32 +660,6 @@ static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env) tlb_flush(CPU(cpu), 1); } -static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env, - target_ulong eaddr, uint32_t pid) -{ -#if !defined(FLUSH_ALL_TLBS) - CPUState *cs = CPU(ppc_env_get_cpu(env)); - ppcemb_tlb_t *tlb; - hwaddr raddr; - target_ulong page, end; - int i; - - for (i = 0; i < env->nb_tlb; i++) { - tlb = &env->tlb.tlbe[i]; - if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) { - end = tlb->EPN + tlb->size; - for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { - tlb_flush_page(cs, page); - } - tlb->prot &= ~PAGE_VALID; - break; - } - } -#else - ppc4xx_tlb_invalidate_all(env); -#endif -} - static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong address, int rw, int access_type) @@ -1293,10 +1269,12 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) break; #if defined(TARGET_PPC64) case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: case POWERPC_MMU_2_06: case POWERPC_MMU_2_06a: - case POWERPC_MMU_2_06d: - dump_slb(f, cpu_fprintf, env); + case POWERPC_MMU_2_07: + case POWERPC_MMU_2_07a: + dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); break; #endif default: @@ -1433,15 +1411,17 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) switch (env->mmu_model) { #if defined(TARGET_PPC64) case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: case POWERPC_MMU_2_06: case POWERPC_MMU_2_06a: - case POWERPC_MMU_2_06d: - return ppc_hash64_get_phys_page_debug(env, addr); + case POWERPC_MMU_2_07: + case POWERPC_MMU_2_07a: + return ppc_hash64_get_phys_page_debug(cpu, addr); #endif case POWERPC_MMU_32B: case POWERPC_MMU_601: - return ppc_hash32_get_phys_page_debug(env, addr); + return ppc_hash32_get_phys_page_debug(cpu, addr); default: ; @@ -1507,6 +1487,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw, int mmu_idx) { CPUState *cs = CPU(ppc_env_get_cpu(env)); + PowerPCCPU *cpu = POWERPC_CPU(cs); mmu_ctx_t ctx; int access_type; int ret = 0; @@ -1608,9 +1589,9 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, tlb_miss: env->error_code |= ctx.key << 19; env->spr[SPR_HASH1] = env->htab_base + - get_pteg_offset32(env, ctx.hash[0]); + get_pteg_offset32(cpu, ctx.hash[0]); env->spr[SPR_HASH2] = env->htab_base + - get_pteg_offset32(env, ctx.hash[1]); + get_pteg_offset32(cpu, ctx.hash[1]); break; case POWERPC_MMU_SOFT_74xx: if (rw == 1) { @@ -1937,9 +1918,11 @@ void ppc_tlb_invalidate_all(CPUPPCState *env) case POWERPC_MMU_601: #if defined(TARGET_PPC64) case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: case POWERPC_MMU_2_06: case POWERPC_MMU_2_06a: - case POWERPC_MMU_2_06d: + case POWERPC_MMU_2_07: + case POWERPC_MMU_2_07a: #endif /* defined(TARGET_PPC64) */ tlb_flush(CPU(cpu), 1); break; @@ -1965,25 +1948,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) ppc6xx_tlb_invalidate_virt(env, addr, 1); } break; - case POWERPC_MMU_SOFT_4xx: - case POWERPC_MMU_SOFT_4xx_Z: - ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]); - break; - case POWERPC_MMU_REAL: - cpu_abort(CPU(cpu), "No TLB for PowerPC 4xx in real mode\n"); - break; - case POWERPC_MMU_MPC8xx: - /* XXX: TODO */ - cpu_abort(CPU(cpu), "MPC8xx MMU model is not implemented\n"); - break; - case POWERPC_MMU_BOOKE: - /* XXX: TODO */ - cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n"); - break; - case POWERPC_MMU_BOOKE206: - /* XXX: TODO */ - cpu_abort(CPU(cpu), "BookE 2.06 MMU model is not implemented\n"); - break; case POWERPC_MMU_32B: case POWERPC_MMU_601: /* tlbie invalidate TLBs for all segments */ @@ -2011,9 +1975,11 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) break; #if defined(TARGET_PPC64) case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: case POWERPC_MMU_2_06: case POWERPC_MMU_2_06a: - case POWERPC_MMU_2_06d: + case POWERPC_MMU_2_07: + case POWERPC_MMU_2_07a: /* tlbie invalidate TLBs for all segments */ /* XXX: given the fact that there are too many segments to invalidate, * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU, @@ -2023,9 +1989,8 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) break; #endif /* defined(TARGET_PPC64) */ default: - /* XXX: TODO */ - cpu_abort(CPU(cpu), "Unknown MMU model\n"); - break; + /* Should never reach here with other MMU models */ + assert(0); } #else ppc_tlb_invalidate_all(env); @@ -2041,15 +2006,14 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value) env->spr[SPR_SDR1] = value; #if defined(TARGET_PPC64) if (env->mmu_model & POWERPC_MMU_64) { - target_ulong htabsize = value & SDR_64_HTABSIZE; + PowerPCCPU *cpu = ppc_env_get_cpu(env); + Error *local_err = NULL; - if (htabsize > 28) { - fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx - " stored in SDR1\n", htabsize); - htabsize = 28; + ppc_hash64_set_sdr1(cpu, value, &local_err); + if (local_err) { + error_report_err(local_err); + error_free(local_err); } - env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1; - env->htab_base = value & SDR_64_HTABORG; } else #endif /* defined(TARGET_PPC64) */ { @@ -2080,21 +2044,17 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value) (int)srnum, value, env->sr[srnum]); #if defined(TARGET_PPC64) if (env->mmu_model & POWERPC_MMU_64) { - uint64_t rb = 0, rs = 0; + uint64_t esid, vsid; /* ESID = srnum */ - rb |= ((uint32_t)srnum & 0xf) << 28; - /* Set the valid bit */ - rb |= SLB_ESID_V; - /* Index = ESID */ - rb |= (uint32_t)srnum; + esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V; /* VSID = VSID */ - rs |= (value & 0xfffffff) << 12; + vsid = (value & 0xfffffff) << 12; /* flags = flags */ - rs |= ((value >> 27) & 0xf) << 8; + vsid |= ((value >> 27) & 0xf) << 8; - ppc_store_slb(env, rb, rs); + ppc_store_slb(cpu, srnum, esid, vsid); } else #endif if (env->sr[srnum] != value) { @@ -2128,6 +2088,16 @@ void helper_tlbie(CPUPPCState *env, target_ulong addr) ppc_tlb_invalidate_one(env, addr); } +void helper_tlbiva(CPUPPCState *env, target_ulong addr) +{ + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + /* tlbiva instruction only exists on BookE */ + assert(env->mmu_model == POWERPC_MMU_BOOKE); + /* XXX: TODO */ + cpu_abort(CPU(cpu), "BookE MMU model is not implemented\n"); +} + /* Software driven TLBs management */ /* PowerPC 602/603 software TLB load instructions helpers */ static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code) |