aboutsummaryrefslogtreecommitdiffstats
path: root/target-ppc/helper.c
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-11-19 11:41:10 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-11-19 11:41:10 +0000
commitadd78955b0451c6d14d325d66592a634b2e5d595 (patch)
tree7cf2b133679c9c26db7315e6895f7cd33863be62 /target-ppc/helper.c
parent5b8105fa50b0dfde4ac49d7b1dd8044fb82caec6 (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.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index b4c38395f..cb9b778cc 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,