xref: /openbmc/qemu/target/ppc/mmu_common.c (revision 93b799fafd9170da3a79a533ea6f73a18de82e22)
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) 
ppc_store_sdr1(CPUPPCState * env,target_ulong value)40d6ae8ec6SLucas Mateus Castro (alqotel) void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
41d6ae8ec6SLucas Mateus Castro (alqotel) {
42d6ae8ec6SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = env_archcpu(env);
43d6ae8ec6SLucas Mateus Castro (alqotel)     qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
44d6ae8ec6SLucas Mateus Castro (alqotel)     assert(!cpu->env.has_hv_mode || !cpu->vhyp);
45d6ae8ec6SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64)
46d6ae8ec6SLucas Mateus Castro (alqotel)     if (mmu_is_64bit(env->mmu_model)) {
47d6ae8ec6SLucas Mateus Castro (alqotel)         target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
48d6ae8ec6SLucas Mateus Castro (alqotel)         target_ulong htabsize = value & SDR_64_HTABSIZE;
49d6ae8ec6SLucas Mateus Castro (alqotel) 
50d6ae8ec6SLucas Mateus Castro (alqotel)         if (value & ~sdr_mask) {
51d6ae8ec6SLucas Mateus Castro (alqotel)             qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
52d6ae8ec6SLucas Mateus Castro (alqotel)                      " set in SDR1", value & ~sdr_mask);
53d6ae8ec6SLucas Mateus Castro (alqotel)             value &= sdr_mask;
54d6ae8ec6SLucas Mateus Castro (alqotel)         }
55d6ae8ec6SLucas Mateus Castro (alqotel)         if (htabsize > 28) {
56d6ae8ec6SLucas Mateus Castro (alqotel)             qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
57d6ae8ec6SLucas Mateus Castro (alqotel)                      " stored in SDR1", htabsize);
58d6ae8ec6SLucas Mateus Castro (alqotel)             return;
59d6ae8ec6SLucas Mateus Castro (alqotel)         }
60d6ae8ec6SLucas Mateus Castro (alqotel)     }
61d6ae8ec6SLucas Mateus Castro (alqotel) #endif /* defined(TARGET_PPC64) */
62d6ae8ec6SLucas Mateus Castro (alqotel)     /* FIXME: Should check for valid HTABMASK values in 32-bit case */
63d6ae8ec6SLucas Mateus Castro (alqotel)     env->spr[SPR_SDR1] = value;
64d6ae8ec6SLucas Mateus Castro (alqotel) }
65d6ae8ec6SLucas Mateus Castro (alqotel) 
665118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/
675118ebe8SLucas Mateus Castro (alqotel) /* PowerPC MMU emulation */
685118ebe8SLucas Mateus Castro (alqotel) 
ppc6xx_tlb_getnum(CPUPPCState * env,target_ulong eaddr,int way,int is_code)695118ebe8SLucas Mateus Castro (alqotel) int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
705118ebe8SLucas Mateus Castro (alqotel)                                     int way, int is_code)
715118ebe8SLucas Mateus Castro (alqotel) {
725118ebe8SLucas Mateus Castro (alqotel)     int nr;
735118ebe8SLucas Mateus Castro (alqotel) 
745118ebe8SLucas Mateus Castro (alqotel)     /* Select TLB num in a way from address */
755118ebe8SLucas Mateus Castro (alqotel)     nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
765118ebe8SLucas Mateus Castro (alqotel)     /* Select TLB way */
775118ebe8SLucas Mateus Castro (alqotel)     nr += env->tlb_per_way * way;
785fd257f5SBALATON Zoltan     /* 6xx has separate TLBs for instructions and data */
795fd257f5SBALATON Zoltan     if (is_code) {
805118ebe8SLucas Mateus Castro (alqotel)         nr += env->nb_tlb;
815118ebe8SLucas Mateus Castro (alqotel)     }
825118ebe8SLucas Mateus Castro (alqotel) 
835118ebe8SLucas Mateus Castro (alqotel)     return nr;
845118ebe8SLucas Mateus Castro (alqotel) }
855118ebe8SLucas Mateus Castro (alqotel) 
865118ebe8SLucas Mateus Castro (alqotel) /* Software driven TLB helpers */
875118ebe8SLucas Mateus Castro (alqotel) 
ppc6xx_tlb_check(CPUPPCState * env,hwaddr * raddr,int * prot,target_ulong eaddr,MMUAccessType access_type,target_ulong ptem,bool key,bool nx)88aa781c10SBALATON Zoltan static int ppc6xx_tlb_check(CPUPPCState *env, hwaddr *raddr, int *prot,
89aa781c10SBALATON Zoltan                             target_ulong eaddr, MMUAccessType access_type,
90aa781c10SBALATON Zoltan                             target_ulong ptem, bool key, bool nx)
915118ebe8SLucas Mateus Castro (alqotel) {
925118ebe8SLucas Mateus Castro (alqotel)     ppc6xx_tlb_t *tlb;
93f8e0cc94SBALATON Zoltan     target_ulong *pte1p;
94f8e0cc94SBALATON Zoltan     int nr, best, way, ret;
95cab21e2eSBALATON Zoltan     bool is_code = (access_type == MMU_INST_FETCH);
965118ebe8SLucas Mateus Castro (alqotel) 
97fa7f2cb9SBALATON Zoltan     /* Initialize real address with an invalid value */
98aa781c10SBALATON Zoltan     *raddr = (hwaddr)-1ULL;
995118ebe8SLucas Mateus Castro (alqotel)     best = -1;
1005118ebe8SLucas Mateus Castro (alqotel)     ret = -1; /* No TLB found */
1015118ebe8SLucas Mateus Castro (alqotel)     for (way = 0; way < env->nb_ways; way++) {
102cab21e2eSBALATON Zoltan         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
1035118ebe8SLucas Mateus Castro (alqotel)         tlb = &env->tlb.tlb6[nr];
1045118ebe8SLucas Mateus Castro (alqotel)         /* This test "emulates" the PTE index match for hardware TLBs */
1055118ebe8SLucas Mateus Castro (alqotel)         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
10656964585SCédric Le Goater             qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx
10756964585SCédric Le Goater                           " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n",
10856964585SCédric Le Goater                           nr, env->nb_tlb,
1095118ebe8SLucas Mateus Castro (alqotel)                           pte_is_valid(tlb->pte0) ? "valid" : "inval",
1105118ebe8SLucas Mateus Castro (alqotel)                           tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
1115118ebe8SLucas Mateus Castro (alqotel)             continue;
1125118ebe8SLucas Mateus Castro (alqotel)         }
11356964585SCédric Le Goater         qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> "
11456964585SCédric Le Goater                       TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n",
11556964585SCédric Le Goater                       nr, env->nb_tlb,
1165118ebe8SLucas Mateus Castro (alqotel)                       pte_is_valid(tlb->pte0) ? "valid" : "inval",
1175118ebe8SLucas Mateus Castro (alqotel)                       tlb->EPN, eaddr, tlb->pte1,
1185118ebe8SLucas Mateus Castro (alqotel)                       access_type == MMU_DATA_STORE ? 'S' : 'L',
1195118ebe8SLucas Mateus Castro (alqotel)                       access_type == MMU_INST_FETCH ? 'I' : 'D');
1200ce61ffaSBALATON Zoltan         /* Check validity and table match */
1210ce61ffaSBALATON Zoltan         if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 ||
122cab21e2eSBALATON Zoltan             (tlb->pte0 & PTE_PTEM_MASK) != ptem) {
1230ce61ffaSBALATON Zoltan             continue;
1240ce61ffaSBALATON Zoltan         }
1250ce61ffaSBALATON Zoltan         /* all matches should have equal RPN, WIMG & PP */
126aa781c10SBALATON Zoltan         if (*raddr != (hwaddr)-1ULL &&
127aa781c10SBALATON Zoltan             (*raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) {
1280ce61ffaSBALATON Zoltan             qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
1290ce61ffaSBALATON Zoltan             /* TLB inconsistency */
1300ce61ffaSBALATON Zoltan             continue;
1310ce61ffaSBALATON Zoltan         }
1320ce61ffaSBALATON Zoltan         /* Keep the matching PTE information */
1335118ebe8SLucas Mateus Castro (alqotel)         best = nr;
134aa781c10SBALATON Zoltan         *raddr = tlb->pte1;
135aa781c10SBALATON Zoltan         *prot = ppc_hash32_prot(key, tlb->pte1 & HPTE32_R_PP, nx);
136aa781c10SBALATON Zoltan         if (check_prot_access_type(*prot, access_type)) {
1370ce61ffaSBALATON Zoltan             qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
1385118ebe8SLucas Mateus Castro (alqotel)             ret = 0;
1390ce61ffaSBALATON Zoltan             break;
1400ce61ffaSBALATON Zoltan         } else {
1410ce61ffaSBALATON Zoltan             qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
1420ce61ffaSBALATON Zoltan             ret = -2;
1435118ebe8SLucas Mateus Castro (alqotel)         }
1445118ebe8SLucas Mateus Castro (alqotel)     }
1455118ebe8SLucas Mateus Castro (alqotel)     if (best != -1) {
146883f2c59SPhilippe Mathieu-Daudé         qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx
14756964585SCédric Le Goater                       " prot=%01x ret=%d\n",
148aa781c10SBALATON Zoltan                       *raddr & TARGET_PAGE_MASK, *prot, ret);
1495118ebe8SLucas Mateus Castro (alqotel)         /* Update page flags */
150f8e0cc94SBALATON Zoltan         pte1p = &env->tlb.tlb6[best].pte1;
151f8e0cc94SBALATON Zoltan         *pte1p |= 0x00000100; /* Update accessed flag */
152f8e0cc94SBALATON Zoltan         if (!(*pte1p & 0x00000080)) {
153f8e0cc94SBALATON Zoltan             if (access_type == MMU_DATA_STORE && ret == 0) {
154f8e0cc94SBALATON Zoltan                 /* Update changed flag */
155f8e0cc94SBALATON Zoltan                 *pte1p |= 0x00000080;
156f8e0cc94SBALATON Zoltan             } else {
157f8e0cc94SBALATON Zoltan                 /* Force page fault for first write access */
158aa781c10SBALATON Zoltan                 *prot &= ~PAGE_WRITE;
159f8e0cc94SBALATON Zoltan             }
160f8e0cc94SBALATON Zoltan         }
1615118ebe8SLucas Mateus Castro (alqotel)     }
162cab21e2eSBALATON Zoltan     if (ret == -1) {
163cab21e2eSBALATON Zoltan         int r = is_code ? SPR_ICMP : SPR_DCMP;
164cab21e2eSBALATON Zoltan         env->spr[r] = ptem;
165cab21e2eSBALATON Zoltan     }
1660af20f35SBALATON Zoltan #if defined(DUMP_PAGE_TABLES)
1670af20f35SBALATON Zoltan     if (qemu_loglevel_mask(CPU_LOG_MMU)) {
1680af20f35SBALATON Zoltan         CPUState *cs = env_cpu(env);
1690af20f35SBALATON Zoltan         hwaddr base = ppc_hash32_hpt_base(env_archcpu(env));
1700af20f35SBALATON Zoltan         hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80;
1710af20f35SBALATON Zoltan         uint32_t a0, a1, a2, a3;
1725118ebe8SLucas Mateus Castro (alqotel) 
1730af20f35SBALATON Zoltan         qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n",
1740af20f35SBALATON Zoltan                  base, len);
1750af20f35SBALATON Zoltan         for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) {
1760af20f35SBALATON Zoltan             a0 = ldl_phys(cs->as, curaddr);
1770af20f35SBALATON Zoltan             a1 = ldl_phys(cs->as, curaddr + 4);
1780af20f35SBALATON Zoltan             a2 = ldl_phys(cs->as, curaddr + 8);
1790af20f35SBALATON Zoltan             a3 = ldl_phys(cs->as, curaddr + 12);
1800af20f35SBALATON Zoltan             if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
1810af20f35SBALATON Zoltan                 qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n",
1820af20f35SBALATON Zoltan                          curaddr, a0, a1, a2, a3);
1830af20f35SBALATON Zoltan             }
1840af20f35SBALATON Zoltan         }
1850af20f35SBALATON Zoltan     }
1860af20f35SBALATON Zoltan #endif
1875118ebe8SLucas Mateus Castro (alqotel)     return ret;
1885118ebe8SLucas Mateus Castro (alqotel) }
1895118ebe8SLucas Mateus Castro (alqotel) 
get_bat_6xx_tlb(CPUPPCState * env,hwaddr * raddr,int * prot,target_ulong eaddr,MMUAccessType access_type,bool pr)1907e590cf6SBALATON Zoltan static int get_bat_6xx_tlb(CPUPPCState *env, hwaddr *raddr, int *prot,
191d3233386SBALATON Zoltan                            target_ulong eaddr, MMUAccessType access_type,
192d3233386SBALATON Zoltan                            bool pr)
1935118ebe8SLucas Mateus Castro (alqotel) {
1945118ebe8SLucas Mateus Castro (alqotel)     target_ulong *BATlt, *BATut, *BATu, *BATl;
1955118ebe8SLucas Mateus Castro (alqotel)     target_ulong BEPIl, BEPIu, bl;
196d3233386SBALATON Zoltan     int i, ret = -1;
1975118ebe8SLucas Mateus Castro (alqotel)     bool ifetch = access_type == MMU_INST_FETCH;
1985118ebe8SLucas Mateus Castro (alqotel) 
19956964585SCédric Le Goater     qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
20068bf3a7bSBALATON Zoltan                   ifetch ? 'I' : 'D', eaddr);
2015118ebe8SLucas Mateus Castro (alqotel)     if (ifetch) {
2025118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->IBAT[1];
2035118ebe8SLucas Mateus Castro (alqotel)         BATut = env->IBAT[0];
2045118ebe8SLucas Mateus Castro (alqotel)     } else {
2055118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->DBAT[1];
2065118ebe8SLucas Mateus Castro (alqotel)         BATut = env->DBAT[0];
2075118ebe8SLucas Mateus Castro (alqotel)     }
2085118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < env->nb_BATs; i++) {
2095118ebe8SLucas Mateus Castro (alqotel)         BATu = &BATut[i];
2105118ebe8SLucas Mateus Castro (alqotel)         BATl = &BATlt[i];
2116ca35e87SBALATON Zoltan         BEPIu = *BATu & BATU32_BEPIU;
2126ca35e87SBALATON Zoltan         BEPIl = *BATu & BATU32_BEPIL;
21356964585SCédric Le Goater         qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu "
21456964585SCédric Le Goater                       TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__,
21568bf3a7bSBALATON Zoltan                       ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl);
216d3233386SBALATON Zoltan         bl = (*BATu & BATU32_BL) << 15;
217d3233386SBALATON Zoltan         if ((!pr && (*BATu & BATU32_VS)) || (pr && (*BATu & BATU32_VP))) {
2186ca35e87SBALATON Zoltan             if ((eaddr & BATU32_BEPIU) == BEPIu &&
2196ca35e87SBALATON Zoltan                 ((eaddr & BATU32_BEPIL) & ~bl) == BEPIl) {
2205118ebe8SLucas Mateus Castro (alqotel)                 /* Get physical address */
2217e590cf6SBALATON Zoltan                 *raddr = (*BATl & BATU32_BEPIU) |
2226ca35e87SBALATON Zoltan                     ((eaddr & BATU32_BEPIL & bl) | (*BATl & BATU32_BEPIL)) |
22368bf3a7bSBALATON Zoltan                     (eaddr & 0x0001F000);
2245118ebe8SLucas Mateus Castro (alqotel)                 /* Compute access rights */
2257e590cf6SBALATON Zoltan                 *prot = ppc_hash32_bat_prot(*BATu, *BATl);
2267e590cf6SBALATON Zoltan                 if (check_prot_access_type(*prot, access_type)) {
227883f2c59SPhilippe Mathieu-Daudé                     qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx
2287e590cf6SBALATON Zoltan                                   " prot=%c%c\n", i, *raddr,
2297e590cf6SBALATON Zoltan                                   *prot & PAGE_READ ? 'R' : '-',
2307e590cf6SBALATON Zoltan                                   *prot & PAGE_WRITE ? 'W' : '-');
231cd1038ecSBALATON Zoltan                     ret = 0;
232cd1038ecSBALATON Zoltan                 } else {
233cd1038ecSBALATON Zoltan                     ret = -2;
2345118ebe8SLucas Mateus Castro (alqotel)                 }
2355118ebe8SLucas Mateus Castro (alqotel)                 break;
2365118ebe8SLucas Mateus Castro (alqotel)             }
2375118ebe8SLucas Mateus Castro (alqotel)         }
2385118ebe8SLucas Mateus Castro (alqotel)     }
2395118ebe8SLucas Mateus Castro (alqotel)     if (ret < 0) {
2405118ebe8SLucas Mateus Castro (alqotel)         if (qemu_log_enabled()) {
24156964585SCédric Le Goater             qemu_log_mask(CPU_LOG_MMU, "no BAT match for "
24268bf3a7bSBALATON Zoltan                           TARGET_FMT_lx ":\n", eaddr);
2435118ebe8SLucas Mateus Castro (alqotel)             for (i = 0; i < 4; i++) {
2445118ebe8SLucas Mateus Castro (alqotel)                 BATu = &BATut[i];
2455118ebe8SLucas Mateus Castro (alqotel)                 BATl = &BATlt[i];
2466ca35e87SBALATON Zoltan                 BEPIu = *BATu & BATU32_BEPIU;
2476ca35e87SBALATON Zoltan                 BEPIl = *BATu & BATU32_BEPIL;
2486ca35e87SBALATON Zoltan                 bl = (*BATu & BATU32_BL) << 15;
24947bededcSBALATON Zoltan                 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx
25047bededcSBALATON Zoltan                               " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx
25147bededcSBALATON Zoltan                               "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " "
25247bededcSBALATON Zoltan                               TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D',
25368bf3a7bSBALATON Zoltan                               i, eaddr, *BATu, *BATl, BEPIu, BEPIl, bl);
2545118ebe8SLucas Mateus Castro (alqotel)             }
2555118ebe8SLucas Mateus Castro (alqotel)         }
2565118ebe8SLucas Mateus Castro (alqotel)     }
2575118ebe8SLucas Mateus Castro (alqotel)     /* No hit */
2585118ebe8SLucas Mateus Castro (alqotel)     return ret;
2595118ebe8SLucas Mateus Castro (alqotel) }
2605118ebe8SLucas Mateus Castro (alqotel) 
mmu6xx_get_physical_address(CPUPPCState * env,hwaddr * raddr,int * prot,target_ulong eaddr,hwaddr * hashp,bool * keyp,MMUAccessType access_type,int type)261*bfb5a5eeSBALATON Zoltan static int mmu6xx_get_physical_address(CPUPPCState *env, hwaddr *raddr,
262*bfb5a5eeSBALATON Zoltan                                        int *prot, target_ulong eaddr,
263da5c1d20SBALATON Zoltan                                        hwaddr *hashp, bool *keyp,
264269d6f00SBALATON Zoltan                                        MMUAccessType access_type, int type)
2655118ebe8SLucas Mateus Castro (alqotel) {
2665118ebe8SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = env_archcpu(env);
2675118ebe8SLucas Mateus Castro (alqotel)     hwaddr hash;
268cab21e2eSBALATON Zoltan     target_ulong vsid, sr, pgidx, ptem;
269d3233386SBALATON Zoltan     bool key, ds, nx;
270d3233386SBALATON Zoltan     bool pr = FIELD_EX64(env->msr, MSR, PR);
2715118ebe8SLucas Mateus Castro (alqotel) 
272269d6f00SBALATON Zoltan     /* First try to find a BAT entry if there are any */
273d3233386SBALATON Zoltan     if (env->nb_BATs &&
274*bfb5a5eeSBALATON Zoltan         get_bat_6xx_tlb(env, raddr, prot, eaddr, access_type, pr) == 0) {
275269d6f00SBALATON Zoltan         return 0;
276269d6f00SBALATON Zoltan     }
277269d6f00SBALATON Zoltan 
278269d6f00SBALATON Zoltan     /* Perform segment based translation when no BATs matched */
2795118ebe8SLucas Mateus Castro (alqotel)     sr = env->sr[eaddr >> 28];
280da5c1d20SBALATON Zoltan     key = ppc_hash32_key(pr, sr);
281da5c1d20SBALATON Zoltan     *keyp = key;
282aaf5845bSBALATON Zoltan     ds = sr & SR32_T;
283691cf34fSBALATON Zoltan     nx = sr & SR32_NX;
284691cf34fSBALATON Zoltan     vsid = sr & SR32_VSID;
2855118ebe8SLucas Mateus Castro (alqotel)     qemu_log_mask(CPU_LOG_MMU,
2865118ebe8SLucas Mateus Castro (alqotel)                   "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
2875118ebe8SLucas Mateus Castro (alqotel)                   " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
2885118ebe8SLucas Mateus Castro (alqotel)                   " ir=%d dr=%d pr=%d %d t=%d\n",
289d41ccf6eSVíctor Colombo                   eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr,
290e4eea6efSVíctor Colombo                   (int)FIELD_EX64(env->msr, MSR, IR),
291e4eea6efSVíctor Colombo                   (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0,
29256964585SCédric Le Goater                   access_type == MMU_DATA_STORE, type);
2938abd6d42SBALATON Zoltan     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
2945118ebe8SLucas Mateus Castro (alqotel)     hash = vsid ^ pgidx;
295cab21e2eSBALATON Zoltan     ptem = (vsid << 7) | (pgidx >> 10); /* Virtual segment ID | API */
2965118ebe8SLucas Mateus Castro (alqotel) 
29747bededcSBALATON Zoltan     qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid "
298da5c1d20SBALATON Zoltan                   TARGET_FMT_lx "\n", key, ds, nx, vsid);
2995118ebe8SLucas Mateus Castro (alqotel)     if (!ds) {
3005118ebe8SLucas Mateus Castro (alqotel)         /* Check if instruction fetch is allowed, if needed */
301691cf34fSBALATON Zoltan         if (type == ACCESS_CODE && nx) {
302f1418bdeSBALATON Zoltan             qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
303f1418bdeSBALATON Zoltan             return -3;
304f1418bdeSBALATON Zoltan         }
3055118ebe8SLucas Mateus Castro (alqotel)         /* Page address translation */
306f1418bdeSBALATON Zoltan         qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask "
307f1418bdeSBALATON Zoltan                       HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n",
3085118ebe8SLucas Mateus Castro (alqotel)                       ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
309f6f8838bSBALATON Zoltan         *hashp = hash;
3105118ebe8SLucas Mateus Castro (alqotel) 
3115118ebe8SLucas Mateus Castro (alqotel)         /* Software TLB search */
312*bfb5a5eeSBALATON Zoltan         return ppc6xx_tlb_check(env, raddr, prot, eaddr,
313aa781c10SBALATON Zoltan                                 access_type, ptem, key, nx);
314f3f66a31SBALATON Zoltan     }
3155118ebe8SLucas Mateus Castro (alqotel) 
316f3f66a31SBALATON Zoltan     /* Direct-store segment : absolutely *BUGGY* for now */
317f3f66a31SBALATON Zoltan     qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
3185118ebe8SLucas Mateus Castro (alqotel)     switch (type) {
3195118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_INT:
3205118ebe8SLucas Mateus Castro (alqotel)         /* Integer load/store : only access allowed */
3215118ebe8SLucas Mateus Castro (alqotel)         break;
3225118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_CACHE:
3235118ebe8SLucas Mateus Castro (alqotel)         /*
3245118ebe8SLucas Mateus Castro (alqotel)          * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
3255118ebe8SLucas Mateus Castro (alqotel)          *
3265118ebe8SLucas Mateus Castro (alqotel)          * Should make the instruction do no-op.  As it already do
3275118ebe8SLucas Mateus Castro (alqotel)          * no-op, it's quite easy :-)
3285118ebe8SLucas Mateus Castro (alqotel)          */
329*bfb5a5eeSBALATON Zoltan         *raddr = eaddr;
3305118ebe8SLucas Mateus Castro (alqotel)         return 0;
33140df08d2SBALATON Zoltan     case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */
33240df08d2SBALATON Zoltan     case ACCESS_FLOAT: /* Floating point load/store */
33340df08d2SBALATON Zoltan     case ACCESS_RES: /* lwarx, ldarx or srwcx. */
33440df08d2SBALATON Zoltan     case ACCESS_EXT: /* eciwx or ecowx */
3355118ebe8SLucas Mateus Castro (alqotel)         return -4;
3365118ebe8SLucas Mateus Castro (alqotel)     }
337da5c1d20SBALATON Zoltan     if ((access_type == MMU_DATA_STORE || !key) &&
338da5c1d20SBALATON Zoltan         (access_type == MMU_DATA_LOAD || key)) {
339*bfb5a5eeSBALATON Zoltan         *raddr = eaddr;
340f3f66a31SBALATON Zoltan         return 2;
3415118ebe8SLucas Mateus Castro (alqotel)     }
342f3f66a31SBALATON Zoltan     return -2;
3435118ebe8SLucas Mateus Castro (alqotel) }
3445118ebe8SLucas Mateus Castro (alqotel) 
3455118ebe8SLucas Mateus Castro (alqotel) static const char *book3e_tsize_to_str[32] = {
3465118ebe8SLucas Mateus Castro (alqotel)     "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
3475118ebe8SLucas Mateus Castro (alqotel)     "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
3485118ebe8SLucas Mateus Castro (alqotel)     "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
3495118ebe8SLucas Mateus Castro (alqotel)     "1T", "2T"
3505118ebe8SLucas Mateus Castro (alqotel) };
3515118ebe8SLucas Mateus Castro (alqotel) 
mmubooke_dump_mmu(CPUPPCState * env)3525118ebe8SLucas Mateus Castro (alqotel) static void mmubooke_dump_mmu(CPUPPCState *env)
3535118ebe8SLucas Mateus Castro (alqotel) {
3545118ebe8SLucas Mateus Castro (alqotel)     ppcemb_tlb_t *entry;
3555118ebe8SLucas Mateus Castro (alqotel)     int i;
3565118ebe8SLucas Mateus Castro (alqotel) 
35705739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM
3585118ebe8SLucas Mateus Castro (alqotel)     if (kvm_enabled() && !env->kvm_sw_tlb) {
3595118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("Cannot access KVM TLB\n");
3605118ebe8SLucas Mateus Castro (alqotel)         return;
3615118ebe8SLucas Mateus Castro (alqotel)     }
36205739977SPhilippe Mathieu-Daudé #endif
3635118ebe8SLucas Mateus Castro (alqotel) 
3645118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nTLB:\n");
3655118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("Effective          Physical           Size PID   Prot     "
3665118ebe8SLucas Mateus Castro (alqotel)                 "Attr\n");
3675118ebe8SLucas Mateus Castro (alqotel) 
3685118ebe8SLucas Mateus Castro (alqotel)     entry = &env->tlb.tlbe[0];
3695118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < env->nb_tlb; i++, entry++) {
3705118ebe8SLucas Mateus Castro (alqotel)         hwaddr ea, pa;
3715118ebe8SLucas Mateus Castro (alqotel)         target_ulong mask;
3725118ebe8SLucas Mateus Castro (alqotel)         uint64_t size = (uint64_t)entry->size;
3735118ebe8SLucas Mateus Castro (alqotel)         char size_buf[20];
3745118ebe8SLucas Mateus Castro (alqotel) 
3755118ebe8SLucas Mateus Castro (alqotel)         /* Check valid flag */
3765118ebe8SLucas Mateus Castro (alqotel)         if (!(entry->prot & PAGE_VALID)) {
3775118ebe8SLucas Mateus Castro (alqotel)             continue;
3785118ebe8SLucas Mateus Castro (alqotel)         }
3795118ebe8SLucas Mateus Castro (alqotel) 
3805118ebe8SLucas Mateus Castro (alqotel)         mask = ~(entry->size - 1);
3815118ebe8SLucas Mateus Castro (alqotel)         ea = entry->EPN & mask;
3825118ebe8SLucas Mateus Castro (alqotel)         pa = entry->RPN & mask;
3835118ebe8SLucas Mateus Castro (alqotel)         /* Extend the physical address to 36 bits */
3845118ebe8SLucas Mateus Castro (alqotel)         pa |= (hwaddr)(entry->RPN & 0xF) << 32;
3855118ebe8SLucas Mateus Castro (alqotel)         if (size >= 1 * MiB) {
3865118ebe8SLucas Mateus Castro (alqotel)             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
3875118ebe8SLucas Mateus Castro (alqotel)         } else {
3885118ebe8SLucas Mateus Castro (alqotel)             snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
3895118ebe8SLucas Mateus Castro (alqotel)         }
3905118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
3915118ebe8SLucas Mateus Castro (alqotel)                     (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
3925118ebe8SLucas Mateus Castro (alqotel)                     entry->prot, entry->attr);
3935118ebe8SLucas Mateus Castro (alqotel)     }
3945118ebe8SLucas Mateus Castro (alqotel) 
3955118ebe8SLucas Mateus Castro (alqotel) }
3965118ebe8SLucas Mateus Castro (alqotel) 
mmubooke206_dump_one_tlb(CPUPPCState * env,int tlbn,int offset,int tlbsize)3975118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
3985118ebe8SLucas Mateus Castro (alqotel)                                      int tlbsize)
3995118ebe8SLucas Mateus Castro (alqotel) {
4005118ebe8SLucas Mateus Castro (alqotel)     ppcmas_tlb_t *entry;
4015118ebe8SLucas Mateus Castro (alqotel)     int i;
4025118ebe8SLucas Mateus Castro (alqotel) 
4035118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nTLB%d:\n", tlbn);
4045118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("Effective          Physical           Size TID   TS SRWX"
4055118ebe8SLucas Mateus Castro (alqotel)                 " URWX WIMGE U0123\n");
4065118ebe8SLucas Mateus Castro (alqotel) 
4075118ebe8SLucas Mateus Castro (alqotel)     entry = &env->tlb.tlbm[offset];
4085118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < tlbsize; i++, entry++) {
4095118ebe8SLucas Mateus Castro (alqotel)         hwaddr ea, pa, size;
4105118ebe8SLucas Mateus Castro (alqotel)         int tsize;
4115118ebe8SLucas Mateus Castro (alqotel) 
4125118ebe8SLucas Mateus Castro (alqotel)         if (!(entry->mas1 & MAS1_VALID)) {
4135118ebe8SLucas Mateus Castro (alqotel)             continue;
4145118ebe8SLucas Mateus Castro (alqotel)         }
4155118ebe8SLucas Mateus Castro (alqotel) 
4165118ebe8SLucas Mateus Castro (alqotel)         tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
4175118ebe8SLucas Mateus Castro (alqotel)         size = 1024ULL << tsize;
4185118ebe8SLucas Mateus Castro (alqotel)         ea = entry->mas2 & ~(size - 1);
4195118ebe8SLucas Mateus Castro (alqotel)         pa = entry->mas7_3 & ~(size - 1);
4205118ebe8SLucas Mateus Castro (alqotel) 
4215118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
4225118ebe8SLucas Mateus Castro (alqotel)                     " U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
4235118ebe8SLucas Mateus Castro (alqotel)                     (uint64_t)ea, (uint64_t)pa,
4245118ebe8SLucas Mateus Castro (alqotel)                     book3e_tsize_to_str[tsize],
4255118ebe8SLucas Mateus Castro (alqotel)                     (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
4265118ebe8SLucas Mateus Castro (alqotel)                     (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
4275118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_SR ? 'R' : '-',
4285118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_SW ? 'W' : '-',
4295118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_SX ? 'X' : '-',
4305118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_UR ? 'R' : '-',
4315118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_UW ? 'W' : '-',
4325118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_UX ? 'X' : '-',
4335118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_W ? 'W' : '-',
4345118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_I ? 'I' : '-',
4355118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_M ? 'M' : '-',
4365118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_G ? 'G' : '-',
4375118ebe8SLucas Mateus Castro (alqotel)                     entry->mas2 & MAS2_E ? 'E' : '-',
4385118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U0 ? '0' : '-',
4395118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U1 ? '1' : '-',
4405118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U2 ? '2' : '-',
4415118ebe8SLucas Mateus Castro (alqotel)                     entry->mas7_3 & MAS3_U3 ? '3' : '-');
4425118ebe8SLucas Mateus Castro (alqotel)     }
4435118ebe8SLucas Mateus Castro (alqotel) }
4445118ebe8SLucas Mateus Castro (alqotel) 
mmubooke206_dump_mmu(CPUPPCState * env)4455118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_mmu(CPUPPCState *env)
4465118ebe8SLucas Mateus Castro (alqotel) {
4475118ebe8SLucas Mateus Castro (alqotel)     int offset = 0;
4485118ebe8SLucas Mateus Castro (alqotel)     int i;
4495118ebe8SLucas Mateus Castro (alqotel) 
45005739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM
4515118ebe8SLucas Mateus Castro (alqotel)     if (kvm_enabled() && !env->kvm_sw_tlb) {
4525118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("Cannot access KVM TLB\n");
4535118ebe8SLucas Mateus Castro (alqotel)         return;
4545118ebe8SLucas Mateus Castro (alqotel)     }
45505739977SPhilippe Mathieu-Daudé #endif
4565118ebe8SLucas Mateus Castro (alqotel) 
4575118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
4585118ebe8SLucas Mateus Castro (alqotel)         int size = booke206_tlb_size(env, i);
4595118ebe8SLucas Mateus Castro (alqotel) 
4605118ebe8SLucas Mateus Castro (alqotel)         if (size == 0) {
4615118ebe8SLucas Mateus Castro (alqotel)             continue;
4625118ebe8SLucas Mateus Castro (alqotel)         }
4635118ebe8SLucas Mateus Castro (alqotel) 
4645118ebe8SLucas Mateus Castro (alqotel)         mmubooke206_dump_one_tlb(env, i, offset, size);
4655118ebe8SLucas Mateus Castro (alqotel)         offset += size;
4665118ebe8SLucas Mateus Castro (alqotel)     }
4675118ebe8SLucas Mateus Castro (alqotel) }
4685118ebe8SLucas Mateus Castro (alqotel) 
mmu6xx_dump_BATs(CPUPPCState * env,int type)4695118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
4705118ebe8SLucas Mateus Castro (alqotel) {
4715118ebe8SLucas Mateus Castro (alqotel)     target_ulong *BATlt, *BATut, *BATu, *BATl;
4725118ebe8SLucas Mateus Castro (alqotel)     target_ulong BEPIl, BEPIu, bl;
4735118ebe8SLucas Mateus Castro (alqotel)     int i;
4745118ebe8SLucas Mateus Castro (alqotel) 
4755118ebe8SLucas Mateus Castro (alqotel)     switch (type) {
4765118ebe8SLucas Mateus Castro (alqotel)     case ACCESS_CODE:
4775118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->IBAT[1];
4785118ebe8SLucas Mateus Castro (alqotel)         BATut = env->IBAT[0];
4795118ebe8SLucas Mateus Castro (alqotel)         break;
4805118ebe8SLucas Mateus Castro (alqotel)     default:
4815118ebe8SLucas Mateus Castro (alqotel)         BATlt = env->DBAT[1];
4825118ebe8SLucas Mateus Castro (alqotel)         BATut = env->DBAT[0];
4835118ebe8SLucas Mateus Castro (alqotel)         break;
4845118ebe8SLucas Mateus Castro (alqotel)     }
4855118ebe8SLucas Mateus Castro (alqotel) 
4865118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < env->nb_BATs; i++) {
4875118ebe8SLucas Mateus Castro (alqotel)         BATu = &BATut[i];
4885118ebe8SLucas Mateus Castro (alqotel)         BATl = &BATlt[i];
4896ca35e87SBALATON Zoltan         BEPIu = *BATu & BATU32_BEPIU;
4906ca35e87SBALATON Zoltan         BEPIl = *BATu & BATU32_BEPIL;
4916ca35e87SBALATON Zoltan         bl = (*BATu & BATU32_BL) << 15;
4925118ebe8SLucas Mateus Castro (alqotel)         qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
4935118ebe8SLucas Mateus Castro (alqotel)                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
4945118ebe8SLucas Mateus Castro (alqotel)                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
4955118ebe8SLucas Mateus Castro (alqotel)                     type == ACCESS_CODE ? "code" : "data", i,
4965118ebe8SLucas Mateus Castro (alqotel)                     *BATu, *BATl, BEPIu, BEPIl, bl);
4975118ebe8SLucas Mateus Castro (alqotel)     }
4985118ebe8SLucas Mateus Castro (alqotel) }
4995118ebe8SLucas Mateus Castro (alqotel) 
mmu6xx_dump_mmu(CPUPPCState * env)5005118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_mmu(CPUPPCState *env)
5015118ebe8SLucas Mateus Castro (alqotel) {
5025118ebe8SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = env_archcpu(env);
5035118ebe8SLucas Mateus Castro (alqotel)     ppc6xx_tlb_t *tlb;
5045118ebe8SLucas Mateus Castro (alqotel)     target_ulong sr;
5055118ebe8SLucas Mateus Castro (alqotel)     int type, way, entry, i;
5065118ebe8SLucas Mateus Castro (alqotel) 
5075118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
5085118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
5095118ebe8SLucas Mateus Castro (alqotel) 
5105118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nSegment registers:\n");
5115118ebe8SLucas Mateus Castro (alqotel)     for (i = 0; i < 32; i++) {
5125118ebe8SLucas Mateus Castro (alqotel)         sr = env->sr[i];
5135118ebe8SLucas Mateus Castro (alqotel)         if (sr & 0x80000000) {
5145118ebe8SLucas Mateus Castro (alqotel)             qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
5155118ebe8SLucas Mateus Castro (alqotel)                         "CNTLR_SPEC=0x%05x\n", i,
5165118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
5175118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
5185118ebe8SLucas Mateus Castro (alqotel)                         (uint32_t)(sr & 0xFFFFF));
5195118ebe8SLucas Mateus Castro (alqotel)         } else {
5205118ebe8SLucas Mateus Castro (alqotel)             qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
5215118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
5225118ebe8SLucas Mateus Castro (alqotel)                         sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
5235118ebe8SLucas Mateus Castro (alqotel)                         (uint32_t)(sr & 0x00FFFFFF));
5245118ebe8SLucas Mateus Castro (alqotel)         }
5255118ebe8SLucas Mateus Castro (alqotel)     }
5265118ebe8SLucas Mateus Castro (alqotel) 
5275118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nBATs:\n");
5285118ebe8SLucas Mateus Castro (alqotel)     mmu6xx_dump_BATs(env, ACCESS_INT);
5295118ebe8SLucas Mateus Castro (alqotel)     mmu6xx_dump_BATs(env, ACCESS_CODE);
5305118ebe8SLucas Mateus Castro (alqotel) 
5315118ebe8SLucas Mateus Castro (alqotel)     qemu_printf("\nTLBs                       [EPN    EPN + SIZE]\n");
5325118ebe8SLucas Mateus Castro (alqotel)     for (type = 0; type < 2; type++) {
5335118ebe8SLucas Mateus Castro (alqotel)         for (way = 0; way < env->nb_ways; way++) {
5345118ebe8SLucas Mateus Castro (alqotel)             for (entry = env->nb_tlb * type + env->tlb_per_way * way;
5355118ebe8SLucas Mateus Castro (alqotel)                  entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
5365118ebe8SLucas Mateus Castro (alqotel)                  entry++) {
5375118ebe8SLucas Mateus Castro (alqotel) 
5385118ebe8SLucas Mateus Castro (alqotel)                 tlb = &env->tlb.tlb6[entry];
5395118ebe8SLucas Mateus Castro (alqotel)                 qemu_printf("%s TLB %02d/%02d way:%d %s ["
5405118ebe8SLucas Mateus Castro (alqotel)                             TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
5415118ebe8SLucas Mateus Castro (alqotel)                             type ? "code" : "data", entry % env->nb_tlb,
5425118ebe8SLucas Mateus Castro (alqotel)                             env->nb_tlb, way,
5435118ebe8SLucas Mateus Castro (alqotel)                             pte_is_valid(tlb->pte0) ? "valid" : "inval",
5445118ebe8SLucas Mateus Castro (alqotel)                             tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
5455118ebe8SLucas Mateus Castro (alqotel)             }
5465118ebe8SLucas Mateus Castro (alqotel)         }
5475118ebe8SLucas Mateus Castro (alqotel)     }
5485118ebe8SLucas Mateus Castro (alqotel) }
5495118ebe8SLucas Mateus Castro (alqotel) 
dump_mmu(CPUPPCState * env)5505118ebe8SLucas Mateus Castro (alqotel) void dump_mmu(CPUPPCState *env)
5515118ebe8SLucas Mateus Castro (alqotel) {
5525118ebe8SLucas Mateus Castro (alqotel)     switch (env->mmu_model) {
5535118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_BOOKE:
5545118ebe8SLucas Mateus Castro (alqotel)         mmubooke_dump_mmu(env);
5555118ebe8SLucas Mateus Castro (alqotel)         break;
5565118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_BOOKE206:
5575118ebe8SLucas Mateus Castro (alqotel)         mmubooke206_dump_mmu(env);
5585118ebe8SLucas Mateus Castro (alqotel)         break;
5595118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_SOFT_6xx:
5605118ebe8SLucas Mateus Castro (alqotel)         mmu6xx_dump_mmu(env);
5615118ebe8SLucas Mateus Castro (alqotel)         break;
5625118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64)
5635118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_64B:
5645118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_03:
5655118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_06:
5665118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_07:
5675118ebe8SLucas Mateus Castro (alqotel)         dump_slb(env_archcpu(env));
5685118ebe8SLucas Mateus Castro (alqotel)         break;
5695118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_3_00:
5705118ebe8SLucas Mateus Castro (alqotel)         if (ppc64_v3_radix(env_archcpu(env))) {
5715118ebe8SLucas Mateus Castro (alqotel)             qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
5725118ebe8SLucas Mateus Castro (alqotel)                           __func__);
5735118ebe8SLucas Mateus Castro (alqotel)         } else {
5745118ebe8SLucas Mateus Castro (alqotel)             dump_slb(env_archcpu(env));
5755118ebe8SLucas Mateus Castro (alqotel)         }
5765118ebe8SLucas Mateus Castro (alqotel)         break;
5775118ebe8SLucas Mateus Castro (alqotel) #endif
5785118ebe8SLucas Mateus Castro (alqotel)     default:
5795118ebe8SLucas Mateus Castro (alqotel)         qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
5805118ebe8SLucas Mateus Castro (alqotel)     }
5815118ebe8SLucas Mateus Castro (alqotel) }
5825118ebe8SLucas Mateus Castro (alqotel) 
583ba91e5d0SBALATON Zoltan 
ppc_real_mode_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp)584c29f808aSBALATON Zoltan static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr,
585c29f808aSBALATON Zoltan                                 MMUAccessType access_type,
586c29f808aSBALATON Zoltan                                 hwaddr *raddrp, int *psizep, int *protp)
587c29f808aSBALATON Zoltan {
588c29f808aSBALATON Zoltan     CPUPPCState *env = &cpu->env;
589c29f808aSBALATON Zoltan 
590c29f808aSBALATON Zoltan     if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR)
591c29f808aSBALATON Zoltan                                       : !FIELD_EX64(env->msr, MSR, DR)) {
592c29f808aSBALATON Zoltan         *raddrp = eaddr;
593c29f808aSBALATON Zoltan         *protp = PAGE_RWX;
594c29f808aSBALATON Zoltan         *psizep = TARGET_PAGE_BITS;
595c29f808aSBALATON Zoltan         return true;
596c29f808aSBALATON Zoltan     } else if (env->mmu_model == POWERPC_MMU_REAL) {
597c29f808aSBALATON Zoltan         cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n");
598c29f808aSBALATON Zoltan     }
599c29f808aSBALATON Zoltan     return false;
600c29f808aSBALATON Zoltan }
601c29f808aSBALATON Zoltan 
ppc_40x_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp,int mmu_idx,bool guest_visible)60258b01325SBALATON Zoltan static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr,
60358b01325SBALATON Zoltan                           MMUAccessType access_type,
60458b01325SBALATON Zoltan                           hwaddr *raddrp, int *psizep, int *protp,
60558b01325SBALATON Zoltan                           int mmu_idx, bool guest_visible)
60658b01325SBALATON Zoltan {
60758b01325SBALATON Zoltan     CPUState *cs = CPU(cpu);
60858b01325SBALATON Zoltan     CPUPPCState *env = &cpu->env;
60958b01325SBALATON Zoltan     int ret;
61058b01325SBALATON Zoltan 
61158b01325SBALATON Zoltan     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
61258b01325SBALATON Zoltan         return true;
61358b01325SBALATON Zoltan     }
61458b01325SBALATON Zoltan 
61558b01325SBALATON Zoltan     ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type);
61658b01325SBALATON Zoltan     if (ret == 0) {
61758b01325SBALATON Zoltan         *psizep = TARGET_PAGE_BITS;
61858b01325SBALATON Zoltan         return true;
61958b01325SBALATON Zoltan     } else if (!guest_visible) {
62058b01325SBALATON Zoltan         return false;
62158b01325SBALATON Zoltan     }
62258b01325SBALATON Zoltan 
62358b01325SBALATON Zoltan     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
62458b01325SBALATON Zoltan     if (access_type == MMU_INST_FETCH) {
62558b01325SBALATON Zoltan         switch (ret) {
62658b01325SBALATON Zoltan         case -1:
62758b01325SBALATON Zoltan             /* No matches in page tables or TLB */
62858b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_ITLB;
62958b01325SBALATON Zoltan             env->error_code = 0;
63058b01325SBALATON Zoltan             env->spr[SPR_40x_DEAR] = eaddr;
63158b01325SBALATON Zoltan             env->spr[SPR_40x_ESR] = 0x00000000;
63258b01325SBALATON Zoltan             break;
63358b01325SBALATON Zoltan         case -2:
63458b01325SBALATON Zoltan             /* Access rights violation */
63558b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_ISI;
63658b01325SBALATON Zoltan             env->error_code = 0x08000000;
63758b01325SBALATON Zoltan             break;
63858b01325SBALATON Zoltan         default:
63958b01325SBALATON Zoltan             g_assert_not_reached();
64058b01325SBALATON Zoltan         }
64158b01325SBALATON Zoltan     } else {
64258b01325SBALATON Zoltan         switch (ret) {
64358b01325SBALATON Zoltan         case -1:
64458b01325SBALATON Zoltan             /* No matches in page tables or TLB */
64558b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_DTLB;
64658b01325SBALATON Zoltan             env->error_code = 0;
64758b01325SBALATON Zoltan             env->spr[SPR_40x_DEAR] = eaddr;
64858b01325SBALATON Zoltan             if (access_type == MMU_DATA_STORE) {
64958b01325SBALATON Zoltan                 env->spr[SPR_40x_ESR] = 0x00800000;
65058b01325SBALATON Zoltan             } else {
65158b01325SBALATON Zoltan                 env->spr[SPR_40x_ESR] = 0x00000000;
65258b01325SBALATON Zoltan             }
65358b01325SBALATON Zoltan             break;
65458b01325SBALATON Zoltan         case -2:
65558b01325SBALATON Zoltan             /* Access rights violation */
65658b01325SBALATON Zoltan             cs->exception_index = POWERPC_EXCP_DSI;
65758b01325SBALATON Zoltan             env->error_code = 0;
65858b01325SBALATON Zoltan             env->spr[SPR_40x_DEAR] = eaddr;
65958b01325SBALATON Zoltan             if (access_type == MMU_DATA_STORE) {
66058b01325SBALATON Zoltan                 env->spr[SPR_40x_ESR] |= 0x00800000;
66158b01325SBALATON Zoltan             }
66258b01325SBALATON Zoltan             break;
66358b01325SBALATON Zoltan         default:
66458b01325SBALATON Zoltan             g_assert_not_reached();
66558b01325SBALATON Zoltan         }
66658b01325SBALATON Zoltan     }
66758b01325SBALATON Zoltan     return false;
66858b01325SBALATON Zoltan }
66958b01325SBALATON Zoltan 
ppc_6xx_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp,int mmu_idx,bool guest_visible)6706b9ea7f3SBALATON Zoltan static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr,
6715118ebe8SLucas Mateus Castro (alqotel)                           MMUAccessType access_type,
6725118ebe8SLucas Mateus Castro (alqotel)                           hwaddr *raddrp, int *psizep, int *protp,
6735118ebe8SLucas Mateus Castro (alqotel)                           int mmu_idx, bool guest_visible)
6745118ebe8SLucas Mateus Castro (alqotel) {
6755118ebe8SLucas Mateus Castro (alqotel)     CPUState *cs = CPU(cpu);
6765118ebe8SLucas Mateus Castro (alqotel)     CPUPPCState *env = &cpu->env;
677f6f8838bSBALATON Zoltan     hwaddr hash = 0; /* init to 0 to avoid used uninit warning */
678da5c1d20SBALATON Zoltan     bool key;
679f6f8838bSBALATON Zoltan     int type, ret;
6805118ebe8SLucas Mateus Castro (alqotel) 
681c29f808aSBALATON Zoltan     if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) {
682c29f808aSBALATON Zoltan         return true;
683c29f808aSBALATON Zoltan     }
684c29f808aSBALATON Zoltan 
6855118ebe8SLucas Mateus Castro (alqotel)     if (access_type == MMU_INST_FETCH) {
6865118ebe8SLucas Mateus Castro (alqotel)         /* code access */
6875118ebe8SLucas Mateus Castro (alqotel)         type = ACCESS_CODE;
6885118ebe8SLucas Mateus Castro (alqotel)     } else if (guest_visible) {
6895118ebe8SLucas Mateus Castro (alqotel)         /* data access */
6905118ebe8SLucas Mateus Castro (alqotel)         type = env->access_type;
6915118ebe8SLucas Mateus Castro (alqotel)     } else {
6925118ebe8SLucas Mateus Castro (alqotel)         type = ACCESS_INT;
6935118ebe8SLucas Mateus Castro (alqotel)     }
6945118ebe8SLucas Mateus Castro (alqotel) 
695*bfb5a5eeSBALATON Zoltan     ret = mmu6xx_get_physical_address(env, raddrp, protp, eaddr, &hash, &key,
696f6f8838bSBALATON Zoltan                                       access_type, type);
6975118ebe8SLucas Mateus Castro (alqotel)     if (ret == 0) {
6985118ebe8SLucas Mateus Castro (alqotel)         *psizep = TARGET_PAGE_BITS;
6995118ebe8SLucas Mateus Castro (alqotel)         return true;
7009e9ca54cSBALATON Zoltan     } else if (!guest_visible) {
7019e9ca54cSBALATON Zoltan         return false;
7025118ebe8SLucas Mateus Castro (alqotel)     }
7035118ebe8SLucas Mateus Castro (alqotel) 
70456964585SCédric Le Goater     log_cpu_state_mask(CPU_LOG_MMU, cs, 0);
7055118ebe8SLucas Mateus Castro (alqotel)     if (type == ACCESS_CODE) {
7065118ebe8SLucas Mateus Castro (alqotel)         switch (ret) {
7075118ebe8SLucas Mateus Castro (alqotel)         case -1:
7085118ebe8SLucas Mateus Castro (alqotel)             /* No matches in page tables or TLB */
7095118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_IFTLB;
7105118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 1 << 18;
7115118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_IMISS] = eaddr;
712cab21e2eSBALATON Zoltan             env->spr[SPR_ICMP] |= 0x80000000;
7135118ebe8SLucas Mateus Castro (alqotel)             goto tlb_miss;
7145118ebe8SLucas Mateus Castro (alqotel)         case -2:
7155118ebe8SLucas Mateus Castro (alqotel)             /* Access rights violation */
7165118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_ISI;
7175118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 0x08000000;
7185118ebe8SLucas Mateus Castro (alqotel)             break;
7195118ebe8SLucas Mateus Castro (alqotel)         case -3:
7205118ebe8SLucas Mateus Castro (alqotel)             /* No execute protection violation */
7215118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_ISI;
722ba91e5d0SBALATON Zoltan             env->error_code = 0x10000000;
7235118ebe8SLucas Mateus Castro (alqotel)             break;
7245118ebe8SLucas Mateus Castro (alqotel)         case -4:
7255118ebe8SLucas Mateus Castro (alqotel)             /* Direct store exception */
7265118ebe8SLucas Mateus Castro (alqotel)             /* No code fetch is allowed in direct-store areas */
7275118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_ISI;
7285118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 0x10000000;
7295118ebe8SLucas Mateus Castro (alqotel)             break;
7305118ebe8SLucas Mateus Castro (alqotel)         }
7315118ebe8SLucas Mateus Castro (alqotel)     } else {
7325118ebe8SLucas Mateus Castro (alqotel)         switch (ret) {
7335118ebe8SLucas Mateus Castro (alqotel)         case -1:
7345118ebe8SLucas Mateus Castro (alqotel)             /* No matches in page tables or TLB */
7355118ebe8SLucas Mateus Castro (alqotel)             if (access_type == MMU_DATA_STORE) {
7365118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DSTLB;
7375118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 1 << 16;
7385118ebe8SLucas Mateus Castro (alqotel)             } else {
7395118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DLTLB;
7405118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 0;
7415118ebe8SLucas Mateus Castro (alqotel)             }
7425118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_DMISS] = eaddr;
743cab21e2eSBALATON Zoltan             env->spr[SPR_DCMP] |= 0x80000000;
7445118ebe8SLucas Mateus Castro (alqotel) tlb_miss:
745da5c1d20SBALATON Zoltan             env->error_code |= key << 19;
7465118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
747f6f8838bSBALATON Zoltan                                   get_pteg_offset32(cpu, hash);
7485118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
749f6f8838bSBALATON Zoltan                                   get_pteg_offset32(cpu, ~hash);
7505118ebe8SLucas Mateus Castro (alqotel)             break;
7515118ebe8SLucas Mateus Castro (alqotel)         case -2:
7525118ebe8SLucas Mateus Castro (alqotel)             /* Access rights violation */
7535118ebe8SLucas Mateus Castro (alqotel)             cs->exception_index = POWERPC_EXCP_DSI;
7545118ebe8SLucas Mateus Castro (alqotel)             env->error_code = 0;
7555118ebe8SLucas Mateus Castro (alqotel)             env->spr[SPR_DAR] = eaddr;
7565118ebe8SLucas Mateus Castro (alqotel)             if (access_type == MMU_DATA_STORE) {
7575118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DSISR] = 0x0A000000;
7585118ebe8SLucas Mateus Castro (alqotel)             } else {
7595118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DSISR] = 0x08000000;
7605118ebe8SLucas Mateus Castro (alqotel)             }
7615118ebe8SLucas Mateus Castro (alqotel)             break;
7625118ebe8SLucas Mateus Castro (alqotel)         case -4:
7635118ebe8SLucas Mateus Castro (alqotel)             /* Direct store exception */
7645118ebe8SLucas Mateus Castro (alqotel)             switch (type) {
7655118ebe8SLucas Mateus Castro (alqotel)             case ACCESS_FLOAT:
7665118ebe8SLucas Mateus Castro (alqotel)                 /* Floating point load/store */
7675118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_ALIGN;
7685118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = POWERPC_EXCP_ALIGN_FP;
7695118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
7705118ebe8SLucas Mateus Castro (alqotel)                 break;
7715118ebe8SLucas Mateus Castro (alqotel)             case ACCESS_RES:
7725118ebe8SLucas Mateus Castro (alqotel)                 /* lwarx, ldarx or stwcx. */
7735118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DSI;
7745118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 0;
7755118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
7765118ebe8SLucas Mateus Castro (alqotel)                 if (access_type == MMU_DATA_STORE) {
7775118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x06000000;
7785118ebe8SLucas Mateus Castro (alqotel)                 } else {
7795118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x04000000;
7805118ebe8SLucas Mateus Castro (alqotel)                 }
7815118ebe8SLucas Mateus Castro (alqotel)                 break;
7825118ebe8SLucas Mateus Castro (alqotel)             case ACCESS_EXT:
7835118ebe8SLucas Mateus Castro (alqotel)                 /* eciwx or ecowx */
7845118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_DSI;
7855118ebe8SLucas Mateus Castro (alqotel)                 env->error_code = 0;
7865118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
7875118ebe8SLucas Mateus Castro (alqotel)                 if (access_type == MMU_DATA_STORE) {
7885118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x06100000;
7895118ebe8SLucas Mateus Castro (alqotel)                 } else {
7905118ebe8SLucas Mateus Castro (alqotel)                     env->spr[SPR_DSISR] = 0x04100000;
7915118ebe8SLucas Mateus Castro (alqotel)                 }
7925118ebe8SLucas Mateus Castro (alqotel)                 break;
7935118ebe8SLucas Mateus Castro (alqotel)             default:
7945118ebe8SLucas Mateus Castro (alqotel)                 printf("DSI: invalid exception (%d)\n", ret);
7955118ebe8SLucas Mateus Castro (alqotel)                 cs->exception_index = POWERPC_EXCP_PROGRAM;
7969e9ca54cSBALATON Zoltan                 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
7975118ebe8SLucas Mateus Castro (alqotel)                 env->spr[SPR_DAR] = eaddr;
7985118ebe8SLucas Mateus Castro (alqotel)                 break;
7995118ebe8SLucas Mateus Castro (alqotel)             }
8005118ebe8SLucas Mateus Castro (alqotel)             break;
8015118ebe8SLucas Mateus Castro (alqotel)         }
8025118ebe8SLucas Mateus Castro (alqotel)     }
8035118ebe8SLucas Mateus Castro (alqotel)     return false;
8045118ebe8SLucas Mateus Castro (alqotel) }
8055118ebe8SLucas Mateus Castro (alqotel) 
8065118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/
8075118ebe8SLucas Mateus Castro (alqotel) 
ppc_xlate(PowerPCCPU * cpu,vaddr eaddr,MMUAccessType access_type,hwaddr * raddrp,int * psizep,int * protp,int mmu_idx,bool guest_visible)8085118ebe8SLucas Mateus Castro (alqotel) bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
8095118ebe8SLucas Mateus Castro (alqotel)                       hwaddr *raddrp, int *psizep, int *protp,
8105118ebe8SLucas Mateus Castro (alqotel)                       int mmu_idx, bool guest_visible)
8115118ebe8SLucas Mateus Castro (alqotel) {
8125118ebe8SLucas Mateus Castro (alqotel)     switch (cpu->env.mmu_model) {
8135118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64)
8145118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_3_00:
8155118ebe8SLucas Mateus Castro (alqotel)         if (ppc64_v3_radix(cpu)) {
8165118ebe8SLucas Mateus Castro (alqotel)             return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp,
8175118ebe8SLucas Mateus Castro (alqotel)                                      psizep, protp, mmu_idx, guest_visible);
8185118ebe8SLucas Mateus Castro (alqotel)         }
8195118ebe8SLucas Mateus Castro (alqotel)         /* fall through */
8205118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_64B:
8215118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_03:
8225118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_06:
8235118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_2_07:
8245118ebe8SLucas Mateus Castro (alqotel)         return ppc_hash64_xlate(cpu, eaddr, access_type,
8255118ebe8SLucas Mateus Castro (alqotel)                                 raddrp, psizep, protp, mmu_idx, guest_visible);
8265118ebe8SLucas Mateus Castro (alqotel) #endif
8275118ebe8SLucas Mateus Castro (alqotel) 
8285118ebe8SLucas Mateus Castro (alqotel)     case POWERPC_MMU_32B:
8295118ebe8SLucas Mateus Castro (alqotel)         return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp,
8305118ebe8SLucas Mateus Castro (alqotel)                                psizep, protp, mmu_idx, guest_visible);
831ba91e5d0SBALATON Zoltan     case POWERPC_MMU_BOOKE:
832ba91e5d0SBALATON Zoltan     case POWERPC_MMU_BOOKE206:
833ba91e5d0SBALATON Zoltan         return ppc_booke_xlate(cpu, eaddr, access_type, raddrp,
834ba91e5d0SBALATON Zoltan                                psizep, protp, mmu_idx, guest_visible);
83558b01325SBALATON Zoltan     case POWERPC_MMU_SOFT_4xx:
83658b01325SBALATON Zoltan         return ppc_40x_xlate(cpu, eaddr, access_type, raddrp,
83758b01325SBALATON Zoltan                              psizep, protp, mmu_idx, guest_visible);
8386b9ea7f3SBALATON Zoltan     case POWERPC_MMU_SOFT_6xx:
8396b9ea7f3SBALATON Zoltan         return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp,
8406b9ea7f3SBALATON Zoltan                              psizep, protp, mmu_idx, guest_visible);
841c29f808aSBALATON Zoltan     case POWERPC_MMU_REAL:
842c29f808aSBALATON Zoltan         return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep,
843c29f808aSBALATON Zoltan                                    protp);
844cfd5c128SBALATON Zoltan     case POWERPC_MMU_MPC8xx:
845cfd5c128SBALATON Zoltan         cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n");
8465118ebe8SLucas Mateus Castro (alqotel)     default:
8476b9ea7f3SBALATON Zoltan         cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n");
8485118ebe8SLucas Mateus Castro (alqotel)     }
8495118ebe8SLucas Mateus Castro (alqotel) }
8505118ebe8SLucas Mateus Castro (alqotel) 
ppc_cpu_get_phys_page_debug(CPUState * cs,vaddr addr)8515118ebe8SLucas Mateus Castro (alqotel) hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
8525118ebe8SLucas Mateus Castro (alqotel) {
8535118ebe8SLucas Mateus Castro (alqotel)     PowerPCCPU *cpu = POWERPC_CPU(cs);
8545118ebe8SLucas Mateus Castro (alqotel)     hwaddr raddr;
8555118ebe8SLucas Mateus Castro (alqotel)     int s, p;
8565118ebe8SLucas Mateus Castro (alqotel) 
8575118ebe8SLucas Mateus Castro (alqotel)     /*
8585118ebe8SLucas Mateus Castro (alqotel)      * Some MMUs have separate TLBs for code and data. If we only
8595118ebe8SLucas Mateus Castro (alqotel)      * try an MMU_DATA_LOAD, we may not be able to read instructions
8605118ebe8SLucas Mateus Castro (alqotel)      * mapped by code TLBs, so we also try a MMU_INST_FETCH.
8615118ebe8SLucas Mateus Castro (alqotel)      */
8625118ebe8SLucas Mateus Castro (alqotel)     if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
863fb00f730SRichard Henderson                   ppc_env_mmu_index(&cpu->env, false), false) ||
8645118ebe8SLucas Mateus Castro (alqotel)         ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
865fb00f730SRichard Henderson                   ppc_env_mmu_index(&cpu->env, true), false)) {
8665118ebe8SLucas Mateus Castro (alqotel)         return raddr & TARGET_PAGE_MASK;
8675118ebe8SLucas Mateus Castro (alqotel)     }
8685118ebe8SLucas Mateus Castro (alqotel)     return -1;
8695118ebe8SLucas Mateus Castro (alqotel) }
870