diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-03 20:19:40 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-03 20:19:40 +0000 |
commit | 8f793433afd8f892db15fc153bb0aa94145582d6 (patch) | |
tree | ccc2a48dabb1f52f52b53d8d83dd35f542f7bbca /target-ppc/helper.c | |
parent | 0387d928754f08574a18ff72104d669d91dcc2f8 (diff) |
Enable PowerPC 64 MMU model and exceptions.
Cleanups in MMU exceptions generation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3319 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r-- | target-ppc/helper.c | 139 |
1 files changed, 71 insertions, 68 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c index daee4c7a18..1039111a0b 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -45,10 +45,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, if (rw == 2) { exception = POWERPC_EXCP_ISI; - error_code = 0; + error_code = 0x40000000; } else { exception = POWERPC_EXCP_DSI; - error_code = 0; + error_code = 0x40000000; if (rw) error_code |= 0x02000000; env->spr[SPR_DAR] = address; @@ -1227,7 +1227,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu) { mmu_ctx_t ctx; - int exception = 0, error_code = 0; int access_type; int ret = 0; @@ -1253,40 +1252,34 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, cpu_dump_state(env, logfile, fprintf, 0); #endif if (access_type == ACCESS_CODE) { - exception = POWERPC_EXCP_ISI; switch (ret) { case -1: /* No matches in page tables or TLB */ switch (env->mmu_model) { case POWERPC_MMU_SOFT_6xx: - exception = POWERPC_EXCP_IFTLB; + env->exception_index = POWERPC_EXCP_IFTLB; + env->error_code = 1 << 18; env->spr[SPR_IMISS] = address; env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; - error_code = 1 << 18; goto tlb_miss; case POWERPC_MMU_SOFT_74xx: - exception = POWERPC_EXCP_IFTLB; + env->exception_index = POWERPC_EXCP_IFTLB; goto tlb_miss_74xx; case POWERPC_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx_Z: - exception = POWERPC_EXCP_ITLB; - error_code = 0; + env->exception_index = POWERPC_EXCP_ITLB; + env->error_code = 0; env->spr[SPR_40x_DEAR] = address; env->spr[SPR_40x_ESR] = 0x00000000; break; case POWERPC_MMU_32B: - error_code = 0x40000000; - break; #if defined(TARGET_PPC64) case POWERPC_MMU_64B: - /* XXX: TODO */ - cpu_abort(env, "MMU model not implemented\n"); - return -1; case POWERPC_MMU_64BRIDGE: - /* XXX: TODO */ - cpu_abort(env, "MMU model not implemented\n"); - return -1; #endif + env->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x40000000; + break; case POWERPC_MMU_601: /* XXX: TODO */ cpu_abort(env, "MMU model not implemented\n"); @@ -1310,64 +1303,65 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, break; case -2: /* Access rights violation */ - error_code = 0x08000000; + env->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x08000000; break; case -3: /* No execute protection violation */ - error_code = 0x10000000; + env->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x10000000; break; case -4: /* Direct store exception */ /* No code fetch is allowed in direct-store areas */ - error_code = 0x10000000; + env->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x10000000; break; #if defined(TARGET_PPC64) case -5: /* No match in segment table */ - exception = POWERPC_EXCP_ISEG; - error_code = 0; + env->exception_index = POWERPC_EXCP_ISEG; + env->error_code = 0; break; #endif } } else { - exception = POWERPC_EXCP_DSI; switch (ret) { case -1: /* No matches in page tables or TLB */ switch (env->mmu_model) { case POWERPC_MMU_SOFT_6xx: if (rw == 1) { - exception = POWERPC_EXCP_DSTLB; - error_code = 1 << 16; + env->exception_index = POWERPC_EXCP_DSTLB; + env->error_code = 1 << 16; } else { - exception = POWERPC_EXCP_DLTLB; - error_code = 0; + env->exception_index = POWERPC_EXCP_DLTLB; + env->error_code = 0; } env->spr[SPR_DMISS] = address; env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; tlb_miss: - error_code |= ctx.key << 19; + env->error_code |= ctx.key << 19; env->spr[SPR_HASH1] = ctx.pg_addr[0]; env->spr[SPR_HASH2] = ctx.pg_addr[1]; - /* Do not alter DAR nor DSISR */ - goto out; + break; case POWERPC_MMU_SOFT_74xx: if (rw == 1) { - exception = POWERPC_EXCP_DSTLB; + env->exception_index = POWERPC_EXCP_DSTLB; } else { - exception = POWERPC_EXCP_DLTLB; + env->exception_index = POWERPC_EXCP_DLTLB; } tlb_miss_74xx: /* Implement LRU algorithm */ + env->error_code = ctx.key << 19; env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) | ((env->last_way + 1) & (env->nb_ways - 1)); env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem; - error_code = ctx.key << 19; break; case POWERPC_MMU_SOFT_4xx: case POWERPC_MMU_SOFT_4xx_Z: - exception = POWERPC_EXCP_DTLB; - error_code = 0; + env->exception_index = POWERPC_EXCP_DTLB; + env->error_code = 0; env->spr[SPR_40x_DEAR] = address; if (rw) env->spr[SPR_40x_ESR] = 0x00800000; @@ -1375,18 +1369,18 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, env->spr[SPR_40x_ESR] = 0x00000000; break; case POWERPC_MMU_32B: - error_code = 0x40000000; - break; #if defined(TARGET_PPC64) case POWERPC_MMU_64B: - /* XXX: TODO */ - cpu_abort(env, "MMU model not implemented\n"); - return -1; case POWERPC_MMU_64BRIDGE: - /* XXX: TODO */ - cpu_abort(env, "MMU model not implemented\n"); - return -1; #endif + env->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = address; + if (rw == 1) + env->spr[SPR_DSISR] = 0x42000000; + else + env->spr[SPR_DSISR] = 0x40000000; + break; case POWERPC_MMU_601: /* XXX: TODO */ cpu_abort(env, "MMU model not implemented\n"); @@ -1410,52 +1404,66 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, break; case -2: /* Access rights violation */ - error_code = 0x08000000; + env->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = address; + if (rw == 1) + env->spr[SPR_DSISR] = 0x0A000000; + else + env->spr[SPR_DSISR] = 0x08000000; break; case -4: /* Direct store exception */ switch (access_type) { case ACCESS_FLOAT: /* Floating point load/store */ - exception = POWERPC_EXCP_ALIGN; - error_code = POWERPC_EXCP_ALIGN_FP; + env->exception_index = POWERPC_EXCP_ALIGN; + env->error_code = POWERPC_EXCP_ALIGN_FP; + env->spr[SPR_DAR] = address; break; case ACCESS_RES: - /* lwarx, ldarx or srwcx. */ - error_code = 0x04000000; + /* lwarx, ldarx or stwcx. */ + env->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = address; + if (rw == 1) + env->spr[SPR_DSISR] = 0x06000000; + else + env->spr[SPR_DSISR] = 0x04000000; break; case ACCESS_EXT: /* eciwx or ecowx */ - error_code = 0x04100000; + env->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = address; + if (rw == 1) + env->spr[SPR_DSISR] = 0x06100000; + else + env->spr[SPR_DSISR] = 0x04100000; break; default: printf("DSI: invalid exception (%d)\n", ret); - exception = POWERPC_EXCP_PROGRAM; - error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; + env->exception_index = POWERPC_EXCP_PROGRAM; + env->error_code = + POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; + env->spr[SPR_DAR] = address; break; } break; #if defined(TARGET_PPC64) case -5: /* No match in segment table */ - exception = POWERPC_EXCP_DSEG; - error_code = 0; + env->exception_index = POWERPC_EXCP_DSEG; + env->error_code = 0; + env->spr[SPR_DAR] = address; break; #endif } - if (exception == POWERPC_EXCP_DSI && rw == 1) - error_code |= 0x02000000; - /* Store fault address */ - env->spr[SPR_DAR] = address; - env->spr[SPR_DSISR] = error_code; } - out: #if 0 - printf("%s: set exception to %d %02x\n", - __func__, exception, error_code); + printf("%s: set exception to %d %02x\n", __func__, + env->exception, env->error_code); #endif - env->exception_index = exception; - env->error_code = error_code; ret = 1; } @@ -2291,8 +2299,6 @@ static always_inline void powerpc_excp (CPUState *env, if (lpes1 == 0) msr_hv = 1; #endif - /* XXX: TODO */ - cpu_abort(env, "Data segment exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_ISEG: /* Instruction segment exception */ msr_ri = 0; @@ -2300,9 +2306,6 @@ static always_inline void powerpc_excp (CPUState *env, if (lpes1 == 0) msr_hv = 1; #endif - /* XXX: TODO */ - cpu_abort(env, - "Instruction segment exception is not implemented yet !\n"); goto store_next; #endif /* defined(TARGET_PPC64) */ #if defined(TARGET_PPC64H) |