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
This commit is contained in:
parent
0387d92875
commit
8f793433af
|
@ -45,10 +45,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||||
|
|
||||||
if (rw == 2) {
|
if (rw == 2) {
|
||||||
exception = POWERPC_EXCP_ISI;
|
exception = POWERPC_EXCP_ISI;
|
||||||
error_code = 0;
|
error_code = 0x40000000;
|
||||||
} else {
|
} else {
|
||||||
exception = POWERPC_EXCP_DSI;
|
exception = POWERPC_EXCP_DSI;
|
||||||
error_code = 0;
|
error_code = 0x40000000;
|
||||||
if (rw)
|
if (rw)
|
||||||
error_code |= 0x02000000;
|
error_code |= 0x02000000;
|
||||||
env->spr[SPR_DAR] = address;
|
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)
|
int is_user, int is_softmmu)
|
||||||
{
|
{
|
||||||
mmu_ctx_t ctx;
|
mmu_ctx_t ctx;
|
||||||
int exception = 0, error_code = 0;
|
|
||||||
int access_type;
|
int access_type;
|
||||||
int ret = 0;
|
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);
|
cpu_dump_state(env, logfile, fprintf, 0);
|
||||||
#endif
|
#endif
|
||||||
if (access_type == ACCESS_CODE) {
|
if (access_type == ACCESS_CODE) {
|
||||||
exception = POWERPC_EXCP_ISI;
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -1:
|
case -1:
|
||||||
/* No matches in page tables or TLB */
|
/* No matches in page tables or TLB */
|
||||||
switch (env->mmu_model) {
|
switch (env->mmu_model) {
|
||||||
case POWERPC_MMU_SOFT_6xx:
|
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_IMISS] = address;
|
||||||
env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
|
env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
|
||||||
error_code = 1 << 18;
|
|
||||||
goto tlb_miss;
|
goto tlb_miss;
|
||||||
case POWERPC_MMU_SOFT_74xx:
|
case POWERPC_MMU_SOFT_74xx:
|
||||||
exception = POWERPC_EXCP_IFTLB;
|
env->exception_index = POWERPC_EXCP_IFTLB;
|
||||||
goto tlb_miss_74xx;
|
goto tlb_miss_74xx;
|
||||||
case POWERPC_MMU_SOFT_4xx:
|
case POWERPC_MMU_SOFT_4xx:
|
||||||
case POWERPC_MMU_SOFT_4xx_Z:
|
case POWERPC_MMU_SOFT_4xx_Z:
|
||||||
exception = POWERPC_EXCP_ITLB;
|
env->exception_index = POWERPC_EXCP_ITLB;
|
||||||
error_code = 0;
|
env->error_code = 0;
|
||||||
env->spr[SPR_40x_DEAR] = address;
|
env->spr[SPR_40x_DEAR] = address;
|
||||||
env->spr[SPR_40x_ESR] = 0x00000000;
|
env->spr[SPR_40x_ESR] = 0x00000000;
|
||||||
break;
|
break;
|
||||||
case POWERPC_MMU_32B:
|
case POWERPC_MMU_32B:
|
||||||
error_code = 0x40000000;
|
|
||||||
break;
|
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
case POWERPC_MMU_64B:
|
case POWERPC_MMU_64B:
|
||||||
/* XXX: TODO */
|
|
||||||
cpu_abort(env, "MMU model not implemented\n");
|
|
||||||
return -1;
|
|
||||||
case POWERPC_MMU_64BRIDGE:
|
case POWERPC_MMU_64BRIDGE:
|
||||||
/* XXX: TODO */
|
|
||||||
cpu_abort(env, "MMU model not implemented\n");
|
|
||||||
return -1;
|
|
||||||
#endif
|
#endif
|
||||||
|
env->exception_index = POWERPC_EXCP_ISI;
|
||||||
|
env->error_code = 0x40000000;
|
||||||
|
break;
|
||||||
case POWERPC_MMU_601:
|
case POWERPC_MMU_601:
|
||||||
/* XXX: TODO */
|
/* XXX: TODO */
|
||||||
cpu_abort(env, "MMU model not implemented\n");
|
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;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
/* Access rights violation */
|
/* Access rights violation */
|
||||||
error_code = 0x08000000;
|
env->exception_index = POWERPC_EXCP_ISI;
|
||||||
|
env->error_code = 0x08000000;
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
/* No execute protection violation */
|
/* No execute protection violation */
|
||||||
error_code = 0x10000000;
|
env->exception_index = POWERPC_EXCP_ISI;
|
||||||
|
env->error_code = 0x10000000;
|
||||||
break;
|
break;
|
||||||
case -4:
|
case -4:
|
||||||
/* Direct store exception */
|
/* Direct store exception */
|
||||||
/* No code fetch is allowed in direct-store areas */
|
/* No code fetch is allowed in direct-store areas */
|
||||||
error_code = 0x10000000;
|
env->exception_index = POWERPC_EXCP_ISI;
|
||||||
|
env->error_code = 0x10000000;
|
||||||
break;
|
break;
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
case -5:
|
case -5:
|
||||||
/* No match in segment table */
|
/* No match in segment table */
|
||||||
exception = POWERPC_EXCP_ISEG;
|
env->exception_index = POWERPC_EXCP_ISEG;
|
||||||
error_code = 0;
|
env->error_code = 0;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
exception = POWERPC_EXCP_DSI;
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -1:
|
case -1:
|
||||||
/* No matches in page tables or TLB */
|
/* No matches in page tables or TLB */
|
||||||
switch (env->mmu_model) {
|
switch (env->mmu_model) {
|
||||||
case POWERPC_MMU_SOFT_6xx:
|
case POWERPC_MMU_SOFT_6xx:
|
||||||
if (rw == 1) {
|
if (rw == 1) {
|
||||||
exception = POWERPC_EXCP_DSTLB;
|
env->exception_index = POWERPC_EXCP_DSTLB;
|
||||||
error_code = 1 << 16;
|
env->error_code = 1 << 16;
|
||||||
} else {
|
} else {
|
||||||
exception = POWERPC_EXCP_DLTLB;
|
env->exception_index = POWERPC_EXCP_DLTLB;
|
||||||
error_code = 0;
|
env->error_code = 0;
|
||||||
}
|
}
|
||||||
env->spr[SPR_DMISS] = address;
|
env->spr[SPR_DMISS] = address;
|
||||||
env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
|
env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
|
||||||
tlb_miss:
|
tlb_miss:
|
||||||
error_code |= ctx.key << 19;
|
env->error_code |= ctx.key << 19;
|
||||||
env->spr[SPR_HASH1] = ctx.pg_addr[0];
|
env->spr[SPR_HASH1] = ctx.pg_addr[0];
|
||||||
env->spr[SPR_HASH2] = ctx.pg_addr[1];
|
env->spr[SPR_HASH2] = ctx.pg_addr[1];
|
||||||
/* Do not alter DAR nor DSISR */
|
break;
|
||||||
goto out;
|
|
||||||
case POWERPC_MMU_SOFT_74xx:
|
case POWERPC_MMU_SOFT_74xx:
|
||||||
if (rw == 1) {
|
if (rw == 1) {
|
||||||
exception = POWERPC_EXCP_DSTLB;
|
env->exception_index = POWERPC_EXCP_DSTLB;
|
||||||
} else {
|
} else {
|
||||||
exception = POWERPC_EXCP_DLTLB;
|
env->exception_index = POWERPC_EXCP_DLTLB;
|
||||||
}
|
}
|
||||||
tlb_miss_74xx:
|
tlb_miss_74xx:
|
||||||
/* Implement LRU algorithm */
|
/* Implement LRU algorithm */
|
||||||
|
env->error_code = ctx.key << 19;
|
||||||
env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
|
env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
|
||||||
((env->last_way + 1) & (env->nb_ways - 1));
|
((env->last_way + 1) & (env->nb_ways - 1));
|
||||||
env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
|
env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
|
||||||
error_code = ctx.key << 19;
|
|
||||||
break;
|
break;
|
||||||
case POWERPC_MMU_SOFT_4xx:
|
case POWERPC_MMU_SOFT_4xx:
|
||||||
case POWERPC_MMU_SOFT_4xx_Z:
|
case POWERPC_MMU_SOFT_4xx_Z:
|
||||||
exception = POWERPC_EXCP_DTLB;
|
env->exception_index = POWERPC_EXCP_DTLB;
|
||||||
error_code = 0;
|
env->error_code = 0;
|
||||||
env->spr[SPR_40x_DEAR] = address;
|
env->spr[SPR_40x_DEAR] = address;
|
||||||
if (rw)
|
if (rw)
|
||||||
env->spr[SPR_40x_ESR] = 0x00800000;
|
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;
|
env->spr[SPR_40x_ESR] = 0x00000000;
|
||||||
break;
|
break;
|
||||||
case POWERPC_MMU_32B:
|
case POWERPC_MMU_32B:
|
||||||
error_code = 0x40000000;
|
|
||||||
break;
|
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
case POWERPC_MMU_64B:
|
case POWERPC_MMU_64B:
|
||||||
/* XXX: TODO */
|
|
||||||
cpu_abort(env, "MMU model not implemented\n");
|
|
||||||
return -1;
|
|
||||||
case POWERPC_MMU_64BRIDGE:
|
case POWERPC_MMU_64BRIDGE:
|
||||||
/* XXX: TODO */
|
|
||||||
cpu_abort(env, "MMU model not implemented\n");
|
|
||||||
return -1;
|
|
||||||
#endif
|
#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:
|
case POWERPC_MMU_601:
|
||||||
/* XXX: TODO */
|
/* XXX: TODO */
|
||||||
cpu_abort(env, "MMU model not implemented\n");
|
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;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
/* Access rights violation */
|
/* 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;
|
break;
|
||||||
case -4:
|
case -4:
|
||||||
/* Direct store exception */
|
/* Direct store exception */
|
||||||
switch (access_type) {
|
switch (access_type) {
|
||||||
case ACCESS_FLOAT:
|
case ACCESS_FLOAT:
|
||||||
/* Floating point load/store */
|
/* Floating point load/store */
|
||||||
exception = POWERPC_EXCP_ALIGN;
|
env->exception_index = POWERPC_EXCP_ALIGN;
|
||||||
error_code = POWERPC_EXCP_ALIGN_FP;
|
env->error_code = POWERPC_EXCP_ALIGN_FP;
|
||||||
|
env->spr[SPR_DAR] = address;
|
||||||
break;
|
break;
|
||||||
case ACCESS_RES:
|
case ACCESS_RES:
|
||||||
/* lwarx, ldarx or srwcx. */
|
/* lwarx, ldarx or stwcx. */
|
||||||
error_code = 0x04000000;
|
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;
|
break;
|
||||||
case ACCESS_EXT:
|
case ACCESS_EXT:
|
||||||
/* eciwx or ecowx */
|
/* 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;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("DSI: invalid exception (%d)\n", ret);
|
printf("DSI: invalid exception (%d)\n", ret);
|
||||||
exception = POWERPC_EXCP_PROGRAM;
|
env->exception_index = POWERPC_EXCP_PROGRAM;
|
||||||
error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
|
env->error_code =
|
||||||
|
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
|
||||||
|
env->spr[SPR_DAR] = address;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if defined(TARGET_PPC64)
|
#if defined(TARGET_PPC64)
|
||||||
case -5:
|
case -5:
|
||||||
/* No match in segment table */
|
/* No match in segment table */
|
||||||
exception = POWERPC_EXCP_DSEG;
|
env->exception_index = POWERPC_EXCP_DSEG;
|
||||||
error_code = 0;
|
env->error_code = 0;
|
||||||
|
env->spr[SPR_DAR] = address;
|
||||||
break;
|
break;
|
||||||
#endif
|
#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
|
#if 0
|
||||||
printf("%s: set exception to %d %02x\n",
|
printf("%s: set exception to %d %02x\n", __func__,
|
||||||
__func__, exception, error_code);
|
env->exception, env->error_code);
|
||||||
#endif
|
#endif
|
||||||
env->exception_index = exception;
|
|
||||||
env->error_code = error_code;
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2291,8 +2299,6 @@ static always_inline void powerpc_excp (CPUState *env,
|
||||||
if (lpes1 == 0)
|
if (lpes1 == 0)
|
||||||
msr_hv = 1;
|
msr_hv = 1;
|
||||||
#endif
|
#endif
|
||||||
/* XXX: TODO */
|
|
||||||
cpu_abort(env, "Data segment exception is not implemented yet !\n");
|
|
||||||
goto store_next;
|
goto store_next;
|
||||||
case POWERPC_EXCP_ISEG: /* Instruction segment exception */
|
case POWERPC_EXCP_ISEG: /* Instruction segment exception */
|
||||||
msr_ri = 0;
|
msr_ri = 0;
|
||||||
|
@ -2300,9 +2306,6 @@ static always_inline void powerpc_excp (CPUState *env,
|
||||||
if (lpes1 == 0)
|
if (lpes1 == 0)
|
||||||
msr_hv = 1;
|
msr_hv = 1;
|
||||||
#endif
|
#endif
|
||||||
/* XXX: TODO */
|
|
||||||
cpu_abort(env,
|
|
||||||
"Instruction segment exception is not implemented yet !\n");
|
|
||||||
goto store_next;
|
goto store_next;
|
||||||
#endif /* defined(TARGET_PPC64) */
|
#endif /* defined(TARGET_PPC64) */
|
||||||
#if defined(TARGET_PPC64H)
|
#if defined(TARGET_PPC64H)
|
||||||
|
|
Loading…
Reference in a new issue