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 | 93 | /* MMU model */ |
94 | 94 | typedef enum powerpc_mmu_t powerpc_mmu_t; |
95 | 95 | enum powerpc_mmu_t { |
96 | - POWERPC_MMU_UNKNOWN = 0, | |
96 | + POWERPC_MMU_UNKNOWN = 0x00000000, | |
97 | 97 | /* Standard 32 bits PowerPC MMU */ |
98 | - POWERPC_MMU_32B, | |
98 | + POWERPC_MMU_32B = 0x00000001, | |
99 | 99 | /* PowerPC 6xx MMU with software TLB */ |
100 | - POWERPC_MMU_SOFT_6xx, | |
100 | + POWERPC_MMU_SOFT_6xx = 0x00000002, | |
101 | 101 | /* PowerPC 74xx MMU with software TLB */ |
102 | - POWERPC_MMU_SOFT_74xx, | |
102 | + POWERPC_MMU_SOFT_74xx = 0x00000003, | |
103 | 103 | /* PowerPC 4xx MMU with software TLB */ |
104 | - POWERPC_MMU_SOFT_4xx, | |
104 | + POWERPC_MMU_SOFT_4xx = 0x00000004, | |
105 | 105 | /* PowerPC 4xx MMU with software TLB and zones protections */ |
106 | - POWERPC_MMU_SOFT_4xx_Z, | |
106 | + POWERPC_MMU_SOFT_4xx_Z = 0x00000005, | |
107 | 107 | /* PowerPC MMU in real mode only */ |
108 | - POWERPC_MMU_REAL, | |
108 | + POWERPC_MMU_REAL = 0x00000006, | |
109 | 109 | /* Freescale MPC8xx MMU model */ |
110 | - POWERPC_MMU_MPC8xx, | |
110 | + POWERPC_MMU_MPC8xx = 0x00000007, | |
111 | 111 | /* BookE MMU model */ |
112 | - POWERPC_MMU_BOOKE, | |
112 | + POWERPC_MMU_BOOKE = 0x00000008, | |
113 | 113 | /* BookE FSL MMU model */ |
114 | - POWERPC_MMU_BOOKE_FSL, | |
114 | + POWERPC_MMU_BOOKE_FSL = 0x00000009, | |
115 | 115 | /* PowerPC 601 MMU model (specific BATs format) */ |
116 | - POWERPC_MMU_601, | |
116 | + POWERPC_MMU_601 = 0x0000000A, | |
117 | 117 | #if defined(TARGET_PPC64) |
118 | +#define POWERPC_MMU_64 0x00010000 | |
118 | 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 | 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 | 706 | int h, int rw, int type) |
707 | 707 | { |
708 | 708 | #if defined(TARGET_PPC64) |
709 | - if (env->mmu_model == POWERPC_MMU_64B) | |
709 | + if (env->mmu_model & POWERPC_MMU_64) | |
710 | 710 | return find_pte64(ctx, h, rw, type); |
711 | 711 | #endif |
712 | 712 | |
... | ... | @@ -916,7 +916,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, |
916 | 916 | |
917 | 917 | pr = msr_pr; |
918 | 918 | #if defined(TARGET_PPC64) |
919 | - if (env->mmu_model == POWERPC_MMU_64B) { | |
919 | + if (env->mmu_model & POWERPC_MMU_64) { | |
920 | 920 | #if defined (DEBUG_MMU) |
921 | 921 | if (loglevel != 0) { |
922 | 922 | fprintf(logfile, "Check SLBs\n"); |
... | ... | @@ -973,7 +973,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx, |
973 | 973 | sdr = env->sdr1; |
974 | 974 | pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; |
975 | 975 | #if defined(TARGET_PPC64) |
976 | - if (env->mmu_model == POWERPC_MMU_64B) { | |
976 | + if (env->mmu_model & POWERPC_MMU_64) { | |
977 | 977 | htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); |
978 | 978 | /* XXX: this is false for 1 TB segments */ |
979 | 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 | 1002 | #endif |
1003 | 1003 | ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); |
1004 | 1004 | #if defined(TARGET_PPC64) |
1005 | - if (env->mmu_model == POWERPC_MMU_64B) { | |
1005 | + if (env->mmu_model & POWERPC_MMU_64) { | |
1006 | 1006 | /* Only 5 bits of the page index are used in the AVPN */ |
1007 | 1007 | ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); |
1008 | 1008 | } else |
... | ... | @@ -1362,6 +1362,7 @@ static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx, |
1362 | 1362 | ctx->prot |= PAGE_WRITE; |
1363 | 1363 | break; |
1364 | 1364 | #if defined(TARGET_PPC64) |
1365 | + case POWERPC_MMU_620: | |
1365 | 1366 | case POWERPC_MMU_64B: |
1366 | 1367 | /* Real address are 60 bits long */ |
1367 | 1368 | ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; |
... | ... | @@ -1430,6 +1431,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, |
1430 | 1431 | case POWERPC_MMU_SOFT_6xx: |
1431 | 1432 | case POWERPC_MMU_SOFT_74xx: |
1432 | 1433 | #if defined(TARGET_PPC64) |
1434 | + case POWERPC_MMU_620: | |
1433 | 1435 | case POWERPC_MMU_64B: |
1434 | 1436 | #endif |
1435 | 1437 | /* Try to find a BAT */ |
... | ... | @@ -1538,6 +1540,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
1538 | 1540 | case POWERPC_MMU_32B: |
1539 | 1541 | case POWERPC_MMU_601: |
1540 | 1542 | #if defined(TARGET_PPC64) |
1543 | + case POWERPC_MMU_620: | |
1541 | 1544 | case POWERPC_MMU_64B: |
1542 | 1545 | #endif |
1543 | 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 | 1586 | #if defined(TARGET_PPC64) |
1584 | 1587 | case -5: |
1585 | 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 | 1597 | break; |
1589 | 1598 | #endif |
1590 | 1599 | } |
... | ... | @@ -1634,6 +1643,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
1634 | 1643 | case POWERPC_MMU_32B: |
1635 | 1644 | case POWERPC_MMU_601: |
1636 | 1645 | #if defined(TARGET_PPC64) |
1646 | + case POWERPC_MMU_620: | |
1637 | 1647 | case POWERPC_MMU_64B: |
1638 | 1648 | #endif |
1639 | 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 | 1726 | #if defined(TARGET_PPC64) |
1717 | 1727 | case -5: |
1718 | 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 | 1743 | break; |
1723 | 1744 | #endif |
1724 | 1745 | } |
... | ... | @@ -1955,6 +1976,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) |
1955 | 1976 | case POWERPC_MMU_32B: |
1956 | 1977 | case POWERPC_MMU_601: |
1957 | 1978 | #if defined(TARGET_PPC64) |
1979 | + case POWERPC_MMU_620: | |
1958 | 1980 | case POWERPC_MMU_64B: |
1959 | 1981 | #endif /* defined(TARGET_PPC64) */ |
1960 | 1982 | tlb_flush(env, 1); |
... | ... | @@ -2021,6 +2043,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) |
2021 | 2043 | tlb_flush_page(env, addr | (0xF << 28)); |
2022 | 2044 | break; |
2023 | 2045 | #if defined(TARGET_PPC64) |
2046 | + case POWERPC_MMU_620: | |
2024 | 2047 | case POWERPC_MMU_64B: |
2025 | 2048 | /* tlbie invalidate TLBs for all segments */ |
2026 | 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 | 5237 | /* PowerPC 620 */ |
5238 | 5238 | #define POWERPC_INSNS_620 (POWERPC_INSNS_WORKS | PPC_FLOAT_FSQRT | \ |
5239 | 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 | 5242 | #define POWERPC_EXCP_620 (POWERPC_EXCP_970) |
5243 | 5243 | #define POWERPC_INPUT_620 (PPC_FLAGS_INPUT_6xx) |
5244 | 5244 | #define POWERPC_BFDM_620 (bfd_mach_ppc64) |
5245 | 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 | 5247 | #define check_pow_620 check_pow_nocheck /* Check this */ |
5248 | 5248 | |
5249 | 5249 | __attribute__ (( unused )) |
... | ... | @@ -8313,6 +8313,9 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def) |
8313 | 8313 | case POWERPC_MMU_64B: |
8314 | 8314 | mmu_model = "PowerPC 64"; |
8315 | 8315 | break; |
8316 | + case POWERPC_MMU_620: | |
8317 | + mmu_model = "PowerPC 620"; | |
8318 | + break; | |
8316 | 8319 | #endif |
8317 | 8320 | default: |
8318 | 8321 | mmu_model = "Unknown or invalid"; | ... | ... |