diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-19 11:41:10 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-19 11:41:10 +0000 |
commit | add78955b0451c6d14d325d66592a634b2e5d595 (patch) | |
tree | 7cf2b133679c9c26db7315e6895f7cd33863be62 /target-ppc/helper.c | |
parent | 5b8105fa50b0dfde4ac49d7b1dd8044fb82caec6 (diff) |
PowerPC 620 MMU do not have the same exact behavior as standard
64 bits PowerPC ones.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3706 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r-- | target-ppc/helper.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c index b4c38395f5..cb9b778cc7 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -706,7 +706,7 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw, int type) { #if defined(TARGET_PPC64) - if (env->mmu_model == POWERPC_MMU_64B) + if (env->mmu_model & POWERPC_MMU_64) return find_pte64(ctx, h, rw, type); #endif @@ -916,7 +916,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, pr = msr_pr; #if defined(TARGET_PPC64) - if (env->mmu_model == POWERPC_MMU_64B) { + if (env->mmu_model & POWERPC_MMU_64) { #if defined (DEBUG_MMU) if (loglevel != 0) { fprintf(logfile, "Check SLBs\n"); @@ -973,7 +973,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, sdr = env->sdr1; pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; #if defined(TARGET_PPC64) - if (env->mmu_model == POWERPC_MMU_64B) { + if (env->mmu_model & POWERPC_MMU_64) { htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); /* XXX: this is false for 1 TB segments */ hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; @@ -1002,7 +1002,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, #endif ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); #if defined(TARGET_PPC64) - if (env->mmu_model == POWERPC_MMU_64B) { + if (env->mmu_model & POWERPC_MMU_64) { /* Only 5 bits of the page index are used in the AVPN */ ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); } else @@ -1362,6 +1362,7 @@ static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx, ctx->prot |= PAGE_WRITE; break; #if defined(TARGET_PPC64) + case POWERPC_MMU_620: case POWERPC_MMU_64B: /* Real address are 60 bits long */ ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; @@ -1430,6 +1431,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, case POWERPC_MMU_SOFT_6xx: case POWERPC_MMU_SOFT_74xx: #if defined(TARGET_PPC64) + case POWERPC_MMU_620: case POWERPC_MMU_64B: #endif /* Try to find a BAT */ @@ -1538,6 +1540,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, case POWERPC_MMU_32B: case POWERPC_MMU_601: #if defined(TARGET_PPC64) + case POWERPC_MMU_620: case POWERPC_MMU_64B: #endif env->exception_index = POWERPC_EXCP_ISI; @@ -1583,8 +1586,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #if defined(TARGET_PPC64) case -5: /* No match in segment table */ - env->exception_index = POWERPC_EXCP_ISEG; - env->error_code = 0; + if (env->mmu_model == POWERPC_MMU_620) { + env->exception_index = POWERPC_EXCP_ISI; + /* XXX: this might be incorrect */ + env->error_code = 0x40000000; + } else { + env->exception_index = POWERPC_EXCP_ISEG; + env->error_code = 0; + } break; #endif } @@ -1634,6 +1643,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, case POWERPC_MMU_32B: case POWERPC_MMU_601: #if defined(TARGET_PPC64) + case POWERPC_MMU_620: case POWERPC_MMU_64B: #endif env->exception_index = POWERPC_EXCP_DSI; @@ -1716,9 +1726,20 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #if defined(TARGET_PPC64) case -5: /* No match in segment table */ - env->exception_index = POWERPC_EXCP_DSEG; - env->error_code = 0; - env->spr[SPR_DAR] = address; + if (env->mmu_model == POWERPC_MMU_620) { + env->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = address; + /* XXX: this might be incorrect */ + if (rw == 1) + env->spr[SPR_DSISR] = 0x42000000; + else + env->spr[SPR_DSISR] = 0x40000000; + } else { + env->exception_index = POWERPC_EXCP_DSEG; + env->error_code = 0; + env->spr[SPR_DAR] = address; + } break; #endif } @@ -1955,6 +1976,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) case POWERPC_MMU_32B: case POWERPC_MMU_601: #if defined(TARGET_PPC64) + case POWERPC_MMU_620: case POWERPC_MMU_64B: #endif /* defined(TARGET_PPC64) */ tlb_flush(env, 1); @@ -2021,6 +2043,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) tlb_flush_page(env, addr | (0xF << 28)); break; #if defined(TARGET_PPC64) + case POWERPC_MMU_620: case POWERPC_MMU_64B: /* tlbie invalidate TLBs for all segments */ /* XXX: given the fact that there are too many segments to invalidate, |