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"; | ... | ... |