xref: /openbmc/qemu/target/ppc/mmu_common.c (revision 691cf34f216141138bb0289735a762dd7d812137)
15118ebe8SLucas Mateus Castro (alqotel) /*
25118ebe8SLucas Mateus Castro (alqotel)  *  PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
35118ebe8SLucas Mateus Castro (alqotel)  *
45118ebe8SLucas Mateus Castro (alqotel)  *  Copyright (c) 2003-2007 Jocelyn Mayer
55118ebe8SLucas Mateus Castro (alqotel)  *
65118ebe8SLucas Mateus Castro (alqotel)  * This library is free software; you can redistribute it and/or
75118ebe8SLucas Mateus Castro (alqotel)  * modify it under the terms of the GNU Lesser General Public
85118ebe8SLucas Mateus Castro (alqotel)  * License as published by the Free Software Foundation; either
95118ebe8SLucas Mateus Castro (alqotel)  * version 2.1 of the License, or (at your option) any later version.
105118ebe8SLucas Mateus Castro (alqotel)  *
115118ebe8SLucas Mateus Castro (alqotel)  * This library is distributed in the hope that it will be useful,
125118ebe8SLucas Mateus Castro (alqotel)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
135118ebe8SLucas Mateus Castro (alqotel)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145118ebe8SLucas Mateus Castro (alqotel)  * Lesser General Public License for more details.
155118ebe8SLucas Mateus Castro (alqotel)  *
165118ebe8SLucas Mateus Castro (alqotel)  * You should have received a copy of the GNU Lesser General Public
175118ebe8SLucas Mateus Castro (alqotel)  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
185118ebe8SLucas Mateus Castro (alqotel)  */
195118ebe8SLucas Mateus Castro (alqotel) 
205118ebe8SLucas Mateus Castro (alqotel) #include "qemu/osdep.h"
215118ebe8SLucas Mateus Castro (alqotel) #include "qemu/units.h"
225118ebe8SLucas Mateus Castro (alqotel) #include "cpu.h"
235118ebe8SLucas Mateus Castro (alqotel) #include "sysemu/kvm.h"
245118ebe8SLucas Mateus Castro (alqotel) #include "kvm_ppc.h"
255118ebe8SLucas Mateus Castro (alqotel) #include "mmu-hash64.h"
265118ebe8SLucas Mateus Castro (alqotel) #include "mmu-hash32.h"
275118ebe8SLucas Mateus Castro (alqotel) #include "exec/exec-all.h"
2874781c08SPhilippe Mathieu-Daudé #include "exec/page-protection.h"
295118ebe8SLucas Mateus Castro (alqotel) #include "exec/log.h"
305118ebe8SLucas Mateus Castro (alqotel) #include "helper_regs.h"
315118ebe8SLucas Mateus Castro (alqotel) #include "qemu/error-report.h"
325118ebe8SLucas Mateus Castro (alqotel) #include "qemu/qemu-print.h"
335118ebe8SLucas Mateus Castro (alqotel) #include "internal.h"
345118ebe8SLucas Mateus Castro (alqotel) #include "mmu-book3s-v3.h"
355118ebe8SLucas Mateus Castro (alqotel) #include "mmu-radix64.h"
36e7baac64SBALATON Zoltan #include "mmu-booke.h"
375118ebe8SLucas Mateus Castro (alqotel) 
385118ebe8SLucas Mateus Castro (alqotel) /* #define DUMP_PAGE_TABLES */
395118ebe8SLucas Mateus Castro (alqotel) 
40306b5320SBALATON Zoltan /* Context used internally during MMU translations */
41306b5320SBALATON Zoltan typedef struct {
42306b5320SBALATON Zoltan     hwaddr raddr;      /* Real address             */
43306b5320SBALATON Zoltan     int prot;          /* Protection bits          */
44306b5320SBALATON Zoltan     target_ulong ptem; /* Virtual segment ID | API */
45306b5320SBALATON Zoltan     int key;           /* Access key               */
46306b5320SBALATON Zoltan } mmu_ctx_t;
47306b5320SBALATON Zoltan 
48d6ae8ec6SLucas Mateus Castro (alqotel) void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
49d6ae8ec6SLucas Mateus Castro (alqotel) {
50d6ae8ec6SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = env_archcpu(env);
51d6ae8ec6SLucas Mateus Castro (alqotel)     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
52d6ae8ec6SLucas Mateus Castro (alqotel)     assert(!cpu->env.has_hv_mode || !cpu->vhyp);
53d6ae8ec6SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64)
54d6ae8ec6SLucas Mateus Castro (alqotel)     if (mmu_is_64bit(env->mmu_model)) {
55d6ae8ec6SLucas Mateus Castro (alqotel)         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
56d6ae8ec6SLucas Mateus Castro (alqotel)         target_ulong htabsize = value & SDR_64_HTABSIZE;
57d6ae8ec6SLucas Mateus Castro (alqotel) 
58d6ae8ec6SLucas Mateus Castro (alqotel)         if (value & ~sdr_mask) {
59d6ae8ec6SLucas Mateus Castro (alqotel)             qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
60d6ae8ec6SLucas Mateus Castro (alqotel)                      " set in SDR1", value & ~sdr_mask);
61d6ae8ec6SLucas Mateus Castro (alqotel)             value &= sdr_mask;
62d6ae8ec6SLucas Mateus Castro (alqotel)         }
63d6ae8ec6SLucas Mateus Castro (alqotel)         if (htabsize > 28) {
64d6ae8ec6SLucas Mateus Castro (alqotel)             qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
65d6ae8ec6SLucas Mateus Castro (alqotel)                      " stored in SDR1", htabsize);
66d6ae8ec6SLucas Mateus Castro (alqotel)             return;
67d6ae8ec6SLucas Mateus Castro (alqotel)         }
68d6ae8ec6SLucas Mateus Castro (alqotel)     }
69d6ae8ec6SLucas Mateus Castro (alqotel) #endif /* defined(TARGET_PPC64) */
70d6ae8ec6SLucas Mateus Castro (alqotel)     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
71d6ae8ec6SLucas Mateus Castro (alqotel)     env->spr[SPR_SDR1] = value;
72d6ae8ec6SLucas Mateus Castro (alqotel) }
73d6ae8ec6SLucas Mateus Castro (alqotel) 
745118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/
755118ebe8SLucas Mateus Castro (alqotel) /* PowerPC MMU emulation */
765118ebe8SLucas Mateus Castro (alqotel) 
775118ebe8SLucas Mateus Castro (alqotel) int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
785118ebe8SLucas Mateus Castro (alqotel)                                     int way, int is_code)
795118ebe8SLucas Mateus Castro (alqotel) {
805118ebe8SLucas Mateus Castro (alqotel)     int nr;
815118ebe8SLucas Mateus Castro (alqotel) 
825118ebe8SLucas Mateus Castro (alqotel)     /* Select TLB num in a way from address */
835118ebe8SLucas Mateus Castro (alqotel)     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
845118ebe8SLucas Mateus Castro (alqotel)     /* Select TLB way */
855118ebe8SLucas Mateus Castro (alqotel)     nr += env->tlb_per_way * way;
865fd257f5SBALATON Zoltan     /* 6xx has separate TLBs for instructions and data */
875fd257f5SBALATON Zoltan     if (is_code) {
885118ebe8SLucas Mateus Castro (alqotel)         nr += env->nb_tlb;
895118ebe8SLucas Mateus Castro (alqotel)     }
905118ebe8SLucas Mateus Castro (alqotel) 
915118ebe8SLucas Mateus Castro (alqotel)     return nr;
925118ebe8SLucas Mateus Castro (alqotel) }
935118ebe8SLucas Mateus Castro (alqotel) 
945118ebe8SLucas Mateus Castro (alqotel) static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
953208c36aSBALATON Zoltan                                 target_ulong pte1, int pteh,
96*691cf34fSBALATON Zoltan                                 MMUAccessType access_type, bool nx)
975118ebe8SLucas Mateus Castro (alqotel) {
985118ebe8SLucas Mateus Castro (alqotel)     /* Check validity and table match */
999e2d6802SBALATON Zoltan     if (!pte_is_valid(pte0) || ((pte0 >> 6) & 1) != pteh ||
1009e2d6802SBALATON Zoltan         (pte0 & PTE_PTEM_MASK) != ctx->ptem) {
1019e2d6802SBALATON Zoltan         return -1;
1029e2d6802SBALATON Zoltan     }
1035118ebe8SLucas Mateus Castro (alqotel)     /* all matches should have equal RPN, WIMG & PP */
1049e2d6802SBALATON Zoltan     if (ctx->raddr != (hwaddr)-1ULL &&
1059e2d6802SBALATON Zoltan         (ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
1065118ebe8SLucas Mateus Castro (alqotel)         qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
1075118ebe8SLucas Mateus Castro (alqotel)         return -3;
1085118ebe8SLucas Mateus Castro (alqotel)     }
1095118ebe8SLucas Mateus Castro (alqotel)     /* Keep the matching PTE information */
1105118ebe8SLucas Mateus Castro (alqotel)     ctx->raddr = pte1;
111*691cf34fSBALATON Zoltan     ctx->prot = ppc_hash32_prot(ctx->key, pte1 & HPTE32_R_PP, nx);
112cd1038ecSBALATON Zoltan     if (check_prot_access_type(ctx->prot, access_type)) {
1135118ebe8SLucas Mateus Castro (alqotel)         qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
1140e65cea1SBALATON Zoltan         return 0;
1155118ebe8SLucas Mateus Castro (alqotel)     } else {
1165118ebe8SLucas Mateus Castro (alqotel)         qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
1170e65cea1SBALATON Zoltan         return -2;
1185118ebe8SLucas Mateus Castro (alqotel)     }
1195118ebe8SLucas Mateus Castro (alqotel) }
1205118ebe8SLucas Mateus Castro (alqotel) 
1215118ebe8SLucas Mateus Castro (alqotel) /* Software driven TLB helpers */
1225118ebe8SLucas Mateus Castro (alqotel) 
123*691cf34fSBALATON Zoltan static int ppc6xx_tlb_check(CPUPPCState *env,
124*691cf34fSBALATON Zoltan                             mmu_ctx_t *ctx, target_ulong eaddr,
125*691cf34fSBALATON Zoltan                             MMUAccessType access_type, bool nx)
1265118ebe8SLucas Mateus Castro (alqotel) {
1275118ebe8SLucas Mateus Castro (alqotel)     ppc6xx_tlb_t *tlb;
128f8e0cc94SBALATON Zoltan     target_ulong *pte1p;
129f8e0cc94SBALATON Zoltan     int nr, best, way, ret;
1305118ebe8SLucas Mateus Castro (alqotel) 
1315118ebe8SLucas Mateus Castro (alqotel)     best = -1;
1325118ebe8SLucas Mateus Castro (alqotel)     ret = -1; /* No TLB found */
1335118ebe8SLucas Mateus Castro (alqotel)     for (way = 0; way < env->nb_ways; way++) {
1345118ebe8SLucas Mateus Castro (alqotel)         nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
1355118ebe8SLucas Mateus Castro (alqotel)         tlb = &env->tlb.tlb6[nr];
1365118ebe8SLucas Mateus Castro (alqotel)         /* This test "emulates" the PTE index match for hardware TLBs */
1375118ebe8SLucas Mateus Castro (alqotel)         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
13856964585SCédric Le Goater             qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx
13956964585SCédric Le Goater                           " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n",
14056964585SCédric Le Goater                           nr, env->nb_tlb,
1415118ebe8SLucas Mateus Castro (alqotel)                           pte_is_valid(tlb->pte0) ? "valid" : "inval",
1425118ebe8SLucas Mateus Castro (alqotel)                           tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
1435118ebe8SLucas Mateus Castro (alqotel)             continue;
1445118ebe8SLucas Mateus Castro (alqotel)         }
14556964585SCédric Le Goater         qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> "
14656964585SCédric Le Goater                       TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n",
14756964585SCédric Le Goater                       nr, env->nb_tlb,
1485118ebe8SLucas Mateus Castro (alqotel)                       pte_is_valid(tlb->pte0) ? "valid" : "inval",
1495118ebe8SLucas Mateus Castro (alqotel)                       tlb->EPN, eaddr, tlb->pte1,
1505118ebe8SLucas Mateus Castro (alqotel)                       access_type == MMU_DATA_STORE ? 'S' : 'L',
1515118ebe8SLucas Mateus Castro (alqotel)                       access_type == MMU_INST_FETCH ? 'I' : 'D');
1525118ebe8SLucas Mateus Castro (alqotel)         switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
153*691cf34fSBALATON Zoltan                                      0, access_type, nx)) {
1545118ebe8SLucas Mateus Castro (alqotel)         case -2:
1555118ebe8SLucas Mateus Castro (alqotel)             /* Access violation */
1565118ebe8SLucas Mateus Castro (alqotel)             ret = -2;
1575118ebe8SLucas Mateus Castro (alqotel)             best = nr;
1585118ebe8SLucas Mateus Castro (alqotel)             break;
1590af20f35SBALATON Zoltan         case -1: /* No match */
1600af20f35SBALATON Zoltan         case -3: /* TLB inconsistency */
1615118ebe8SLucas Mateus Castro (alqotel)         default:
1625118ebe8SLucas Mateus Castro (alqotel)             break;
1635118ebe8SLucas Mateus Castro (alqotel)         case 0:
1645118ebe8SLucas Mateus Castro (alqotel)             /* access granted */
1655118ebe8SLucas Mateus Castro (alqotel)             /*
1665118ebe8SLucas Mateus Castro (alqotel)              * XXX: we should go on looping to check all TLBs
1675118ebe8SLucas Mateus Castro (alqotel)              *      consistency but we can speed-up the whole thing as
1685118ebe8SLucas Mateus Castro (alqotel)              *      the result would be undefined if TLBs are not
1695118ebe8SLucas Mateus Castro (alqotel)              *      consistent.
1705118ebe8SLucas Mateus Castro (alqotel)              */
1715118ebe8SLucas Mateus Castro (alqotel)             ret = 0;
1725118ebe8SLucas Mateus Castro (alqotel)             best = nr;
1735118ebe8SLucas Mateus Castro (alqotel)             goto done;
1745118ebe8SLucas Mateus Castro (alqotel)         }
1755118ebe8SLucas Mateus Castro (alqotel)     }
1765118ebe8SLucas Mateus Castro (alqotel)     if (best != -1) {
1775118ebe8SLucas Mateus Castro (alqotel) done:
178883f2c59SPhilippe Mathieu-Daudé         qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
17956964585SCédric Le Goater                       " prot=%01x ret=%d\n",
1805118ebe8SLucas Mateus Castro (alqotel)                       ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
1815118ebe8SLucas Mateus Castro (alqotel)         /* Update page flags */
182f8e0cc94SBALATON Zoltan         pte1p = &env->tlb.tlb6[best].pte1;
183f8e0cc94SBALATON Zoltan         *pte1p |= 0x00000100; /* Update accessed flag */
184f8e0cc94SBALATON Zoltan         if (!(*pte1p & 0x00000080)) {
185f8e0cc94SBALATON Zoltan             if (access_type == MMU_DATA_STORE && ret == 0) {
186f8e0cc94SBALATON Zoltan                 /* Update changed flag */
187f8e0cc94SBALATON Zoltan                 *pte1p |= 0x00000080;
188f8e0cc94SBALATON Zoltan             } else {
189f8e0cc94SBALATON Zoltan                 /* Force page fault for first write access */
190f8e0cc94SBALATON Zoltan                 ctx->prot &= ~PAGE_WRITE;
191f8e0cc94SBALATON Zoltan             }
192f8e0cc94SBALATON Zoltan         }
1935118ebe8SLucas Mateus Castro (alqotel)     }
1940af20f35SBALATON Zoltan #if defined(DUMP_PAGE_TABLES)
1950af20f35SBALATON Zoltan     if (qemu_loglevel_mask(CPU_LOG_MMU)) {
1960af20f35SBALATON Zoltan         CPUState *cs = env_cpu(env);
1970af20f35SBALATON Zoltan         hwaddr base = ppc_hash32_hpt_base(env_archcpu(env));
1980af20f35SBALATON Zoltan         hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80;
1990af20f35SBALATON Zoltan         uint32_t a0, a1, a2, a3;
2005118ebe8SLucas Mateus Castro (alqotel) 
2010af20f35SBALATON Zoltan         qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
2020af20f35SBALATON Zoltan                  base, len);
2030af20f35SBALATON Zoltan         for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) {
2040af20f35SBALATON Zoltan             a0 = ldl_phys(cs->as, curaddr);
2050af20f35SBALATON Zoltan             a1 = ldl_phys(cs->as, curaddr + 4);
2060af20f35SBALATON Zoltan             a2 = ldl_phys(cs->as, curaddr + 8);
2070af20f35SBALATON Zoltan             a3 = ldl_phys(cs->as, curaddr + 12);
2080af20f35SBALATON Zoltan             if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
2090af20f35SBALATON Zoltan                 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
2100af20f35SBALATON Zoltan                          curaddr, a0, a1, a2, a3);
2110af20f35SBALATON Zoltan             }
2120af20f35SBALATON Zoltan         }
2130af20f35SBALATON Zoltan     }
2140af20f35SBALATON Zoltan #endif
2155118ebe8SLucas Mateus Castro (alqotel)     return ret;
2165118ebe8SLucas Mateus Castro (alqotel) }
2175118ebe8SLucas Mateus Castro (alqotel) 
2185118ebe8SLucas Mateus Castro (alqotel) /* Perform BAT hit & translation */
2195118ebe8SLucas Mateus Castro (alqotel) static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
2205118ebe8SLucas Mateus Castro (alqotel)                                  int *validp, int *protp, target_ulong *BATu,
2215118ebe8SLucas Mateus Castro (alqotel)                                  target_ulong *BATl)
2225118ebe8SLucas Mateus Castro (alqotel) {
2235118ebe8SLucas Mateus Castro (alqotel)     target_ulong bl;
2245118ebe8SLucas Mateus Castro (alqotel)     int pp, valid, prot;
2255118ebe8SLucas Mateus Castro (alqotel) 
2265118ebe8SLucas Mateus Castro (alqotel)     bl = (*BATu & 0x00001FFC) << 15;
2275118ebe8SLucas Mateus Castro (alqotel)     valid = 0;
2285118ebe8SLucas Mateus Castro (alqotel)     prot = 0;
229d41ccf6eSVíctor Colombo     if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) ||
230d41ccf6eSVíctor Colombo         (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) {
2315118ebe8SLucas Mateus Castro (alqotel)         valid = 1;
2325118ebe8SLucas Mateus Castro (alqotel)         pp = *BATl & 0x00000003;
2335118ebe8SLucas Mateus Castro (alqotel)         if (pp != 0) {
2345118ebe8SLucas Mateus Castro (alqotel)             prot = PAGE_READ | PAGE_EXEC;
2355118ebe8SLucas Mateus Castro (alqotel)             if (pp == 0x2) {
2365118ebe8SLucas Mateus Castro (alqotel)                 prot |= PAGE_WRITE;
2375118ebe8SLucas Mateus Castro (alqotel)             }
2385118ebe8SLucas Mateus Castro (alqotel)         }
2395118ebe8SLucas Mateus Castro (alqotel)     }
2405118ebe8SLucas Mateus Castro (alqotel)     *blp = bl;
2415118ebe8SLucas Mateus Castro (alqotel)     *validp = valid;
2425118ebe8SLucas Mateus Castro (alqotel)     *protp = prot;
2435118ebe8SLucas Mateus Castro (alqotel) }
2445118ebe8SLucas Mateus Castro (alqotel) 
2455118ebe8SLucas Mateus Castro (alqotel) static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
2465118ebe8SLucas Mateus Castro (alqotel)                            target_ulong virtual, MMUAccessType access_type)
2475118ebe8SLucas Mateus Castro (alqotel) {
2485118ebe8SLucas Mateus Castro (alqotel)     target_ulong *BATlt, *BATut, *BATu, *BATl;
2495118ebe8SLucas Mateus Castro (alqotel)     target_ulong BEPIl, BEPIu, bl;
2505118ebe8SLucas Mateus Castro (alqotel)     int i, valid, prot;
2515118ebe8SLucas Mateus Castro (alqotel)     int ret = -1;
2525118ebe8SLucas Mateus Castro (alqotel)     bool ifetch = access_type == MMU_INST_FETCH;
2535118ebe8SLucas Mateus Castro (alqotel) 
25456964585SCédric Le Goater     qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
2555118ebe8SLucas Mateus Castro (alqotel)                   ifetch ? 'I' : 'D', virtual);
2565118ebe8SLucas Mateus Castro (alqotel)     if (ifetch) {
2575118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->IBAT[1];
2585118ebe8SLucas Mateus Castro (alqotel)         BATut = env->IBAT[0];
2595118ebe8SLucas Mateus Castro (alqotel)     } else {
2605118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->DBAT[1];
2615118ebe8SLucas Mateus Castro (alqotel)         BATut = env->DBAT[0];
2625118ebe8SLucas Mateus Castro (alqotel)     }
2635118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < env->nb_BATs; i++) {
2645118ebe8SLucas Mateus Castro (alqotel)         BATu = &BATut[i];
2655118ebe8SLucas Mateus Castro (alqotel)         BATl = &BATlt[i];
2665118ebe8SLucas Mateus Castro (alqotel)         BEPIu = *BATu & 0xF0000000;
2675118ebe8SLucas Mateus Castro (alqotel)         BEPIl = *BATu & 0x0FFE0000;
2685118ebe8SLucas Mateus Castro (alqotel)         bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
26956964585SCédric Le Goater         qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
27056964585SCédric Le Goater                       TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
2715118ebe8SLucas Mateus Castro (alqotel)                       ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
2725118ebe8SLucas Mateus Castro (alqotel)         if ((virtual & 0xF0000000) == BEPIu &&
2735118ebe8SLucas Mateus Castro (alqotel)             ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
2745118ebe8SLucas Mateus Castro (alqotel)             /* BAT matches */
2755118ebe8SLucas Mateus Castro (alqotel)             if (valid != 0) {
2765118ebe8SLucas Mateus Castro (alqotel)                 /* Get physical address */
2775118ebe8SLucas Mateus Castro (alqotel)                 ctx->raddr = (*BATl & 0xF0000000) |
2785118ebe8SLucas Mateus Castro (alqotel)                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
2795118ebe8SLucas Mateus Castro (alqotel)                     (virtual & 0x0001F000);
2805118ebe8SLucas Mateus Castro (alqotel)                 /* Compute access rights */
2815118ebe8SLucas Mateus Castro (alqotel)                 ctx->prot = prot;
282cd1038ecSBALATON Zoltan                 if (check_prot_access_type(ctx->prot, access_type)) {
283883f2c59SPhilippe Mathieu-Daudé                     qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx
28456964585SCédric Le Goater                                   " prot=%c%c\n", i, ctx->raddr,
28556964585SCédric Le Goater                                   ctx->prot & PAGE_READ ? 'R' : '-',
2865118ebe8SLucas Mateus Castro (alqotel)                                   ctx->prot & PAGE_WRITE ? 'W' : '-');
287cd1038ecSBALATON Zoltan                     ret = 0;
288cd1038ecSBALATON Zoltan                 } else {
289cd1038ecSBALATON Zoltan                     ret = -2;
2905118ebe8SLucas Mateus Castro (alqotel)                 }
2915118ebe8SLucas Mateus Castro (alqotel)                 break;
2925118ebe8SLucas Mateus Castro (alqotel)             }
2935118ebe8SLucas Mateus Castro (alqotel)         }
2945118ebe8SLucas Mateus Castro (alqotel)     }
2955118ebe8SLucas Mateus Castro (alqotel)     if (ret < 0) {
2965118ebe8SLucas Mateus Castro (alqotel)         if (qemu_log_enabled()) {
29756964585SCédric Le Goater             qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
29856964585SCédric Le Goater                           TARGET_FMT_lx ":\n", virtual);
2995118ebe8SLucas Mateus Castro (alqotel)             for (i = 0; i < 4; i++) {
3005118ebe8SLucas Mateus Castro (alqotel)                 BATu = &BATut[i];
3015118ebe8SLucas Mateus Castro (alqotel)                 BATl = &BATlt[i];
3025118ebe8SLucas Mateus Castro (alqotel)                 BEPIu = *BATu & 0xF0000000;
3035118ebe8SLucas Mateus Castro (alqotel)                 BEPIl = *BATu & 0x0FFE0000;
3045118ebe8SLucas Mateus Castro (alqotel)                 bl = (*BATu & 0x00001FFC) << 15;
30547bededcSBALATON Zoltan                 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
30647bededcSBALATON Zoltan                               " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
30747bededcSBALATON Zoltan                               "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
30847bededcSBALATON Zoltan                               TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
30947bededcSBALATON Zoltan                               i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl);
3105118ebe8SLucas Mateus Castro (alqotel)             }
3115118ebe8SLucas Mateus Castro (alqotel)         }
3125118ebe8SLucas Mateus Castro (alqotel)     }
3135118ebe8SLucas Mateus Castro (alqotel)     /* No hit */
3145118ebe8SLucas Mateus Castro (alqotel)     return ret;
3155118ebe8SLucas Mateus Castro (alqotel) }
3165118ebe8SLucas Mateus Castro (alqotel) 
317269d6f00SBALATON Zoltan static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
318f6f8838bSBALATON Zoltan                                        target_ulong eaddr, hwaddr *hashp,
319269d6f00SBALATON Zoltan                                        MMUAccessType access_type, int type)
3205118ebe8SLucas Mateus Castro (alqotel) {
3215118ebe8SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = env_archcpu(env);
3225118ebe8SLucas Mateus Castro (alqotel)     hwaddr hash;
323269d6f00SBALATON Zoltan     target_ulong vsid, sr, pgidx;
324d41ccf6eSVíctor Colombo     int ds, target_page_bits;
325*691cf34fSBALATON Zoltan     bool pr, nx;
3265118ebe8SLucas Mateus Castro (alqotel) 
327269d6f00SBALATON Zoltan     /* First try to find a BAT entry if there are any */
328269d6f00SBALATON Zoltan     if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) {
329269d6f00SBALATON Zoltan         return 0;
330269d6f00SBALATON Zoltan     }
331269d6f00SBALATON Zoltan 
332269d6f00SBALATON Zoltan     /* Perform segment based translation when no BATs matched */
333d41ccf6eSVíctor Colombo     pr = FIELD_EX64(env->msr, MSR, PR);
3345118ebe8SLucas Mateus Castro (alqotel) 
3355118ebe8SLucas Mateus Castro (alqotel)     sr = env->sr[eaddr >> 28];
336d41ccf6eSVíctor Colombo     ctx->key = (((sr & 0x20000000) && pr) ||
337d41ccf6eSVíctor Colombo                 ((sr & 0x40000000) && !pr)) ? 1 : 0;
3385118ebe8SLucas Mateus Castro (alqotel)     ds = sr & 0x80000000 ? 1 : 0;
339*691cf34fSBALATON Zoltan     nx = sr & SR32_NX;
340*691cf34fSBALATON Zoltan     vsid = sr & SR32_VSID;
3415118ebe8SLucas Mateus Castro (alqotel)     target_page_bits = TARGET_PAGE_BITS;
3425118ebe8SLucas Mateus Castro (alqotel)     qemu_log_mask(CPU_LOG_MMU,
3435118ebe8SLucas Mateus Castro (alqotel)                   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
3445118ebe8SLucas Mateus Castro (alqotel)                   " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
3455118ebe8SLucas Mateus Castro (alqotel)                   " ir=%d dr=%d pr=%d %d t=%d\n",
346d41ccf6eSVíctor Colombo                   eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr,
347e4eea6efSVíctor Colombo                   (int)FIELD_EX64(env->msr, MSR, IR),
348e4eea6efSVíctor Colombo                   (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
34956964585SCédric Le Goater                   access_type == MMU_DATA_STORE, type);
3505118ebe8SLucas Mateus Castro (alqotel)     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
3515118ebe8SLucas Mateus Castro (alqotel)     hash = vsid ^ pgidx;
3525118ebe8SLucas Mateus Castro (alqotel)     ctx->ptem = (vsid << 7) | (pgidx >> 10);
3535118ebe8SLucas Mateus Castro (alqotel) 
35447bededcSBALATON Zoltan     qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
355*691cf34fSBALATON Zoltan                   TARGET_FMT_lx "\n", ctx->key, ds, nx, vsid);
3565118ebe8SLucas Mateus Castro (alqotel)     if (!ds) {
3575118ebe8SLucas Mateus Castro (alqotel)         /* Check if instruction fetch is allowed, if needed */
358*691cf34fSBALATON Zoltan         if (type == ACCESS_CODE && nx) {
359f1418bdeSBALATON Zoltan             qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
360f1418bdeSBALATON Zoltan             return -3;
361f1418bdeSBALATON Zoltan         }
3625118ebe8SLucas Mateus Castro (alqotel)         /* Page address translation */
363f1418bdeSBALATON Zoltan         qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
364f1418bdeSBALATON Zoltan                       HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
3655118ebe8SLucas Mateus Castro (alqotel)                       ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
366f6f8838bSBALATON Zoltan         *hashp = hash;
3675118ebe8SLucas Mateus Castro (alqotel) 
3685118ebe8SLucas Mateus Castro (alqotel)         /* Initialize real address with an invalid value */
3695118ebe8SLucas Mateus Castro (alqotel)         ctx->raddr = (hwaddr)-1ULL;
3705118ebe8SLucas Mateus Castro (alqotel)         /* Software TLB search */
371*691cf34fSBALATON Zoltan         return ppc6xx_tlb_check(env, ctx, eaddr, access_type, nx);
372f3f66a31SBALATON Zoltan     }
3735118ebe8SLucas Mateus Castro (alqotel) 
374f3f66a31SBALATON Zoltan     /* Direct-store segment : absolutely *BUGGY* for now */
375f3f66a31SBALATON Zoltan     qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
3765118ebe8SLucas Mateus Castro (alqotel)     switch (type) {
3775118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_INT:
3785118ebe8SLucas Mateus Castro (alqotel)         /* Integer load/store : only access allowed */
3795118ebe8SLucas Mateus Castro (alqotel)         break;
3805118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_CODE:
3815118ebe8SLucas Mateus Castro (alqotel)         /* No code fetch is allowed in direct-store areas */
3825118ebe8SLucas Mateus Castro (alqotel)         return -4;
3835118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_FLOAT:
3845118ebe8SLucas Mateus Castro (alqotel)         /* Floating point load/store */
3855118ebe8SLucas Mateus Castro (alqotel)         return -4;
3865118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_RES:
3875118ebe8SLucas Mateus Castro (alqotel)         /* lwarx, ldarx or srwcx. */
3885118ebe8SLucas Mateus Castro (alqotel)         return -4;
3895118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_CACHE:
3905118ebe8SLucas Mateus Castro (alqotel)         /*
3915118ebe8SLucas Mateus Castro (alqotel)          * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
3925118ebe8SLucas Mateus Castro (alqotel)          *
3935118ebe8SLucas Mateus Castro (alqotel)          * Should make the instruction do no-op.  As it already do
3945118ebe8SLucas Mateus Castro (alqotel)          * no-op, it's quite easy :-)
3955118ebe8SLucas Mateus Castro (alqotel)          */
3965118ebe8SLucas Mateus Castro (alqotel)         ctx->raddr = eaddr;
3975118ebe8SLucas Mateus Castro (alqotel)         return 0;
3985118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_EXT:
3995118ebe8SLucas Mateus Castro (alqotel)         /* eciwx or ecowx */
4005118ebe8SLucas Mateus Castro (alqotel)         return -4;
4015118ebe8SLucas Mateus Castro (alqotel)     default:
402f3f66a31SBALATON Zoltan         qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need address"
403f3f66a31SBALATON Zoltan                                    " translation\n");
4045118ebe8SLucas Mateus Castro (alqotel)         return -4;
4055118ebe8SLucas Mateus Castro (alqotel)     }
4065118ebe8SLucas Mateus Castro (alqotel)     if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
4075118ebe8SLucas Mateus Castro (alqotel)         (access_type == MMU_DATA_LOAD || ctx->key != 0)) {
4085118ebe8SLucas Mateus Castro (alqotel)         ctx->raddr = eaddr;
409f3f66a31SBALATON Zoltan         return 2;
4105118ebe8SLucas Mateus Castro (alqotel)     }
411f3f66a31SBALATON Zoltan     return -2;
4125118ebe8SLucas Mateus Castro (alqotel) }
4135118ebe8SLucas Mateus Castro (alqotel) 
4145118ebe8SLucas Mateus Castro (alqotel) static const char *book3e_tsize_to_str[32] = {
4155118ebe8SLucas Mateus Castro (alqotel)     "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
4165118ebe8SLucas Mateus Castro (alqotel)     "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
4175118ebe8SLucas Mateus Castro (alqotel)     "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
4185118ebe8SLucas Mateus Castro (alqotel)     "1T", "2T"
4195118ebe8SLucas Mateus Castro (alqotel) };
4205118ebe8SLucas Mateus Castro (alqotel) 
4215118ebe8SLucas Mateus Castro (alqotel) static void mmubooke_dump_mmu(CPUPPCState *env)
4225118ebe8SLucas Mateus Castro (alqotel) {
4235118ebe8SLucas Mateus Castro (alqotel)     ppcemb_tlb_t *entry;
4245118ebe8SLucas Mateus Castro (alqotel)     int i;
4255118ebe8SLucas Mateus Castro (alqotel) 
42605739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM
4275118ebe8SLucas Mateus Castro (alqotel)     if (kvm_enabled() && !env->kvm_sw_tlb) {
4285118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("Cannot access KVM TLB\n");
4295118ebe8SLucas Mateus Castro (alqotel)         return;
4305118ebe8SLucas Mateus Castro (alqotel)     }
43105739977SPhilippe Mathieu-Daudé #endif
4325118ebe8SLucas Mateus Castro (alqotel) 
4335118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nTLB:\n");
4345118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("Effective          Physical           Size PID   Prot     "
4355118ebe8SLucas Mateus Castro (alqotel)                 "Attr\n");
4365118ebe8SLucas Mateus Castro (alqotel) 
4375118ebe8SLucas Mateus Castro (alqotel)     entry = &env->tlb.tlbe[0];
4385118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < env->nb_tlb; i++, entry++) {
4395118ebe8SLucas Mateus Castro (alqotel)         hwaddr ea, pa;
4405118ebe8SLucas Mateus Castro (alqotel)         target_ulong mask;
4415118ebe8SLucas Mateus Castro (alqotel)         uint64_t size = (uint64_t)entry->size;
4425118ebe8SLucas Mateus Castro (alqotel)         char size_buf[20];
4435118ebe8SLucas Mateus Castro (alqotel) 
4445118ebe8SLucas Mateus Castro (alqotel)         /* Check valid flag */
4455118ebe8SLucas Mateus Castro (alqotel)         if (!(entry->prot & PAGE_VALID)) {
4465118ebe8SLucas Mateus Castro (alqotel)             continue;
4475118ebe8SLucas Mateus Castro (alqotel)         }
4485118ebe8SLucas Mateus Castro (alqotel) 
4495118ebe8SLucas Mateus Castro (alqotel)         mask = ~(entry->size - 1);
4505118ebe8SLucas Mateus Castro (alqotel)         ea = entry->EPN & mask;
4515118ebe8SLucas Mateus Castro (alqotel)         pa = entry->RPN & mask;
4525118ebe8SLucas Mateus Castro (alqotel)         /* Extend the physical address to 36 bits */
4535118ebe8SLucas Mateus Castro (alqotel)         pa |= (hwaddr)(entry->RPN & 0xF) << 32;
4545118ebe8SLucas Mateus Castro (alqotel)         if (size >= 1 * MiB) {
4555118ebe8SLucas Mateus Castro (alqotel)             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
4565118ebe8SLucas Mateus Castro (alqotel)         } else {
4575118ebe8SLucas Mateus Castro (alqotel)             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
4585118ebe8SLucas Mateus Castro (alqotel)         }
4595118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
4605118ebe8SLucas Mateus Castro (alqotel)                     (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
4615118ebe8SLucas Mateus Castro (alqotel)                     entry->prot, entry->attr);
4625118ebe8SLucas Mateus Castro (alqotel)     }
4635118ebe8SLucas Mateus Castro (alqotel) 
4645118ebe8SLucas Mateus Castro (alqotel) }
4655118ebe8SLucas Mateus Castro (alqotel) 
4665118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
4675118ebe8SLucas Mateus Castro (alqotel)                                      int tlbsize)
4685118ebe8SLucas Mateus Castro (alqotel) {
4695118ebe8SLucas Mateus Castro (alqotel)     ppcmas_tlb_t *entry;
4705118ebe8SLucas Mateus Castro (alqotel)     int i;
4715118ebe8SLucas Mateus Castro (alqotel) 
4725118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nTLB%d:\n", tlbn);
4735118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("Effective          Physical           Size TID   TS SRWX"
4745118ebe8SLucas Mateus Castro (alqotel)                 " URWX WIMGE U0123\n");
4755118ebe8SLucas Mateus Castro (alqotel) 
4765118ebe8SLucas Mateus Castro (alqotel)     entry = &env->tlb.tlbm[offset];
4775118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < tlbsize; i++, entry++) {
4785118ebe8SLucas Mateus Castro (alqotel)         hwaddr ea, pa, size;
4795118ebe8SLucas Mateus Castro (alqotel)         int tsize;
4805118ebe8SLucas Mateus Castro (alqotel) 
4815118ebe8SLucas Mateus Castro (alqotel)         if (!(entry->mas1 & MAS1_VALID)) {
4825118ebe8SLucas Mateus Castro (alqotel)             continue;
4835118ebe8SLucas Mateus Castro (alqotel)         }
4845118ebe8SLucas Mateus Castro (alqotel) 
4855118ebe8SLucas Mateus Castro (alqotel)         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
4865118ebe8SLucas Mateus Castro (alqotel)         size = 1024ULL << tsize;
4875118ebe8SLucas Mateus Castro (alqotel)         ea = entry->mas2 & ~(size - 1);
4885118ebe8SLucas Mateus Castro (alqotel)         pa = entry->mas7_3 & ~(size - 1);
4895118ebe8SLucas Mateus Castro (alqotel) 
4905118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
4915118ebe8SLucas Mateus Castro (alqotel)                     " U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
4925118ebe8SLucas Mateus Castro (alqotel)                     (uint64_t)ea, (uint64_t)pa,
4935118ebe8SLucas Mateus Castro (alqotel)                     book3e_tsize_to_str[tsize],
4945118ebe8SLucas Mateus Castro (alqotel)                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
4955118ebe8SLucas Mateus Castro (alqotel)                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
4965118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
4975118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
4985118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
4995118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
5005118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
5015118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
5025118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_W ? 'W' : '-',
5035118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_I ? 'I' : '-',
5045118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_M ? 'M' : '-',
5055118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_G ? 'G' : '-',
5065118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_E ? 'E' : '-',
5075118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
5085118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
5095118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
5105118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
5115118ebe8SLucas Mateus Castro (alqotel)     }
5125118ebe8SLucas Mateus Castro (alqotel) }
5135118ebe8SLucas Mateus Castro (alqotel) 
5145118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_mmu(CPUPPCState *env)
5155118ebe8SLucas Mateus Castro (alqotel) {
5165118ebe8SLucas Mateus Castro (alqotel)     int offset = 0;
5175118ebe8SLucas Mateus Castro (alqotel)     int i;
5185118ebe8SLucas Mateus Castro (alqotel) 
51905739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM
5205118ebe8SLucas Mateus Castro (alqotel)     if (kvm_enabled() && !env->kvm_sw_tlb) {
5215118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("Cannot access KVM TLB\n");
5225118ebe8SLucas Mateus Castro (alqotel)         return;
5235118ebe8SLucas Mateus Castro (alqotel)     }
52405739977SPhilippe Mathieu-Daudé #endif
5255118ebe8SLucas Mateus Castro (alqotel) 
5265118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
5275118ebe8SLucas Mateus Castro (alqotel)         int size = booke206_tlb_size(env, i);
5285118ebe8SLucas Mateus Castro (alqotel) 
5295118ebe8SLucas Mateus Castro (alqotel)         if (size == 0) {
5305118ebe8SLucas Mateus Castro (alqotel)             continue;
5315118ebe8SLucas Mateus Castro (alqotel)         }
5325118ebe8SLucas Mateus Castro (alqotel) 
5335118ebe8SLucas Mateus Castro (alqotel)         mmubooke206_dump_one_tlb(env, i, offset, size);
5345118ebe8SLucas Mateus Castro (alqotel)         offset += size;
5355118ebe8SLucas Mateus Castro (alqotel)     }
5365118ebe8SLucas Mateus Castro (alqotel) }
5375118ebe8SLucas Mateus Castro (alqotel) 
5385118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
5395118ebe8SLucas Mateus Castro (alqotel) {
5405118ebe8SLucas Mateus Castro (alqotel)     target_ulong *BATlt, *BATut, *BATu, *BATl;
5415118ebe8SLucas Mateus Castro (alqotel)     target_ulong BEPIl, BEPIu, bl;
5425118ebe8SLucas Mateus Castro (alqotel)     int i;
5435118ebe8SLucas Mateus Castro (alqotel) 
5445118ebe8SLucas Mateus Castro (alqotel)     switch (type) {
5455118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_CODE:
5465118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->IBAT[1];
5475118ebe8SLucas Mateus Castro (alqotel)         BATut = env->IBAT[0];
5485118ebe8SLucas Mateus Castro (alqotel)         break;
5495118ebe8SLucas Mateus Castro (alqotel)     default:
5505118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->DBAT[1];
5515118ebe8SLucas Mateus Castro (alqotel)         BATut = env->DBAT[0];
5525118ebe8SLucas Mateus Castro (alqotel)         break;
5535118ebe8SLucas Mateus Castro (alqotel)     }
5545118ebe8SLucas Mateus Castro (alqotel) 
5555118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < env->nb_BATs; i++) {
5565118ebe8SLucas Mateus Castro (alqotel)         BATu = &BATut[i];
5575118ebe8SLucas Mateus Castro (alqotel)         BATl = &BATlt[i];
5585118ebe8SLucas Mateus Castro (alqotel)         BEPIu = *BATu & 0xF0000000;
5595118ebe8SLucas Mateus Castro (alqotel)         BEPIl = *BATu & 0x0FFE0000;
5605118ebe8SLucas Mateus Castro (alqotel)         bl = (*BATu & 0x00001FFC) << 15;
5615118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
5625118ebe8SLucas Mateus Castro (alqotel)                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
5635118ebe8SLucas Mateus Castro (alqotel)                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
5645118ebe8SLucas Mateus Castro (alqotel)                     type == ACCESS_CODE ? "code" : "data", i,
5655118ebe8SLucas Mateus Castro (alqotel)                     *BATu, *BATl, BEPIu, BEPIl, bl);
5665118ebe8SLucas Mateus Castro (alqotel)     }
5675118ebe8SLucas Mateus Castro (alqotel) }
5685118ebe8SLucas Mateus Castro (alqotel) 
5695118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_mmu(CPUPPCState *env)
5705118ebe8SLucas Mateus Castro (alqotel) {
5715118ebe8SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = env_archcpu(env);
5725118ebe8SLucas Mateus Castro (alqotel)     ppc6xx_tlb_t *tlb;
5735118ebe8SLucas Mateus Castro (alqotel)     target_ulong sr;
5745118ebe8SLucas Mateus Castro (alqotel)     int type, way, entry, i;
5755118ebe8SLucas Mateus Castro (alqotel) 
5765118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
5775118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
5785118ebe8SLucas Mateus Castro (alqotel) 
5795118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nSegment registers:\n");
5805118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < 32; i++) {
5815118ebe8SLucas Mateus Castro (alqotel)         sr = env->sr[i];
5825118ebe8SLucas Mateus Castro (alqotel)         if (sr & 0x80000000) {
5835118ebe8SLucas Mateus Castro (alqotel)             qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
5845118ebe8SLucas Mateus Castro (alqotel)                         "CNTLR_SPEC=0x%05x\n", i,
5855118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
5865118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
5875118ebe8SLucas Mateus Castro (alqotel)                         (uint32_t)(sr & 0xFFFFF));
5885118ebe8SLucas Mateus Castro (alqotel)         } else {
5895118ebe8SLucas Mateus Castro (alqotel)             qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
5905118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
5915118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
5925118ebe8SLucas Mateus Castro (alqotel)                         (uint32_t)(sr & 0x00FFFFFF));
5935118ebe8SLucas Mateus Castro (alqotel)         }
5945118ebe8SLucas Mateus Castro (alqotel)     }
5955118ebe8SLucas Mateus Castro (alqotel) 
5965118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nBATs:\n");
5975118ebe8SLucas Mateus Castro (alqotel)     mmu6xx_dump_BATs(env, ACCESS_INT);
5985118ebe8SLucas Mateus Castro (alqotel)     mmu6xx_dump_BATs(env, ACCESS_CODE);
5995118ebe8SLucas Mateus Castro (alqotel) 
6005118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
6015118ebe8SLucas Mateus Castro (alqotel)     for (type = 0; type < 2; type++) {
6025118ebe8SLucas Mateus Castro (alqotel)         for (way = 0; way < env->nb_ways; way++) {
6035118ebe8SLucas Mateus Castro (alqotel)             for (entry = env->nb_tlb * type + env->tlb_per_way * way;
6045118ebe8SLucas Mateus Castro (alqotel)                  entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
6055118ebe8SLucas Mateus Castro (alqotel)                  entry++) {
6065118ebe8SLucas Mateus Castro (alqotel) 
6075118ebe8SLucas Mateus Castro (alqotel)                 tlb = &env->tlb.tlb6[entry];
6085118ebe8SLucas Mateus Castro (alqotel)                 qemu_printf("%s TLB %02d/%02d way:%d %s ["
6095118ebe8SLucas Mateus Castro (alqotel)                             TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
6105118ebe8SLucas Mateus Castro (alqotel)                             type ? "code" : "data", entry % env->nb_tlb,
6115118ebe8SLucas Mateus Castro (alqotel)                             env->nb_tlb, way,
6125118ebe8SLucas Mateus Castro (alqotel)                             pte_is_valid(tlb->pte0) ? "valid" : "inval",
6135118ebe8SLucas Mateus Castro (alqotel)                             tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
6145118ebe8SLucas Mateus Castro (alqotel)             }
6155118ebe8SLucas Mateus Castro (alqotel)         }
6165118ebe8SLucas Mateus Castro (alqotel)     }
6175118ebe8SLucas Mateus Castro (alqotel) }
6185118ebe8SLucas Mateus Castro (alqotel) 
6195118ebe8SLucas Mateus Castro (alqotel) void dump_mmu(CPUPPCState *env)
6205118ebe8SLucas Mateus Castro (alqotel) {
6215118ebe8SLucas Mateus Castro (alqotel)     switch (env->mmu_model) {
6225118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_BOOKE:
6235118ebe8SLucas Mateus Castro (alqotel)         mmubooke_dump_mmu(env);
6245118ebe8SLucas Mateus Castro (alqotel)         break;
6255118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_BOOKE206:
6265118ebe8SLucas Mateus Castro (alqotel)         mmubooke206_dump_mmu(env);
6275118ebe8SLucas Mateus Castro (alqotel)         break;
6285118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_SOFT_6xx:
6295118ebe8SLucas Mateus Castro (alqotel)         mmu6xx_dump_mmu(env);
6305118ebe8SLucas Mateus Castro (alqotel)         break;
6315118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64)
6325118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_64B:
6335118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_03:
6345118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_06:
6355118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_07:
6365118ebe8SLucas Mateus Castro (alqotel)         dump_slb(env_archcpu(env));
6375118ebe8SLucas Mateus Castro (alqotel)         break;
6385118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_3_00:
6395118ebe8SLucas Mateus Castro (alqotel)         if (ppc64_v3_radix(env_archcpu(env))) {
6405118ebe8SLucas Mateus Castro (alqotel)             qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
6415118ebe8SLucas Mateus Castro (alqotel)                           __func__);
6425118ebe8SLucas Mateus Castro (alqotel)         } else {
6435118ebe8SLucas Mateus Castro (alqotel)             dump_slb(env_archcpu(env));
6445118ebe8SLucas Mateus Castro (alqotel)         }
6455118ebe8SLucas Mateus Castro (alqotel)         break;
6465118ebe8SLucas Mateus Castro (alqotel) #endif
6475118ebe8SLucas Mateus Castro (alqotel)     default:
6485118ebe8SLucas Mateus Castro (alqotel)         qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
6495118ebe8SLucas Mateus Castro (alqotel)     }
6505118ebe8SLucas Mateus Castro (alqotel) }
6515118ebe8SLucas Mateus Castro (alqotel) 
652ba91e5d0SBALATON Zoltan 
653c29f808aSBALATON Zoltan static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr,
654c29f808aSBALATON Zoltan                                 MMUAccessType access_type,
655c29f808aSBALATON Zoltan                                 hwaddr *raddrp, int *psizep, int *protp)
656c29f808aSBALATON Zoltan {
657c29f808aSBALATON Zoltan     CPUPPCState *env = &cpu->env;
658c29f808aSBALATON Zoltan 
659c29f808aSBALATON Zoltan     if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR)
660c29f808aSBALATON Zoltan                                       : !FIELD_EX64(env->msr, MSR, DR)) {
661c29f808aSBALATON Zoltan         *raddrp = eaddr;
662c29f808aSBALATON Zoltan         *protp = PAGE_RWX;
663c29f808aSBALATON Zoltan         *psizep = TARGET_PAGE_BITS;
664c29f808aSBALATON Zoltan         return true;
665c29f808aSBALATON Zoltan     } else if (env->mmu_model == POWERPC_MMU_REAL) {
666c29f808aSBALATON Zoltan         cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n");
667c29f808aSBALATON Zoltan     }
668c29f808aSBALATON Zoltan     return false;
669c29f808aSBALATON Zoltan }
670c29f808aSBALATON Zoltan 
67158b01325SBALATON Zoltan static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
67258b01325SBALATON Zoltan                           MMUAccessType access_type,
67358b01325SBALATON Zoltan                           hwaddr *raddrp, int *psizep, int *protp,
67458b01325SBALATON Zoltan                           int mmu_idx, bool guest_visible)
67558b01325SBALATON Zoltan {
67658b01325SBALATON Zoltan     CPUState *cs = CPU(cpu);
67758b01325SBALATON Zoltan     CPUPPCState *env = &cpu->env;
67858b01325SBALATON Zoltan     int ret;
67958b01325SBALATON Zoltan 
68058b01325SBALATON Zoltan     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
68158b01325SBALATON Zoltan         return true;
68258b01325SBALATON Zoltan     }
68358b01325SBALATON Zoltan 
68458b01325SBALATON Zoltan     ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type);
68558b01325SBALATON Zoltan     if (ret == 0) {
68658b01325SBALATON Zoltan         *psizep = TARGET_PAGE_BITS;
68758b01325SBALATON Zoltan         return true;
68858b01325SBALATON Zoltan     } else if (!guest_visible) {
68958b01325SBALATON Zoltan         return false;
69058b01325SBALATON Zoltan     }
69158b01325SBALATON Zoltan 
69258b01325SBALATON Zoltan     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
69358b01325SBALATON Zoltan     if (access_type == MMU_INST_FETCH) {
69458b01325SBALATON Zoltan         switch (ret) {
69558b01325SBALATON Zoltan         case -1:
69658b01325SBALATON Zoltan             /* No matches in page tables or TLB */
69758b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_ITLB;
69858b01325SBALATON Zoltan             env->error_code = 0;
69958b01325SBALATON Zoltan             env->spr[SPR_40x_DEAR] = eaddr;
70058b01325SBALATON Zoltan             env->spr[SPR_40x_ESR] = 0x00000000;
70158b01325SBALATON Zoltan             break;
70258b01325SBALATON Zoltan         case -2:
70358b01325SBALATON Zoltan             /* Access rights violation */
70458b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_ISI;
70558b01325SBALATON Zoltan             env->error_code = 0x08000000;
70658b01325SBALATON Zoltan             break;
70758b01325SBALATON Zoltan         default:
70858b01325SBALATON Zoltan             g_assert_not_reached();
70958b01325SBALATON Zoltan         }
71058b01325SBALATON Zoltan     } else {
71158b01325SBALATON Zoltan         switch (ret) {
71258b01325SBALATON Zoltan         case -1:
71358b01325SBALATON Zoltan             /* No matches in page tables or TLB */
71458b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_DTLB;
71558b01325SBALATON Zoltan             env->error_code = 0;
71658b01325SBALATON Zoltan             env->spr[SPR_40x_DEAR] = eaddr;
71758b01325SBALATON Zoltan             if (access_type == MMU_DATA_STORE) {
71858b01325SBALATON Zoltan                 env->spr[SPR_40x_ESR] = 0x00800000;
71958b01325SBALATON Zoltan             } else {
72058b01325SBALATON Zoltan                 env->spr[SPR_40x_ESR] = 0x00000000;
72158b01325SBALATON Zoltan             }
72258b01325SBALATON Zoltan             break;
72358b01325SBALATON Zoltan         case -2:
72458b01325SBALATON Zoltan             /* Access rights violation */
72558b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_DSI;
72658b01325SBALATON Zoltan             env->error_code = 0;
72758b01325SBALATON Zoltan             env->spr[SPR_40x_DEAR] = eaddr;
72858b01325SBALATON Zoltan             if (access_type == MMU_DATA_STORE) {
72958b01325SBALATON Zoltan                 env->spr[SPR_40x_ESR] |= 0x00800000;
73058b01325SBALATON Zoltan             }
73158b01325SBALATON Zoltan             break;
73258b01325SBALATON Zoltan         default:
73358b01325SBALATON Zoltan             g_assert_not_reached();
73458b01325SBALATON Zoltan         }
73558b01325SBALATON Zoltan     }
73658b01325SBALATON Zoltan     return false;
73758b01325SBALATON Zoltan }
73858b01325SBALATON Zoltan 
7396b9ea7f3SBALATON Zoltan static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
7405118ebe8SLucas Mateus Castro (alqotel)                           MMUAccessType access_type,
7415118ebe8SLucas Mateus Castro (alqotel)                           hwaddr *raddrp, int *psizep, int *protp,
7425118ebe8SLucas Mateus Castro (alqotel)                           int mmu_idx, bool guest_visible)
7435118ebe8SLucas Mateus Castro (alqotel) {
7445118ebe8SLucas Mateus Castro (alqotel)     CPUState *cs = CPU(cpu);
7455118ebe8SLucas Mateus Castro (alqotel)     CPUPPCState *env = &cpu->env;
7465118ebe8SLucas Mateus Castro (alqotel)     mmu_ctx_t ctx;
747f6f8838bSBALATON Zoltan     hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
748f6f8838bSBALATON Zoltan     int type, ret;
7495118ebe8SLucas Mateus Castro (alqotel) 
750c29f808aSBALATON Zoltan     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
751c29f808aSBALATON Zoltan         return true;
752c29f808aSBALATON Zoltan     }
753c29f808aSBALATON Zoltan 
7545118ebe8SLucas Mateus Castro (alqotel)     if (access_type == MMU_INST_FETCH) {
7555118ebe8SLucas Mateus Castro (alqotel)         /* code access */
7565118ebe8SLucas Mateus Castro (alqotel)         type = ACCESS_CODE;
7575118ebe8SLucas Mateus Castro (alqotel)     } else if (guest_visible) {
7585118ebe8SLucas Mateus Castro (alqotel)         /* data access */
7595118ebe8SLucas Mateus Castro (alqotel)         type = env->access_type;
7605118ebe8SLucas Mateus Castro (alqotel)     } else {
7615118ebe8SLucas Mateus Castro (alqotel)         type = ACCESS_INT;
7625118ebe8SLucas Mateus Castro (alqotel)     }
7635118ebe8SLucas Mateus Castro (alqotel) 
7646b9ea7f3SBALATON Zoltan     ctx.prot = 0;
765f6f8838bSBALATON Zoltan     ret = mmu6xx_get_physical_address(env, &ctx, eaddr, &hash,
766f6f8838bSBALATON Zoltan                                       access_type, type);
7675118ebe8SLucas Mateus Castro (alqotel)     if (ret == 0) {
7685118ebe8SLucas Mateus Castro (alqotel)         *raddrp = ctx.raddr;
7695118ebe8SLucas Mateus Castro (alqotel)         *protp = ctx.prot;
7705118ebe8SLucas Mateus Castro (alqotel)         *psizep = TARGET_PAGE_BITS;
7715118ebe8SLucas Mateus Castro (alqotel)         return true;
7729e9ca54cSBALATON Zoltan     } else if (!guest_visible) {
7739e9ca54cSBALATON Zoltan         return false;
7745118ebe8SLucas Mateus Castro (alqotel)     }
7755118ebe8SLucas Mateus Castro (alqotel) 
77656964585SCédric Le Goater     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
7775118ebe8SLucas Mateus Castro (alqotel)     if (type == ACCESS_CODE) {
7785118ebe8SLucas Mateus Castro (alqotel)         switch (ret) {
7795118ebe8SLucas Mateus Castro (alqotel)         case -1:
7805118ebe8SLucas Mateus Castro (alqotel)             /* No matches in page tables or TLB */
7815118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_IFTLB;
7825118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 1 << 18;
7835118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_IMISS] = eaddr;
7845118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
7855118ebe8SLucas Mateus Castro (alqotel)             goto tlb_miss;
7865118ebe8SLucas Mateus Castro (alqotel)         case -2:
7875118ebe8SLucas Mateus Castro (alqotel)             /* Access rights violation */
7885118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_ISI;
7895118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 0x08000000;
7905118ebe8SLucas Mateus Castro (alqotel)             break;
7915118ebe8SLucas Mateus Castro (alqotel)         case -3:
7925118ebe8SLucas Mateus Castro (alqotel)             /* No execute protection violation */
7935118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_ISI;
794ba91e5d0SBALATON Zoltan             env->error_code = 0x10000000;
7955118ebe8SLucas Mateus Castro (alqotel)             break;
7965118ebe8SLucas Mateus Castro (alqotel)         case -4:
7975118ebe8SLucas Mateus Castro (alqotel)             /* Direct store exception */
7985118ebe8SLucas Mateus Castro (alqotel)             /* No code fetch is allowed in direct-store areas */
7995118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_ISI;
8005118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 0x10000000;
8015118ebe8SLucas Mateus Castro (alqotel)             break;
8025118ebe8SLucas Mateus Castro (alqotel)         }
8035118ebe8SLucas Mateus Castro (alqotel)     } else {
8045118ebe8SLucas Mateus Castro (alqotel)         switch (ret) {
8055118ebe8SLucas Mateus Castro (alqotel)         case -1:
8065118ebe8SLucas Mateus Castro (alqotel)             /* No matches in page tables or TLB */
8075118ebe8SLucas Mateus Castro (alqotel)             if (access_type == MMU_DATA_STORE) {
8085118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DSTLB;
8095118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 1 << 16;
8105118ebe8SLucas Mateus Castro (alqotel)             } else {
8115118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DLTLB;
8125118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 0;
8135118ebe8SLucas Mateus Castro (alqotel)             }
8145118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_DMISS] = eaddr;
8155118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
8165118ebe8SLucas Mateus Castro (alqotel) tlb_miss:
8175118ebe8SLucas Mateus Castro (alqotel)             env->error_code |= ctx.key << 19;
8185118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
819f6f8838bSBALATON Zoltan                                   get_pteg_offset32(cpu, hash);
8205118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
821f6f8838bSBALATON Zoltan                                   get_pteg_offset32(cpu, ~hash);
8225118ebe8SLucas Mateus Castro (alqotel)             break;
8235118ebe8SLucas Mateus Castro (alqotel)         case -2:
8245118ebe8SLucas Mateus Castro (alqotel)             /* Access rights violation */
8255118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_DSI;
8265118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 0;
8275118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_DAR] = eaddr;
8285118ebe8SLucas Mateus Castro (alqotel)             if (access_type == MMU_DATA_STORE) {
8295118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DSISR] = 0x0A000000;
8305118ebe8SLucas Mateus Castro (alqotel)             } else {
8315118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DSISR] = 0x08000000;
8325118ebe8SLucas Mateus Castro (alqotel)             }
8335118ebe8SLucas Mateus Castro (alqotel)             break;
8345118ebe8SLucas Mateus Castro (alqotel)         case -4:
8355118ebe8SLucas Mateus Castro (alqotel)             /* Direct store exception */
8365118ebe8SLucas Mateus Castro (alqotel)             switch (type) {
8375118ebe8SLucas Mateus Castro (alqotel)             case ACCESS_FLOAT:
8385118ebe8SLucas Mateus Castro (alqotel)                 /* Floating point load/store */
8395118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_ALIGN;
8405118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = POWERPC_EXCP_ALIGN_FP;
8415118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
8425118ebe8SLucas Mateus Castro (alqotel)                 break;
8435118ebe8SLucas Mateus Castro (alqotel)             case ACCESS_RES:
8445118ebe8SLucas Mateus Castro (alqotel)                 /* lwarx, ldarx or stwcx. */
8455118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DSI;
8465118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 0;
8475118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
8485118ebe8SLucas Mateus Castro (alqotel)                 if (access_type == MMU_DATA_STORE) {
8495118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x06000000;
8505118ebe8SLucas Mateus Castro (alqotel)                 } else {
8515118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x04000000;
8525118ebe8SLucas Mateus Castro (alqotel)                 }
8535118ebe8SLucas Mateus Castro (alqotel)                 break;
8545118ebe8SLucas Mateus Castro (alqotel)             case ACCESS_EXT:
8555118ebe8SLucas Mateus Castro (alqotel)                 /* eciwx or ecowx */
8565118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DSI;
8575118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 0;
8585118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
8595118ebe8SLucas Mateus Castro (alqotel)                 if (access_type == MMU_DATA_STORE) {
8605118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x06100000;
8615118ebe8SLucas Mateus Castro (alqotel)                 } else {
8625118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x04100000;
8635118ebe8SLucas Mateus Castro (alqotel)                 }
8645118ebe8SLucas Mateus Castro (alqotel)                 break;
8655118ebe8SLucas Mateus Castro (alqotel)             default:
8665118ebe8SLucas Mateus Castro (alqotel)                 printf("DSI: invalid exception (%d)\n", ret);
8675118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_PROGRAM;
8689e9ca54cSBALATON Zoltan                 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
8695118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
8705118ebe8SLucas Mateus Castro (alqotel)                 break;
8715118ebe8SLucas Mateus Castro (alqotel)             }
8725118ebe8SLucas Mateus Castro (alqotel)             break;
8735118ebe8SLucas Mateus Castro (alqotel)         }
8745118ebe8SLucas Mateus Castro (alqotel)     }
8755118ebe8SLucas Mateus Castro (alqotel)     return false;
8765118ebe8SLucas Mateus Castro (alqotel) }
8775118ebe8SLucas Mateus Castro (alqotel) 
8785118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/
8795118ebe8SLucas Mateus Castro (alqotel) 
8805118ebe8SLucas Mateus Castro (alqotel) bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
8815118ebe8SLucas Mateus Castro (alqotel)                       hwaddr *raddrp, int *psizep, int *protp,
8825118ebe8SLucas Mateus Castro (alqotel)                       int mmu_idx, bool guest_visible)
8835118ebe8SLucas Mateus Castro (alqotel) {
8845118ebe8SLucas Mateus Castro (alqotel)     switch (cpu->env.mmu_model) {
8855118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64)
8865118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_3_00:
8875118ebe8SLucas Mateus Castro (alqotel)         if (ppc64_v3_radix(cpu)) {
8885118ebe8SLucas Mateus Castro (alqotel)             return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
8895118ebe8SLucas Mateus Castro (alqotel)                                      psizep, protp, mmu_idx, guest_visible);
8905118ebe8SLucas Mateus Castro (alqotel)         }
8915118ebe8SLucas Mateus Castro (alqotel)         /* fall through */
8925118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_64B:
8935118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_03:
8945118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_06:
8955118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_07:
8965118ebe8SLucas Mateus Castro (alqotel)         return ppc_hash64_xlate(cpu, eaddr, access_type,
8975118ebe8SLucas Mateus Castro (alqotel)                                 raddrp, psizep, protp, mmu_idx, guest_visible);
8985118ebe8SLucas Mateus Castro (alqotel) #endif
8995118ebe8SLucas Mateus Castro (alqotel) 
9005118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_32B:
9015118ebe8SLucas Mateus Castro (alqotel)         return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
9025118ebe8SLucas Mateus Castro (alqotel)                                psizep, protp, mmu_idx, guest_visible);
903ba91e5d0SBALATON Zoltan     case POWERPC_MMU_BOOKE:
904ba91e5d0SBALATON Zoltan     case POWERPC_MMU_BOOKE206:
905ba91e5d0SBALATON Zoltan         return ppc_booke_xlate(cpu, eaddr, access_type, raddrp,
906ba91e5d0SBALATON Zoltan                                psizep, protp, mmu_idx, guest_visible);
90758b01325SBALATON Zoltan     case POWERPC_MMU_SOFT_4xx:
90858b01325SBALATON Zoltan         return ppc_40x_xlate(cpu, eaddr, access_type, raddrp,
90958b01325SBALATON Zoltan                              psizep, protp, mmu_idx, guest_visible);
9106b9ea7f3SBALATON Zoltan     case POWERPC_MMU_SOFT_6xx:
9116b9ea7f3SBALATON Zoltan         return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp,
9126b9ea7f3SBALATON Zoltan                              psizep, protp, mmu_idx, guest_visible);
913c29f808aSBALATON Zoltan     case POWERPC_MMU_REAL:
914c29f808aSBALATON Zoltan         return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
915c29f808aSBALATON Zoltan                                    protp);
916cfd5c128SBALATON Zoltan     case POWERPC_MMU_MPC8xx:
917cfd5c128SBALATON Zoltan         cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n");
9185118ebe8SLucas Mateus Castro (alqotel)     default:
9196b9ea7f3SBALATON Zoltan         cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
9205118ebe8SLucas Mateus Castro (alqotel)     }
9215118ebe8SLucas Mateus Castro (alqotel) }
9225118ebe8SLucas Mateus Castro (alqotel) 
9235118ebe8SLucas Mateus Castro (alqotel) hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
9245118ebe8SLucas Mateus Castro (alqotel) {
9255118ebe8SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = POWERPC_CPU(cs);
9265118ebe8SLucas Mateus Castro (alqotel)     hwaddr raddr;
9275118ebe8SLucas Mateus Castro (alqotel)     int s, p;
9285118ebe8SLucas Mateus Castro (alqotel) 
9295118ebe8SLucas Mateus Castro (alqotel)     /*
9305118ebe8SLucas Mateus Castro (alqotel)      * Some MMUs have separate TLBs for code and data. If we only
9315118ebe8SLucas Mateus Castro (alqotel)      * try an MMU_DATA_LOAD, we may not be able to read instructions
9325118ebe8SLucas Mateus Castro (alqotel)      * mapped by code TLBs, so we also try a MMU_INST_FETCH.
9335118ebe8SLucas Mateus Castro (alqotel)      */
9345118ebe8SLucas Mateus Castro (alqotel)     if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
935fb00f730SRichard Henderson                   ppc_env_mmu_index(&cpu->env, false), false) ||
9365118ebe8SLucas Mateus Castro (alqotel)         ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
937fb00f730SRichard Henderson                   ppc_env_mmu_index(&cpu->env, true), false)) {
9385118ebe8SLucas Mateus Castro (alqotel)         return raddr & TARGET_PAGE_MASK;
9395118ebe8SLucas Mateus Castro (alqotel)     }
9405118ebe8SLucas Mateus Castro (alqotel)     return -1;
9415118ebe8SLucas Mateus Castro (alqotel) }
942