aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/helper.c
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-03 20:19:40 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-03 20:19:40 +0000
commit8f793433afd8f892db15fc153bb0aa94145582d6 (patch)
treeccc2a48dabb1f52f52b53d8d83dd35f542f7bbca /target-ppc/helper.c
parent0387d928754f08574a18ff72104d669d91dcc2f8 (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.c139
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)