Commit add78955b0451c6d14d325d66592a634b2e5d595

Authored by j_mayer
1 parent 5b8105fa

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
target-ppc/cpu.h
@@ -93,30 +93,33 @@ typedef uint32_t ppc_gpr_t; @@ -93,30 +93,33 @@ typedef uint32_t ppc_gpr_t;
93 /* MMU model */ 93 /* MMU model */
94 typedef enum powerpc_mmu_t powerpc_mmu_t; 94 typedef enum powerpc_mmu_t powerpc_mmu_t;
95 enum powerpc_mmu_t { 95 enum powerpc_mmu_t {
96 - POWERPC_MMU_UNKNOWN = 0, 96 + POWERPC_MMU_UNKNOWN = 0x00000000,
97 /* Standard 32 bits PowerPC MMU */ 97 /* Standard 32 bits PowerPC MMU */
98 - POWERPC_MMU_32B, 98 + POWERPC_MMU_32B = 0x00000001,
99 /* PowerPC 6xx MMU with software TLB */ 99 /* PowerPC 6xx MMU with software TLB */
100 - POWERPC_MMU_SOFT_6xx, 100 + POWERPC_MMU_SOFT_6xx = 0x00000002,
101 /* PowerPC 74xx MMU with software TLB */ 101 /* PowerPC 74xx MMU with software TLB */
102 - POWERPC_MMU_SOFT_74xx, 102 + POWERPC_MMU_SOFT_74xx = 0x00000003,
103 /* PowerPC 4xx MMU with software TLB */ 103 /* PowerPC 4xx MMU with software TLB */
104 - POWERPC_MMU_SOFT_4xx, 104 + POWERPC_MMU_SOFT_4xx = 0x00000004,
105 /* PowerPC 4xx MMU with software TLB and zones protections */ 105 /* PowerPC 4xx MMU with software TLB and zones protections */
106 - POWERPC_MMU_SOFT_4xx_Z, 106 + POWERPC_MMU_SOFT_4xx_Z = 0x00000005,
107 /* PowerPC MMU in real mode only */ 107 /* PowerPC MMU in real mode only */
108 - POWERPC_MMU_REAL, 108 + POWERPC_MMU_REAL = 0x00000006,
109 /* Freescale MPC8xx MMU model */ 109 /* Freescale MPC8xx MMU model */
110 - POWERPC_MMU_MPC8xx, 110 + POWERPC_MMU_MPC8xx = 0x00000007,
111 /* BookE MMU model */ 111 /* BookE MMU model */
112 - POWERPC_MMU_BOOKE, 112 + POWERPC_MMU_BOOKE = 0x00000008,
113 /* BookE FSL MMU model */ 113 /* BookE FSL MMU model */
114 - POWERPC_MMU_BOOKE_FSL, 114 + POWERPC_MMU_BOOKE_FSL = 0x00000009,
115 /* PowerPC 601 MMU model (specific BATs format) */ 115 /* PowerPC 601 MMU model (specific BATs format) */
116 - POWERPC_MMU_601, 116 + POWERPC_MMU_601 = 0x0000000A,
117 #if defined(TARGET_PPC64) 117 #if defined(TARGET_PPC64)
  118 +#define POWERPC_MMU_64 0x00010000
118 /* 64 bits PowerPC MMU */ 119 /* 64 bits PowerPC MMU */
119 - POWERPC_MMU_64B, 120 + POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
  121 + /* 620 variant (no segment exceptions) */
  122 + POWERPC_MMU_620 = POWERPC_MMU_64 | 0x00000002,
120 #endif /* defined(TARGET_PPC64) */ 123 #endif /* defined(TARGET_PPC64) */
121 }; 124 };
122 125
target-ppc/helper.c
@@ -706,7 +706,7 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx, @@ -706,7 +706,7 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
706 int h, int rw, int type) 706 int h, int rw, int type)
707 { 707 {
708 #if defined(TARGET_PPC64) 708 #if defined(TARGET_PPC64)
709 - if (env->mmu_model == POWERPC_MMU_64B) 709 + if (env->mmu_model & POWERPC_MMU_64)
710 return find_pte64(ctx, h, rw, type); 710 return find_pte64(ctx, h, rw, type);
711 #endif 711 #endif
712 712
@@ -916,7 +916,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, @@ -916,7 +916,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
916 916
917 pr = msr_pr; 917 pr = msr_pr;
918 #if defined(TARGET_PPC64) 918 #if defined(TARGET_PPC64)
919 - if (env->mmu_model == POWERPC_MMU_64B) { 919 + if (env->mmu_model & POWERPC_MMU_64) {
920 #if defined (DEBUG_MMU) 920 #if defined (DEBUG_MMU)
921 if (loglevel != 0) { 921 if (loglevel != 0) {
922 fprintf(logfile, "Check SLBs\n"); 922 fprintf(logfile, "Check SLBs\n");
@@ -973,7 +973,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, @@ -973,7 +973,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
973 sdr = env->sdr1; 973 sdr = env->sdr1;
974 pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; 974 pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
975 #if defined(TARGET_PPC64) 975 #if defined(TARGET_PPC64)
976 - if (env->mmu_model == POWERPC_MMU_64B) { 976 + if (env->mmu_model & POWERPC_MMU_64) {
977 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); 977 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
978 /* XXX: this is false for 1 TB segments */ 978 /* XXX: this is false for 1 TB segments */
979 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; 979 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
@@ -1002,7 +1002,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, @@ -1002,7 +1002,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
1002 #endif 1002 #endif
1003 ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); 1003 ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
1004 #if defined(TARGET_PPC64) 1004 #if defined(TARGET_PPC64)
1005 - if (env->mmu_model == POWERPC_MMU_64B) { 1005 + if (env->mmu_model & POWERPC_MMU_64) {
1006 /* Only 5 bits of the page index are used in the AVPN */ 1006 /* Only 5 bits of the page index are used in the AVPN */
1007 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); 1007 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
1008 } else 1008 } else
@@ -1362,6 +1362,7 @@ static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx, @@ -1362,6 +1362,7 @@ static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
1362 ctx->prot |= PAGE_WRITE; 1362 ctx->prot |= PAGE_WRITE;
1363 break; 1363 break;
1364 #if defined(TARGET_PPC64) 1364 #if defined(TARGET_PPC64)
  1365 + case POWERPC_MMU_620:
1365 case POWERPC_MMU_64B: 1366 case POWERPC_MMU_64B:
1366 /* Real address are 60 bits long */ 1367 /* Real address are 60 bits long */
1367 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; 1368 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
@@ -1430,6 +1431,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, @@ -1430,6 +1431,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1430 case POWERPC_MMU_SOFT_6xx: 1431 case POWERPC_MMU_SOFT_6xx:
1431 case POWERPC_MMU_SOFT_74xx: 1432 case POWERPC_MMU_SOFT_74xx:
1432 #if defined(TARGET_PPC64) 1433 #if defined(TARGET_PPC64)
  1434 + case POWERPC_MMU_620:
1433 case POWERPC_MMU_64B: 1435 case POWERPC_MMU_64B:
1434 #endif 1436 #endif
1435 /* Try to find a BAT */ 1437 /* Try to find a BAT */
@@ -1538,6 +1540,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, @@ -1538,6 +1540,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1538 case POWERPC_MMU_32B: 1540 case POWERPC_MMU_32B:
1539 case POWERPC_MMU_601: 1541 case POWERPC_MMU_601:
1540 #if defined(TARGET_PPC64) 1542 #if defined(TARGET_PPC64)
  1543 + case POWERPC_MMU_620:
1541 case POWERPC_MMU_64B: 1544 case POWERPC_MMU_64B:
1542 #endif 1545 #endif
1543 env->exception_index = POWERPC_EXCP_ISI; 1546 env->exception_index = POWERPC_EXCP_ISI;
@@ -1583,8 +1586,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, @@ -1583,8 +1586,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1583 #if defined(TARGET_PPC64) 1586 #if defined(TARGET_PPC64)
1584 case -5: 1587 case -5:
1585 /* No match in segment table */ 1588 /* No match in segment table */
1586 - env->exception_index = POWERPC_EXCP_ISEG;  
1587 - env->error_code = 0; 1589 + if (env->mmu_model == POWERPC_MMU_620) {
  1590 + env->exception_index = POWERPC_EXCP_ISI;
  1591 + /* XXX: this might be incorrect */
  1592 + env->error_code = 0x40000000;
  1593 + } else {
  1594 + env->exception_index = POWERPC_EXCP_ISEG;
  1595 + env->error_code = 0;
  1596 + }
1588 break; 1597 break;
1589 #endif 1598 #endif
1590 } 1599 }
@@ -1634,6 +1643,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, @@ -1634,6 +1643,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1634 case POWERPC_MMU_32B: 1643 case POWERPC_MMU_32B:
1635 case POWERPC_MMU_601: 1644 case POWERPC_MMU_601:
1636 #if defined(TARGET_PPC64) 1645 #if defined(TARGET_PPC64)
  1646 + case POWERPC_MMU_620:
1637 case POWERPC_MMU_64B: 1647 case POWERPC_MMU_64B:
1638 #endif 1648 #endif
1639 env->exception_index = POWERPC_EXCP_DSI; 1649 env->exception_index = POWERPC_EXCP_DSI;
@@ -1716,9 +1726,20 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, @@ -1716,9 +1726,20 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1716 #if defined(TARGET_PPC64) 1726 #if defined(TARGET_PPC64)
1717 case -5: 1727 case -5:
1718 /* No match in segment table */ 1728 /* No match in segment table */
1719 - env->exception_index = POWERPC_EXCP_DSEG;  
1720 - env->error_code = 0;  
1721 - env->spr[SPR_DAR] = address; 1729 + if (env->mmu_model == POWERPC_MMU_620) {
  1730 + env->exception_index = POWERPC_EXCP_DSI;
  1731 + env->error_code = 0;
  1732 + env->spr[SPR_DAR] = address;
  1733 + /* XXX: this might be incorrect */
  1734 + if (rw == 1)
  1735 + env->spr[SPR_DSISR] = 0x42000000;
  1736 + else
  1737 + env->spr[SPR_DSISR] = 0x40000000;
  1738 + } else {
  1739 + env->exception_index = POWERPC_EXCP_DSEG;
  1740 + env->error_code = 0;
  1741 + env->spr[SPR_DAR] = address;
  1742 + }
1722 break; 1743 break;
1723 #endif 1744 #endif
1724 } 1745 }
@@ -1955,6 +1976,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) @@ -1955,6 +1976,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
1955 case POWERPC_MMU_32B: 1976 case POWERPC_MMU_32B:
1956 case POWERPC_MMU_601: 1977 case POWERPC_MMU_601:
1957 #if defined(TARGET_PPC64) 1978 #if defined(TARGET_PPC64)
  1979 + case POWERPC_MMU_620:
1958 case POWERPC_MMU_64B: 1980 case POWERPC_MMU_64B:
1959 #endif /* defined(TARGET_PPC64) */ 1981 #endif /* defined(TARGET_PPC64) */
1960 tlb_flush(env, 1); 1982 tlb_flush(env, 1);
@@ -2021,6 +2043,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) @@ -2021,6 +2043,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2021 tlb_flush_page(env, addr | (0xF << 28)); 2043 tlb_flush_page(env, addr | (0xF << 28));
2022 break; 2044 break;
2023 #if defined(TARGET_PPC64) 2045 #if defined(TARGET_PPC64)
  2046 + case POWERPC_MMU_620:
2024 case POWERPC_MMU_64B: 2047 case POWERPC_MMU_64B:
2025 /* tlbie invalidate TLBs for all segments */ 2048 /* tlbie invalidate TLBs for all segments */
2026 /* XXX: given the fact that there are too many segments to invalidate, 2049 /* XXX: given the fact that there are too many segments to invalidate,
target-ppc/translate_init.c
@@ -5237,13 +5237,13 @@ static void init_proc_970MP (CPUPPCState *env) @@ -5237,13 +5237,13 @@ static void init_proc_970MP (CPUPPCState *env)
5237 /* PowerPC 620 */ 5237 /* PowerPC 620 */
5238 #define POWERPC_INSNS_620 (POWERPC_INSNS_WORKS | PPC_FLOAT_FSQRT | \ 5238 #define POWERPC_INSNS_620 (POWERPC_INSNS_WORKS | PPC_FLOAT_FSQRT | \
5239 PPC_64B | PPC_SLBI) 5239 PPC_64B | PPC_SLBI)
5240 -#define POWERPC_MSRM_620 (0x800000000005FF73ULL)  
5241 -#define POWERPC_MMU_620 (POWERPC_MMU_64B) 5240 +#define POWERPC_MSRM_620 (0x800000000005FF77ULL)
  5241 +//#define POWERPC_MMU_620 (POWERPC_MMU_620)
5242 #define POWERPC_EXCP_620 (POWERPC_EXCP_970) 5242 #define POWERPC_EXCP_620 (POWERPC_EXCP_970)
5243 #define POWERPC_INPUT_620 (PPC_FLAGS_INPUT_6xx) 5243 #define POWERPC_INPUT_620 (PPC_FLAGS_INPUT_6xx)
5244 #define POWERPC_BFDM_620 (bfd_mach_ppc64) 5244 #define POWERPC_BFDM_620 (bfd_mach_ppc64)
5245 #define POWERPC_FLAG_620 (POWERPC_FLAG_SE | POWERPC_FLAG_BE | \ 5245 #define POWERPC_FLAG_620 (POWERPC_FLAG_SE | POWERPC_FLAG_BE | \
5246 - POWERPC_FLAG_BUS_CLK) 5246 + POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
5247 #define check_pow_620 check_pow_nocheck /* Check this */ 5247 #define check_pow_620 check_pow_nocheck /* Check this */
5248 5248
5249 __attribute__ (( unused )) 5249 __attribute__ (( unused ))
@@ -8313,6 +8313,9 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def) @@ -8313,6 +8313,9 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
8313 case POWERPC_MMU_64B: 8313 case POWERPC_MMU_64B:
8314 mmu_model = "PowerPC 64"; 8314 mmu_model = "PowerPC 64";
8315 break; 8315 break;
  8316 + case POWERPC_MMU_620:
  8317 + mmu_model = "PowerPC 620";
  8318 + break;
8316 #endif 8319 #endif
8317 default: 8320 default:
8318 mmu_model = "Unknown or invalid"; 8321 mmu_model = "Unknown or invalid";