aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--target-ppc/cpu.h27
-rw-r--r--target-ppc/helper.c41
-rw-r--r--target-ppc/translate_init.c9
3 files changed, 53 insertions, 24 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index d2faf61e8e..6f3ff86a1c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -93,30 +93,33 @@ typedef uint32_t ppc_gpr_t;
/* MMU model */
typedef enum powerpc_mmu_t powerpc_mmu_t;
enum powerpc_mmu_t {
- POWERPC_MMU_UNKNOWN = 0,
+ POWERPC_MMU_UNKNOWN = 0x00000000,
/* Standard 32 bits PowerPC MMU */
- POWERPC_MMU_32B,
+ POWERPC_MMU_32B = 0x00000001,
/* PowerPC 6xx MMU with software TLB */
- POWERPC_MMU_SOFT_6xx,
+ POWERPC_MMU_SOFT_6xx = 0x00000002,
/* PowerPC 74xx MMU with software TLB */
- POWERPC_MMU_SOFT_74xx,
+ POWERPC_MMU_SOFT_74xx = 0x00000003,
/* PowerPC 4xx MMU with software TLB */
- POWERPC_MMU_SOFT_4xx,
+ POWERPC_MMU_SOFT_4xx = 0x00000004,
/* PowerPC 4xx MMU with software TLB and zones protections */
- POWERPC_MMU_SOFT_4xx_Z,
+ POWERPC_MMU_SOFT_4xx_Z = 0x00000005,
/* PowerPC MMU in real mode only */
- POWERPC_MMU_REAL,
+ POWERPC_MMU_REAL = 0x00000006,
/* Freescale MPC8xx MMU model */
- POWERPC_MMU_MPC8xx,
+ POWERPC_MMU_MPC8xx = 0x00000007,
/* BookE MMU model */
- POWERPC_MMU_BOOKE,
+ POWERPC_MMU_BOOKE = 0x00000008,
/* BookE FSL MMU model */
- POWERPC_MMU_BOOKE_FSL,
+ POWERPC_MMU_BOOKE_FSL = 0x00000009,
/* PowerPC 601 MMU model (specific BATs format) */
- POWERPC_MMU_601,
+ POWERPC_MMU_601 = 0x0000000A,
#if defined(TARGET_PPC64)
+#define POWERPC_MMU_64 0x00010000
/* 64 bits PowerPC MMU */
- POWERPC_MMU_64B,
+ POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
+ /* 620 variant (no segment exceptions) */
+ POWERPC_MMU_620 = POWERPC_MMU_64 | 0x00000002,
#endif /* defined(TARGET_PPC64) */
};
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,
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index ce0027cc39..f3bc1f5f7f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -5237,13 +5237,13 @@ static void init_proc_970MP (CPUPPCState *env)
/* PowerPC 620 */
#define POWERPC_INSNS_620 (POWERPC_INSNS_WORKS | PPC_FLOAT_FSQRT | \
PPC_64B | PPC_SLBI)
-#define POWERPC_MSRM_620 (0x800000000005FF73ULL)
-#define POWERPC_MMU_620 (POWERPC_MMU_64B)
+#define POWERPC_MSRM_620 (0x800000000005FF77ULL)
+//#define POWERPC_MMU_620 (POWERPC_MMU_620)
#define POWERPC_EXCP_620 (POWERPC_EXCP_970)
#define POWERPC_INPUT_620 (PPC_FLAGS_INPUT_6xx)
#define POWERPC_BFDM_620 (bfd_mach_ppc64)
#define POWERPC_FLAG_620 (POWERPC_FLAG_SE | POWERPC_FLAG_BE | \
- POWERPC_FLAG_BUS_CLK)
+ POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
#define check_pow_620 check_pow_nocheck /* Check this */
__attribute__ (( unused ))
@@ -8313,6 +8313,9 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
case POWERPC_MMU_64B:
mmu_model = "PowerPC 64";
break;
+ case POWERPC_MMU_620:
+ mmu_model = "PowerPC 620";
+ break;
#endif
default:
mmu_model = "Unknown or invalid";