Commit add78955b0451c6d14d325d66592a634b2e5d595
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
Showing
3 changed files
with
53 additions
and
24 deletions
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"; |