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
This commit is contained in:
parent
5b8105fa50
commit
add78955b0
@ -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) */
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user