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 int key; /* Access key */ 45306b5320SBALATON Zoltan } mmu_ctx_t; 46306b5320SBALATON Zoltan 47d6ae8ec6SLucas Mateus Castro (alqotel) void ppc_store_sdr1(CPUPPCState *env, target_ulong value) 48d6ae8ec6SLucas Mateus Castro (alqotel) { 49d6ae8ec6SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = env_archcpu(env); 50d6ae8ec6SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); 51d6ae8ec6SLucas Mateus Castro (alqotel) assert(!cpu->env.has_hv_mode || !cpu->vhyp); 52d6ae8ec6SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64) 53d6ae8ec6SLucas Mateus Castro (alqotel) if (mmu_is_64bit(env->mmu_model)) { 54d6ae8ec6SLucas Mateus Castro (alqotel) target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE; 55d6ae8ec6SLucas Mateus Castro (alqotel) target_ulong htabsize = value & SDR_64_HTABSIZE; 56d6ae8ec6SLucas Mateus Castro (alqotel) 57d6ae8ec6SLucas Mateus Castro (alqotel) if (value & ~sdr_mask) { 58d6ae8ec6SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx 59d6ae8ec6SLucas Mateus Castro (alqotel) " set in SDR1", value & ~sdr_mask); 60d6ae8ec6SLucas Mateus Castro (alqotel) value &= sdr_mask; 61d6ae8ec6SLucas Mateus Castro (alqotel) } 62d6ae8ec6SLucas Mateus Castro (alqotel) if (htabsize > 28) { 63d6ae8ec6SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx 64d6ae8ec6SLucas Mateus Castro (alqotel) " stored in SDR1", htabsize); 65d6ae8ec6SLucas Mateus Castro (alqotel) return; 66d6ae8ec6SLucas Mateus Castro (alqotel) } 67d6ae8ec6SLucas Mateus Castro (alqotel) } 68d6ae8ec6SLucas Mateus Castro (alqotel) #endif /* defined(TARGET_PPC64) */ 69d6ae8ec6SLucas Mateus Castro (alqotel) /* FIXME: Should check for valid HTABMASK values in 32-bit case */ 70d6ae8ec6SLucas Mateus Castro (alqotel) env->spr[SPR_SDR1] = value; 71d6ae8ec6SLucas Mateus Castro (alqotel) } 72d6ae8ec6SLucas Mateus Castro (alqotel) 735118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/ 745118ebe8SLucas Mateus Castro (alqotel) /* PowerPC MMU emulation */ 755118ebe8SLucas Mateus Castro (alqotel) 765118ebe8SLucas Mateus Castro (alqotel) int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr, 775118ebe8SLucas Mateus Castro (alqotel) int way, int is_code) 785118ebe8SLucas Mateus Castro (alqotel) { 795118ebe8SLucas Mateus Castro (alqotel) int nr; 805118ebe8SLucas Mateus Castro (alqotel) 815118ebe8SLucas Mateus Castro (alqotel) /* Select TLB num in a way from address */ 825118ebe8SLucas Mateus Castro (alqotel) nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1); 835118ebe8SLucas Mateus Castro (alqotel) /* Select TLB way */ 845118ebe8SLucas Mateus Castro (alqotel) nr += env->tlb_per_way * way; 855fd257f5SBALATON Zoltan /* 6xx has separate TLBs for instructions and data */ 865fd257f5SBALATON Zoltan if (is_code) { 875118ebe8SLucas Mateus Castro (alqotel) nr += env->nb_tlb; 885118ebe8SLucas Mateus Castro (alqotel) } 895118ebe8SLucas Mateus Castro (alqotel) 905118ebe8SLucas Mateus Castro (alqotel) return nr; 915118ebe8SLucas Mateus Castro (alqotel) } 925118ebe8SLucas Mateus Castro (alqotel) 935118ebe8SLucas Mateus Castro (alqotel) /* Software driven TLB helpers */ 945118ebe8SLucas Mateus Castro (alqotel) 95691cf34fSBALATON Zoltan static int ppc6xx_tlb_check(CPUPPCState *env, 96691cf34fSBALATON Zoltan mmu_ctx_t *ctx, target_ulong eaddr, 97*cab21e2eSBALATON Zoltan MMUAccessType access_type, target_ulong ptem, 98*cab21e2eSBALATON Zoltan bool nx) 995118ebe8SLucas Mateus Castro (alqotel) { 1005118ebe8SLucas Mateus Castro (alqotel) ppc6xx_tlb_t *tlb; 101f8e0cc94SBALATON Zoltan target_ulong *pte1p; 102f8e0cc94SBALATON Zoltan int nr, best, way, ret; 103*cab21e2eSBALATON Zoltan bool is_code = (access_type == MMU_INST_FETCH); 1045118ebe8SLucas Mateus Castro (alqotel) 1055118ebe8SLucas Mateus Castro (alqotel) best = -1; 1065118ebe8SLucas Mateus Castro (alqotel) ret = -1; /* No TLB found */ 1075118ebe8SLucas Mateus Castro (alqotel) for (way = 0; way < env->nb_ways; way++) { 108*cab21e2eSBALATON Zoltan nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code); 1095118ebe8SLucas Mateus Castro (alqotel) tlb = &env->tlb.tlb6[nr]; 1105118ebe8SLucas Mateus Castro (alqotel) /* This test "emulates" the PTE index match for hardware TLBs */ 1115118ebe8SLucas Mateus Castro (alqotel) if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { 11256964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx 11356964585SCédric Le Goater " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n", 11456964585SCédric Le Goater nr, env->nb_tlb, 1155118ebe8SLucas Mateus Castro (alqotel) pte_is_valid(tlb->pte0) ? "valid" : "inval", 1165118ebe8SLucas Mateus Castro (alqotel) tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); 1175118ebe8SLucas Mateus Castro (alqotel) continue; 1185118ebe8SLucas Mateus Castro (alqotel) } 11956964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> " 12056964585SCédric Le Goater TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n", 12156964585SCédric Le Goater nr, env->nb_tlb, 1225118ebe8SLucas Mateus Castro (alqotel) pte_is_valid(tlb->pte0) ? "valid" : "inval", 1235118ebe8SLucas Mateus Castro (alqotel) tlb->EPN, eaddr, tlb->pte1, 1245118ebe8SLucas Mateus Castro (alqotel) access_type == MMU_DATA_STORE ? 'S' : 'L', 1255118ebe8SLucas Mateus Castro (alqotel) access_type == MMU_INST_FETCH ? 'I' : 'D'); 1260ce61ffaSBALATON Zoltan /* Check validity and table match */ 1270ce61ffaSBALATON Zoltan if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 || 128*cab21e2eSBALATON Zoltan (tlb->pte0 & PTE_PTEM_MASK) != ptem) { 1290ce61ffaSBALATON Zoltan continue; 1300ce61ffaSBALATON Zoltan } 1310ce61ffaSBALATON Zoltan /* all matches should have equal RPN, WIMG & PP */ 1320ce61ffaSBALATON Zoltan if (ctx->raddr != (hwaddr)-1ULL && 1330ce61ffaSBALATON Zoltan (ctx->raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) { 1340ce61ffaSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n"); 1350ce61ffaSBALATON Zoltan /* TLB inconsistency */ 1360ce61ffaSBALATON Zoltan continue; 1370ce61ffaSBALATON Zoltan } 1380ce61ffaSBALATON Zoltan /* Keep the matching PTE information */ 1395118ebe8SLucas Mateus Castro (alqotel) best = nr; 1400ce61ffaSBALATON Zoltan ctx->raddr = tlb->pte1; 1410ce61ffaSBALATON Zoltan ctx->prot = ppc_hash32_prot(ctx->key, tlb->pte1 & HPTE32_R_PP, nx); 1420ce61ffaSBALATON Zoltan if (check_prot_access_type(ctx->prot, access_type)) { 1430ce61ffaSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n"); 1445118ebe8SLucas Mateus Castro (alqotel) ret = 0; 1450ce61ffaSBALATON Zoltan break; 1460ce61ffaSBALATON Zoltan } else { 1470ce61ffaSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); 1480ce61ffaSBALATON Zoltan ret = -2; 1495118ebe8SLucas Mateus Castro (alqotel) } 1505118ebe8SLucas Mateus Castro (alqotel) } 1515118ebe8SLucas Mateus Castro (alqotel) if (best != -1) { 152883f2c59SPhilippe Mathieu-Daudé qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx 15356964585SCédric Le Goater " prot=%01x ret=%d\n", 1545118ebe8SLucas Mateus Castro (alqotel) ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); 1555118ebe8SLucas Mateus Castro (alqotel) /* Update page flags */ 156f8e0cc94SBALATON Zoltan pte1p = &env->tlb.tlb6[best].pte1; 157f8e0cc94SBALATON Zoltan *pte1p |= 0x00000100; /* Update accessed flag */ 158f8e0cc94SBALATON Zoltan if (!(*pte1p & 0x00000080)) { 159f8e0cc94SBALATON Zoltan if (access_type == MMU_DATA_STORE && ret == 0) { 160f8e0cc94SBALATON Zoltan /* Update changed flag */ 161f8e0cc94SBALATON Zoltan *pte1p |= 0x00000080; 162f8e0cc94SBALATON Zoltan } else { 163f8e0cc94SBALATON Zoltan /* Force page fault for first write access */ 164f8e0cc94SBALATON Zoltan ctx->prot &= ~PAGE_WRITE; 165f8e0cc94SBALATON Zoltan } 166f8e0cc94SBALATON Zoltan } 1675118ebe8SLucas Mateus Castro (alqotel) } 168*cab21e2eSBALATON Zoltan if (ret == -1) { 169*cab21e2eSBALATON Zoltan int r = is_code ? SPR_ICMP : SPR_DCMP; 170*cab21e2eSBALATON Zoltan env->spr[r] = ptem; 171*cab21e2eSBALATON Zoltan } 1720af20f35SBALATON Zoltan #if defined(DUMP_PAGE_TABLES) 1730af20f35SBALATON Zoltan if (qemu_loglevel_mask(CPU_LOG_MMU)) { 1740af20f35SBALATON Zoltan CPUState *cs = env_cpu(env); 1750af20f35SBALATON Zoltan hwaddr base = ppc_hash32_hpt_base(env_archcpu(env)); 1760af20f35SBALATON Zoltan hwaddr len = ppc_hash32_hpt_mask(env_archcpu(env)) + 0x80; 1770af20f35SBALATON Zoltan uint32_t a0, a1, a2, a3; 1785118ebe8SLucas Mateus Castro (alqotel) 1790af20f35SBALATON Zoltan qemu_log("Page table: " HWADDR_FMT_plx " len " HWADDR_FMT_plx "\n", 1800af20f35SBALATON Zoltan base, len); 1810af20f35SBALATON Zoltan for (hwaddr curaddr = base; curaddr < base + len; curaddr += 16) { 1820af20f35SBALATON Zoltan a0 = ldl_phys(cs->as, curaddr); 1830af20f35SBALATON Zoltan a1 = ldl_phys(cs->as, curaddr + 4); 1840af20f35SBALATON Zoltan a2 = ldl_phys(cs->as, curaddr + 8); 1850af20f35SBALATON Zoltan a3 = ldl_phys(cs->as, curaddr + 12); 1860af20f35SBALATON Zoltan if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) { 1870af20f35SBALATON Zoltan qemu_log(HWADDR_FMT_plx ": %08x %08x %08x %08x\n", 1880af20f35SBALATON Zoltan curaddr, a0, a1, a2, a3); 1890af20f35SBALATON Zoltan } 1900af20f35SBALATON Zoltan } 1910af20f35SBALATON Zoltan } 1920af20f35SBALATON Zoltan #endif 1935118ebe8SLucas Mateus Castro (alqotel) return ret; 1945118ebe8SLucas Mateus Castro (alqotel) } 1955118ebe8SLucas Mateus Castro (alqotel) 1965118ebe8SLucas Mateus Castro (alqotel) /* Perform BAT hit & translation */ 1975118ebe8SLucas Mateus Castro (alqotel) static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp, 1985118ebe8SLucas Mateus Castro (alqotel) int *validp, int *protp, target_ulong *BATu, 1995118ebe8SLucas Mateus Castro (alqotel) target_ulong *BATl) 2005118ebe8SLucas Mateus Castro (alqotel) { 2015118ebe8SLucas Mateus Castro (alqotel) target_ulong bl; 2025118ebe8SLucas Mateus Castro (alqotel) int pp, valid, prot; 2035118ebe8SLucas Mateus Castro (alqotel) 2045118ebe8SLucas Mateus Castro (alqotel) bl = (*BATu & 0x00001FFC) << 15; 2055118ebe8SLucas Mateus Castro (alqotel) valid = 0; 2065118ebe8SLucas Mateus Castro (alqotel) prot = 0; 207d41ccf6eSVíctor Colombo if ((!FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000002)) || 208d41ccf6eSVíctor Colombo (FIELD_EX64(env->msr, MSR, PR) && (*BATu & 0x00000001))) { 2095118ebe8SLucas Mateus Castro (alqotel) valid = 1; 2105118ebe8SLucas Mateus Castro (alqotel) pp = *BATl & 0x00000003; 2115118ebe8SLucas Mateus Castro (alqotel) if (pp != 0) { 2125118ebe8SLucas Mateus Castro (alqotel) prot = PAGE_READ | PAGE_EXEC; 2135118ebe8SLucas Mateus Castro (alqotel) if (pp == 0x2) { 2145118ebe8SLucas Mateus Castro (alqotel) prot |= PAGE_WRITE; 2155118ebe8SLucas Mateus Castro (alqotel) } 2165118ebe8SLucas Mateus Castro (alqotel) } 2175118ebe8SLucas Mateus Castro (alqotel) } 2185118ebe8SLucas Mateus Castro (alqotel) *blp = bl; 2195118ebe8SLucas Mateus Castro (alqotel) *validp = valid; 2205118ebe8SLucas Mateus Castro (alqotel) *protp = prot; 2215118ebe8SLucas Mateus Castro (alqotel) } 2225118ebe8SLucas Mateus Castro (alqotel) 2235118ebe8SLucas Mateus Castro (alqotel) static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, 2245118ebe8SLucas Mateus Castro (alqotel) target_ulong virtual, MMUAccessType access_type) 2255118ebe8SLucas Mateus Castro (alqotel) { 2265118ebe8SLucas Mateus Castro (alqotel) target_ulong *BATlt, *BATut, *BATu, *BATl; 2275118ebe8SLucas Mateus Castro (alqotel) target_ulong BEPIl, BEPIu, bl; 2285118ebe8SLucas Mateus Castro (alqotel) int i, valid, prot; 2295118ebe8SLucas Mateus Castro (alqotel) int ret = -1; 2305118ebe8SLucas Mateus Castro (alqotel) bool ifetch = access_type == MMU_INST_FETCH; 2315118ebe8SLucas Mateus Castro (alqotel) 23256964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__, 2335118ebe8SLucas Mateus Castro (alqotel) ifetch ? 'I' : 'D', virtual); 2345118ebe8SLucas Mateus Castro (alqotel) if (ifetch) { 2355118ebe8SLucas Mateus Castro (alqotel) BATlt = env->IBAT[1]; 2365118ebe8SLucas Mateus Castro (alqotel) BATut = env->IBAT[0]; 2375118ebe8SLucas Mateus Castro (alqotel) } else { 2385118ebe8SLucas Mateus Castro (alqotel) BATlt = env->DBAT[1]; 2395118ebe8SLucas Mateus Castro (alqotel) BATut = env->DBAT[0]; 2405118ebe8SLucas Mateus Castro (alqotel) } 2415118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < env->nb_BATs; i++) { 2425118ebe8SLucas Mateus Castro (alqotel) BATu = &BATut[i]; 2435118ebe8SLucas Mateus Castro (alqotel) BATl = &BATlt[i]; 2445118ebe8SLucas Mateus Castro (alqotel) BEPIu = *BATu & 0xF0000000; 2455118ebe8SLucas Mateus Castro (alqotel) BEPIl = *BATu & 0x0FFE0000; 2465118ebe8SLucas Mateus Castro (alqotel) bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); 24756964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu " 24856964585SCédric Le Goater TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__, 2495118ebe8SLucas Mateus Castro (alqotel) ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); 2505118ebe8SLucas Mateus Castro (alqotel) if ((virtual & 0xF0000000) == BEPIu && 2515118ebe8SLucas Mateus Castro (alqotel) ((virtual & 0x0FFE0000) & ~bl) == BEPIl) { 2525118ebe8SLucas Mateus Castro (alqotel) /* BAT matches */ 2535118ebe8SLucas Mateus Castro (alqotel) if (valid != 0) { 2545118ebe8SLucas Mateus Castro (alqotel) /* Get physical address */ 2555118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = (*BATl & 0xF0000000) | 2565118ebe8SLucas Mateus Castro (alqotel) ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) | 2575118ebe8SLucas Mateus Castro (alqotel) (virtual & 0x0001F000); 2585118ebe8SLucas Mateus Castro (alqotel) /* Compute access rights */ 2595118ebe8SLucas Mateus Castro (alqotel) ctx->prot = prot; 260cd1038ecSBALATON Zoltan if (check_prot_access_type(ctx->prot, access_type)) { 261883f2c59SPhilippe Mathieu-Daudé qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx 26256964585SCédric Le Goater " prot=%c%c\n", i, ctx->raddr, 26356964585SCédric Le Goater ctx->prot & PAGE_READ ? 'R' : '-', 2645118ebe8SLucas Mateus Castro (alqotel) ctx->prot & PAGE_WRITE ? 'W' : '-'); 265cd1038ecSBALATON Zoltan ret = 0; 266cd1038ecSBALATON Zoltan } else { 267cd1038ecSBALATON Zoltan ret = -2; 2685118ebe8SLucas Mateus Castro (alqotel) } 2695118ebe8SLucas Mateus Castro (alqotel) break; 2705118ebe8SLucas Mateus Castro (alqotel) } 2715118ebe8SLucas Mateus Castro (alqotel) } 2725118ebe8SLucas Mateus Castro (alqotel) } 2735118ebe8SLucas Mateus Castro (alqotel) if (ret < 0) { 2745118ebe8SLucas Mateus Castro (alqotel) if (qemu_log_enabled()) { 27556964585SCédric Le Goater qemu_log_mask(CPU_LOG_MMU, "no BAT match for " 27656964585SCédric Le Goater TARGET_FMT_lx ":\n", virtual); 2775118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < 4; i++) { 2785118ebe8SLucas Mateus Castro (alqotel) BATu = &BATut[i]; 2795118ebe8SLucas Mateus Castro (alqotel) BATl = &BATlt[i]; 2805118ebe8SLucas Mateus Castro (alqotel) BEPIu = *BATu & 0xF0000000; 2815118ebe8SLucas Mateus Castro (alqotel) BEPIl = *BATu & 0x0FFE0000; 2825118ebe8SLucas Mateus Castro (alqotel) bl = (*BATu & 0x00001FFC) << 15; 28347bededcSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx 28447bededcSBALATON Zoltan " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx 28547bededcSBALATON Zoltan "\n\t" TARGET_FMT_lx " " TARGET_FMT_lx " " 28647bededcSBALATON Zoltan TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D', 28747bededcSBALATON Zoltan i, virtual, *BATu, *BATl, BEPIu, BEPIl, bl); 2885118ebe8SLucas Mateus Castro (alqotel) } 2895118ebe8SLucas Mateus Castro (alqotel) } 2905118ebe8SLucas Mateus Castro (alqotel) } 2915118ebe8SLucas Mateus Castro (alqotel) /* No hit */ 2925118ebe8SLucas Mateus Castro (alqotel) return ret; 2935118ebe8SLucas Mateus Castro (alqotel) } 2945118ebe8SLucas Mateus Castro (alqotel) 295269d6f00SBALATON Zoltan static int mmu6xx_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, 296f6f8838bSBALATON Zoltan target_ulong eaddr, hwaddr *hashp, 297269d6f00SBALATON Zoltan MMUAccessType access_type, int type) 2985118ebe8SLucas Mateus Castro (alqotel) { 2995118ebe8SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = env_archcpu(env); 3005118ebe8SLucas Mateus Castro (alqotel) hwaddr hash; 301*cab21e2eSBALATON Zoltan target_ulong vsid, sr, pgidx, ptem; 302aaf5845bSBALATON Zoltan bool pr, ds, nx; 3035118ebe8SLucas Mateus Castro (alqotel) 304269d6f00SBALATON Zoltan /* First try to find a BAT entry if there are any */ 305269d6f00SBALATON Zoltan if (env->nb_BATs && get_bat_6xx_tlb(env, ctx, eaddr, access_type) == 0) { 306269d6f00SBALATON Zoltan return 0; 307269d6f00SBALATON Zoltan } 308269d6f00SBALATON Zoltan 309269d6f00SBALATON Zoltan /* Perform segment based translation when no BATs matched */ 310d41ccf6eSVíctor Colombo pr = FIELD_EX64(env->msr, MSR, PR); 3115118ebe8SLucas Mateus Castro (alqotel) 3125118ebe8SLucas Mateus Castro (alqotel) sr = env->sr[eaddr >> 28]; 313d41ccf6eSVíctor Colombo ctx->key = (((sr & 0x20000000) && pr) || 314d41ccf6eSVíctor Colombo ((sr & 0x40000000) && !pr)) ? 1 : 0; 315aaf5845bSBALATON Zoltan ds = sr & SR32_T; 316691cf34fSBALATON Zoltan nx = sr & SR32_NX; 317691cf34fSBALATON Zoltan vsid = sr & SR32_VSID; 3185118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(CPU_LOG_MMU, 3195118ebe8SLucas Mateus Castro (alqotel) "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx 3205118ebe8SLucas Mateus Castro (alqotel) " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx 3215118ebe8SLucas Mateus Castro (alqotel) " ir=%d dr=%d pr=%d %d t=%d\n", 322d41ccf6eSVíctor Colombo eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, 323e4eea6efSVíctor Colombo (int)FIELD_EX64(env->msr, MSR, IR), 324e4eea6efSVíctor Colombo (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0, 32556964585SCédric Le Goater access_type == MMU_DATA_STORE, type); 3268abd6d42SBALATON Zoltan pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS; 3275118ebe8SLucas Mateus Castro (alqotel) hash = vsid ^ pgidx; 328*cab21e2eSBALATON Zoltan ptem = (vsid << 7) | (pgidx >> 10); /* Virtual segment ID | API */ 3295118ebe8SLucas Mateus Castro (alqotel) 33047bededcSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid " 331691cf34fSBALATON Zoltan TARGET_FMT_lx "\n", ctx->key, ds, nx, vsid); 3325118ebe8SLucas Mateus Castro (alqotel) if (!ds) { 3335118ebe8SLucas Mateus Castro (alqotel) /* Check if instruction fetch is allowed, if needed */ 334691cf34fSBALATON Zoltan if (type == ACCESS_CODE && nx) { 335f1418bdeSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "No access allowed\n"); 336f1418bdeSBALATON Zoltan return -3; 337f1418bdeSBALATON Zoltan } 3385118ebe8SLucas Mateus Castro (alqotel) /* Page address translation */ 339f1418bdeSBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx " htab_mask " 340f1418bdeSBALATON Zoltan HWADDR_FMT_plx " hash " HWADDR_FMT_plx "\n", 3415118ebe8SLucas Mateus Castro (alqotel) ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash); 342f6f8838bSBALATON Zoltan *hashp = hash; 3435118ebe8SLucas Mateus Castro (alqotel) 3445118ebe8SLucas Mateus Castro (alqotel) /* Initialize real address with an invalid value */ 3455118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = (hwaddr)-1ULL; 3465118ebe8SLucas Mateus Castro (alqotel) /* Software TLB search */ 347*cab21e2eSBALATON Zoltan return ppc6xx_tlb_check(env, ctx, eaddr, access_type, ptem, nx); 348f3f66a31SBALATON Zoltan } 3495118ebe8SLucas Mateus Castro (alqotel) 350f3f66a31SBALATON Zoltan /* Direct-store segment : absolutely *BUGGY* for now */ 351f3f66a31SBALATON Zoltan qemu_log_mask(CPU_LOG_MMU, "direct store...\n"); 3525118ebe8SLucas Mateus Castro (alqotel) switch (type) { 3535118ebe8SLucas Mateus Castro (alqotel) case ACCESS_INT: 3545118ebe8SLucas Mateus Castro (alqotel) /* Integer load/store : only access allowed */ 3555118ebe8SLucas Mateus Castro (alqotel) break; 3565118ebe8SLucas Mateus Castro (alqotel) case ACCESS_CACHE: 3575118ebe8SLucas Mateus Castro (alqotel) /* 3585118ebe8SLucas Mateus Castro (alqotel) * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi 3595118ebe8SLucas Mateus Castro (alqotel) * 3605118ebe8SLucas Mateus Castro (alqotel) * Should make the instruction do no-op. As it already do 3615118ebe8SLucas Mateus Castro (alqotel) * no-op, it's quite easy :-) 3625118ebe8SLucas Mateus Castro (alqotel) */ 3635118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = eaddr; 3645118ebe8SLucas Mateus Castro (alqotel) return 0; 36540df08d2SBALATON Zoltan case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */ 36640df08d2SBALATON Zoltan case ACCESS_FLOAT: /* Floating point load/store */ 36740df08d2SBALATON Zoltan case ACCESS_RES: /* lwarx, ldarx or srwcx. */ 36840df08d2SBALATON Zoltan case ACCESS_EXT: /* eciwx or ecowx */ 3695118ebe8SLucas Mateus Castro (alqotel) return -4; 3705118ebe8SLucas Mateus Castro (alqotel) } 3715118ebe8SLucas Mateus Castro (alqotel) if ((access_type == MMU_DATA_STORE || ctx->key != 1) && 3725118ebe8SLucas Mateus Castro (alqotel) (access_type == MMU_DATA_LOAD || ctx->key != 0)) { 3735118ebe8SLucas Mateus Castro (alqotel) ctx->raddr = eaddr; 374f3f66a31SBALATON Zoltan return 2; 3755118ebe8SLucas Mateus Castro (alqotel) } 376f3f66a31SBALATON Zoltan return -2; 3775118ebe8SLucas Mateus Castro (alqotel) } 3785118ebe8SLucas Mateus Castro (alqotel) 3795118ebe8SLucas Mateus Castro (alqotel) static const char *book3e_tsize_to_str[32] = { 3805118ebe8SLucas Mateus Castro (alqotel) "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", 3815118ebe8SLucas Mateus Castro (alqotel) "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", 3825118ebe8SLucas Mateus Castro (alqotel) "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G", 3835118ebe8SLucas Mateus Castro (alqotel) "1T", "2T" 3845118ebe8SLucas Mateus Castro (alqotel) }; 3855118ebe8SLucas Mateus Castro (alqotel) 3865118ebe8SLucas Mateus Castro (alqotel) static void mmubooke_dump_mmu(CPUPPCState *env) 3875118ebe8SLucas Mateus Castro (alqotel) { 3885118ebe8SLucas Mateus Castro (alqotel) ppcemb_tlb_t *entry; 3895118ebe8SLucas Mateus Castro (alqotel) int i; 3905118ebe8SLucas Mateus Castro (alqotel) 39105739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM 3925118ebe8SLucas Mateus Castro (alqotel) if (kvm_enabled() && !env->kvm_sw_tlb) { 3935118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Cannot access KVM TLB\n"); 3945118ebe8SLucas Mateus Castro (alqotel) return; 3955118ebe8SLucas Mateus Castro (alqotel) } 39605739977SPhilippe Mathieu-Daudé #endif 3975118ebe8SLucas Mateus Castro (alqotel) 3985118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nTLB:\n"); 3995118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Effective Physical Size PID Prot " 4005118ebe8SLucas Mateus Castro (alqotel) "Attr\n"); 4015118ebe8SLucas Mateus Castro (alqotel) 4025118ebe8SLucas Mateus Castro (alqotel) entry = &env->tlb.tlbe[0]; 4035118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < env->nb_tlb; i++, entry++) { 4045118ebe8SLucas Mateus Castro (alqotel) hwaddr ea, pa; 4055118ebe8SLucas Mateus Castro (alqotel) target_ulong mask; 4065118ebe8SLucas Mateus Castro (alqotel) uint64_t size = (uint64_t)entry->size; 4075118ebe8SLucas Mateus Castro (alqotel) char size_buf[20]; 4085118ebe8SLucas Mateus Castro (alqotel) 4095118ebe8SLucas Mateus Castro (alqotel) /* Check valid flag */ 4105118ebe8SLucas Mateus Castro (alqotel) if (!(entry->prot & PAGE_VALID)) { 4115118ebe8SLucas Mateus Castro (alqotel) continue; 4125118ebe8SLucas Mateus Castro (alqotel) } 4135118ebe8SLucas Mateus Castro (alqotel) 4145118ebe8SLucas Mateus Castro (alqotel) mask = ~(entry->size - 1); 4155118ebe8SLucas Mateus Castro (alqotel) ea = entry->EPN & mask; 4165118ebe8SLucas Mateus Castro (alqotel) pa = entry->RPN & mask; 4175118ebe8SLucas Mateus Castro (alqotel) /* Extend the physical address to 36 bits */ 4185118ebe8SLucas Mateus Castro (alqotel) pa |= (hwaddr)(entry->RPN & 0xF) << 32; 4195118ebe8SLucas Mateus Castro (alqotel) if (size >= 1 * MiB) { 4205118ebe8SLucas Mateus Castro (alqotel) snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB); 4215118ebe8SLucas Mateus Castro (alqotel) } else { 4225118ebe8SLucas Mateus Castro (alqotel) snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB); 4235118ebe8SLucas Mateus Castro (alqotel) } 4245118ebe8SLucas Mateus Castro (alqotel) qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n", 4255118ebe8SLucas Mateus Castro (alqotel) (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID, 4265118ebe8SLucas Mateus Castro (alqotel) entry->prot, entry->attr); 4275118ebe8SLucas Mateus Castro (alqotel) } 4285118ebe8SLucas Mateus Castro (alqotel) 4295118ebe8SLucas Mateus Castro (alqotel) } 4305118ebe8SLucas Mateus Castro (alqotel) 4315118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset, 4325118ebe8SLucas Mateus Castro (alqotel) int tlbsize) 4335118ebe8SLucas Mateus Castro (alqotel) { 4345118ebe8SLucas Mateus Castro (alqotel) ppcmas_tlb_t *entry; 4355118ebe8SLucas Mateus Castro (alqotel) int i; 4365118ebe8SLucas Mateus Castro (alqotel) 4375118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nTLB%d:\n", tlbn); 4385118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Effective Physical Size TID TS SRWX" 4395118ebe8SLucas Mateus Castro (alqotel) " URWX WIMGE U0123\n"); 4405118ebe8SLucas Mateus Castro (alqotel) 4415118ebe8SLucas Mateus Castro (alqotel) entry = &env->tlb.tlbm[offset]; 4425118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < tlbsize; i++, entry++) { 4435118ebe8SLucas Mateus Castro (alqotel) hwaddr ea, pa, size; 4445118ebe8SLucas Mateus Castro (alqotel) int tsize; 4455118ebe8SLucas Mateus Castro (alqotel) 4465118ebe8SLucas Mateus Castro (alqotel) if (!(entry->mas1 & MAS1_VALID)) { 4475118ebe8SLucas Mateus Castro (alqotel) continue; 4485118ebe8SLucas Mateus Castro (alqotel) } 4495118ebe8SLucas Mateus Castro (alqotel) 4505118ebe8SLucas Mateus Castro (alqotel) tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; 4515118ebe8SLucas Mateus Castro (alqotel) size = 1024ULL << tsize; 4525118ebe8SLucas Mateus Castro (alqotel) ea = entry->mas2 & ~(size - 1); 4535118ebe8SLucas Mateus Castro (alqotel) pa = entry->mas7_3 & ~(size - 1); 4545118ebe8SLucas Mateus Castro (alqotel) 4555118ebe8SLucas Mateus Castro (alqotel) qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c" 4565118ebe8SLucas Mateus Castro (alqotel) " U%c%c%c %c%c%c%c%c U%c%c%c%c\n", 4575118ebe8SLucas Mateus Castro (alqotel) (uint64_t)ea, (uint64_t)pa, 4585118ebe8SLucas Mateus Castro (alqotel) book3e_tsize_to_str[tsize], 4595118ebe8SLucas Mateus Castro (alqotel) (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT, 4605118ebe8SLucas Mateus Castro (alqotel) (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT, 4615118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_SR ? 'R' : '-', 4625118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_SW ? 'W' : '-', 4635118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_SX ? 'X' : '-', 4645118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_UR ? 'R' : '-', 4655118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_UW ? 'W' : '-', 4665118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_UX ? 'X' : '-', 4675118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_W ? 'W' : '-', 4685118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_I ? 'I' : '-', 4695118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_M ? 'M' : '-', 4705118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_G ? 'G' : '-', 4715118ebe8SLucas Mateus Castro (alqotel) entry->mas2 & MAS2_E ? 'E' : '-', 4725118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U0 ? '0' : '-', 4735118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U1 ? '1' : '-', 4745118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U2 ? '2' : '-', 4755118ebe8SLucas Mateus Castro (alqotel) entry->mas7_3 & MAS3_U3 ? '3' : '-'); 4765118ebe8SLucas Mateus Castro (alqotel) } 4775118ebe8SLucas Mateus Castro (alqotel) } 4785118ebe8SLucas Mateus Castro (alqotel) 4795118ebe8SLucas Mateus Castro (alqotel) static void mmubooke206_dump_mmu(CPUPPCState *env) 4805118ebe8SLucas Mateus Castro (alqotel) { 4815118ebe8SLucas Mateus Castro (alqotel) int offset = 0; 4825118ebe8SLucas Mateus Castro (alqotel) int i; 4835118ebe8SLucas Mateus Castro (alqotel) 48405739977SPhilippe Mathieu-Daudé #ifdef CONFIG_KVM 4855118ebe8SLucas Mateus Castro (alqotel) if (kvm_enabled() && !env->kvm_sw_tlb) { 4865118ebe8SLucas Mateus Castro (alqotel) qemu_printf("Cannot access KVM TLB\n"); 4875118ebe8SLucas Mateus Castro (alqotel) return; 4885118ebe8SLucas Mateus Castro (alqotel) } 48905739977SPhilippe Mathieu-Daudé #endif 4905118ebe8SLucas Mateus Castro (alqotel) 4915118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < BOOKE206_MAX_TLBN; i++) { 4925118ebe8SLucas Mateus Castro (alqotel) int size = booke206_tlb_size(env, i); 4935118ebe8SLucas Mateus Castro (alqotel) 4945118ebe8SLucas Mateus Castro (alqotel) if (size == 0) { 4955118ebe8SLucas Mateus Castro (alqotel) continue; 4965118ebe8SLucas Mateus Castro (alqotel) } 4975118ebe8SLucas Mateus Castro (alqotel) 4985118ebe8SLucas Mateus Castro (alqotel) mmubooke206_dump_one_tlb(env, i, offset, size); 4995118ebe8SLucas Mateus Castro (alqotel) offset += size; 5005118ebe8SLucas Mateus Castro (alqotel) } 5015118ebe8SLucas Mateus Castro (alqotel) } 5025118ebe8SLucas Mateus Castro (alqotel) 5035118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_BATs(CPUPPCState *env, int type) 5045118ebe8SLucas Mateus Castro (alqotel) { 5055118ebe8SLucas Mateus Castro (alqotel) target_ulong *BATlt, *BATut, *BATu, *BATl; 5065118ebe8SLucas Mateus Castro (alqotel) target_ulong BEPIl, BEPIu, bl; 5075118ebe8SLucas Mateus Castro (alqotel) int i; 5085118ebe8SLucas Mateus Castro (alqotel) 5095118ebe8SLucas Mateus Castro (alqotel) switch (type) { 5105118ebe8SLucas Mateus Castro (alqotel) case ACCESS_CODE: 5115118ebe8SLucas Mateus Castro (alqotel) BATlt = env->IBAT[1]; 5125118ebe8SLucas Mateus Castro (alqotel) BATut = env->IBAT[0]; 5135118ebe8SLucas Mateus Castro (alqotel) break; 5145118ebe8SLucas Mateus Castro (alqotel) default: 5155118ebe8SLucas Mateus Castro (alqotel) BATlt = env->DBAT[1]; 5165118ebe8SLucas Mateus Castro (alqotel) BATut = env->DBAT[0]; 5175118ebe8SLucas Mateus Castro (alqotel) break; 5185118ebe8SLucas Mateus Castro (alqotel) } 5195118ebe8SLucas Mateus Castro (alqotel) 5205118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < env->nb_BATs; i++) { 5215118ebe8SLucas Mateus Castro (alqotel) BATu = &BATut[i]; 5225118ebe8SLucas Mateus Castro (alqotel) BATl = &BATlt[i]; 5235118ebe8SLucas Mateus Castro (alqotel) BEPIu = *BATu & 0xF0000000; 5245118ebe8SLucas Mateus Castro (alqotel) BEPIl = *BATu & 0x0FFE0000; 5255118ebe8SLucas Mateus Castro (alqotel) bl = (*BATu & 0x00001FFC) << 15; 5265118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%s BAT%d BATu " TARGET_FMT_lx 5275118ebe8SLucas Mateus Castro (alqotel) " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " 5285118ebe8SLucas Mateus Castro (alqotel) TARGET_FMT_lx " " TARGET_FMT_lx "\n", 5295118ebe8SLucas Mateus Castro (alqotel) type == ACCESS_CODE ? "code" : "data", i, 5305118ebe8SLucas Mateus Castro (alqotel) *BATu, *BATl, BEPIu, BEPIl, bl); 5315118ebe8SLucas Mateus Castro (alqotel) } 5325118ebe8SLucas Mateus Castro (alqotel) } 5335118ebe8SLucas Mateus Castro (alqotel) 5345118ebe8SLucas Mateus Castro (alqotel) static void mmu6xx_dump_mmu(CPUPPCState *env) 5355118ebe8SLucas Mateus Castro (alqotel) { 5365118ebe8SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = env_archcpu(env); 5375118ebe8SLucas Mateus Castro (alqotel) ppc6xx_tlb_t *tlb; 5385118ebe8SLucas Mateus Castro (alqotel) target_ulong sr; 5395118ebe8SLucas Mateus Castro (alqotel) int type, way, entry, i; 5405118ebe8SLucas Mateus Castro (alqotel) 5415118ebe8SLucas Mateus Castro (alqotel) qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu)); 5425118ebe8SLucas Mateus Castro (alqotel) qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu)); 5435118ebe8SLucas Mateus Castro (alqotel) 5445118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nSegment registers:\n"); 5455118ebe8SLucas Mateus Castro (alqotel) for (i = 0; i < 32; i++) { 5465118ebe8SLucas Mateus Castro (alqotel) sr = env->sr[i]; 5475118ebe8SLucas Mateus Castro (alqotel) if (sr & 0x80000000) { 5485118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x " 5495118ebe8SLucas Mateus Castro (alqotel) "CNTLR_SPEC=0x%05x\n", i, 5505118ebe8SLucas Mateus Castro (alqotel) sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0, 5515118ebe8SLucas Mateus Castro (alqotel) sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF), 5525118ebe8SLucas Mateus Castro (alqotel) (uint32_t)(sr & 0xFFFFF)); 5535118ebe8SLucas Mateus Castro (alqotel) } else { 5545118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i, 5555118ebe8SLucas Mateus Castro (alqotel) sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0, 5565118ebe8SLucas Mateus Castro (alqotel) sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0, 5575118ebe8SLucas Mateus Castro (alqotel) (uint32_t)(sr & 0x00FFFFFF)); 5585118ebe8SLucas Mateus Castro (alqotel) } 5595118ebe8SLucas Mateus Castro (alqotel) } 5605118ebe8SLucas Mateus Castro (alqotel) 5615118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nBATs:\n"); 5625118ebe8SLucas Mateus Castro (alqotel) mmu6xx_dump_BATs(env, ACCESS_INT); 5635118ebe8SLucas Mateus Castro (alqotel) mmu6xx_dump_BATs(env, ACCESS_CODE); 5645118ebe8SLucas Mateus Castro (alqotel) 5655118ebe8SLucas Mateus Castro (alqotel) qemu_printf("\nTLBs [EPN EPN + SIZE]\n"); 5665118ebe8SLucas Mateus Castro (alqotel) for (type = 0; type < 2; type++) { 5675118ebe8SLucas Mateus Castro (alqotel) for (way = 0; way < env->nb_ways; way++) { 5685118ebe8SLucas Mateus Castro (alqotel) for (entry = env->nb_tlb * type + env->tlb_per_way * way; 5695118ebe8SLucas Mateus Castro (alqotel) entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1)); 5705118ebe8SLucas Mateus Castro (alqotel) entry++) { 5715118ebe8SLucas Mateus Castro (alqotel) 5725118ebe8SLucas Mateus Castro (alqotel) tlb = &env->tlb.tlb6[entry]; 5735118ebe8SLucas Mateus Castro (alqotel) qemu_printf("%s TLB %02d/%02d way:%d %s [" 5745118ebe8SLucas Mateus Castro (alqotel) TARGET_FMT_lx " " TARGET_FMT_lx "]\n", 5755118ebe8SLucas Mateus Castro (alqotel) type ? "code" : "data", entry % env->nb_tlb, 5765118ebe8SLucas Mateus Castro (alqotel) env->nb_tlb, way, 5775118ebe8SLucas Mateus Castro (alqotel) pte_is_valid(tlb->pte0) ? "valid" : "inval", 5785118ebe8SLucas Mateus Castro (alqotel) tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE); 5795118ebe8SLucas Mateus Castro (alqotel) } 5805118ebe8SLucas Mateus Castro (alqotel) } 5815118ebe8SLucas Mateus Castro (alqotel) } 5825118ebe8SLucas Mateus Castro (alqotel) } 5835118ebe8SLucas Mateus Castro (alqotel) 5845118ebe8SLucas Mateus Castro (alqotel) void dump_mmu(CPUPPCState *env) 5855118ebe8SLucas Mateus Castro (alqotel) { 5865118ebe8SLucas Mateus Castro (alqotel) switch (env->mmu_model) { 5875118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_BOOKE: 5885118ebe8SLucas Mateus Castro (alqotel) mmubooke_dump_mmu(env); 5895118ebe8SLucas Mateus Castro (alqotel) break; 5905118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_BOOKE206: 5915118ebe8SLucas Mateus Castro (alqotel) mmubooke206_dump_mmu(env); 5925118ebe8SLucas Mateus Castro (alqotel) break; 5935118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_SOFT_6xx: 5945118ebe8SLucas Mateus Castro (alqotel) mmu6xx_dump_mmu(env); 5955118ebe8SLucas Mateus Castro (alqotel) break; 5965118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64) 5975118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_64B: 5985118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_03: 5995118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_06: 6005118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_07: 6015118ebe8SLucas Mateus Castro (alqotel) dump_slb(env_archcpu(env)); 6025118ebe8SLucas Mateus Castro (alqotel) break; 6035118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_3_00: 6045118ebe8SLucas Mateus Castro (alqotel) if (ppc64_v3_radix(env_archcpu(env))) { 6055118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n", 6065118ebe8SLucas Mateus Castro (alqotel) __func__); 6075118ebe8SLucas Mateus Castro (alqotel) } else { 6085118ebe8SLucas Mateus Castro (alqotel) dump_slb(env_archcpu(env)); 6095118ebe8SLucas Mateus Castro (alqotel) } 6105118ebe8SLucas Mateus Castro (alqotel) break; 6115118ebe8SLucas Mateus Castro (alqotel) #endif 6125118ebe8SLucas Mateus Castro (alqotel) default: 6135118ebe8SLucas Mateus Castro (alqotel) qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__); 6145118ebe8SLucas Mateus Castro (alqotel) } 6155118ebe8SLucas Mateus Castro (alqotel) } 6165118ebe8SLucas Mateus Castro (alqotel) 617ba91e5d0SBALATON Zoltan 618c29f808aSBALATON Zoltan static bool ppc_real_mode_xlate(PowerPCCPU *cpu, vaddr eaddr, 619c29f808aSBALATON Zoltan MMUAccessType access_type, 620c29f808aSBALATON Zoltan hwaddr *raddrp, int *psizep, int *protp) 621c29f808aSBALATON Zoltan { 622c29f808aSBALATON Zoltan CPUPPCState *env = &cpu->env; 623c29f808aSBALATON Zoltan 624c29f808aSBALATON Zoltan if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR) 625c29f808aSBALATON Zoltan : !FIELD_EX64(env->msr, MSR, DR)) { 626c29f808aSBALATON Zoltan *raddrp = eaddr; 627c29f808aSBALATON Zoltan *protp = PAGE_RWX; 628c29f808aSBALATON Zoltan *psizep = TARGET_PAGE_BITS; 629c29f808aSBALATON Zoltan return true; 630c29f808aSBALATON Zoltan } else if (env->mmu_model == POWERPC_MMU_REAL) { 631c29f808aSBALATON Zoltan cpu_abort(CPU(cpu), "PowerPC in real mode shold not do translation\n"); 632c29f808aSBALATON Zoltan } 633c29f808aSBALATON Zoltan return false; 634c29f808aSBALATON Zoltan } 635c29f808aSBALATON Zoltan 63658b01325SBALATON Zoltan static bool ppc_40x_xlate(PowerPCCPU *cpu, vaddr eaddr, 63758b01325SBALATON Zoltan MMUAccessType access_type, 63858b01325SBALATON Zoltan hwaddr *raddrp, int *psizep, int *protp, 63958b01325SBALATON Zoltan int mmu_idx, bool guest_visible) 64058b01325SBALATON Zoltan { 64158b01325SBALATON Zoltan CPUState *cs = CPU(cpu); 64258b01325SBALATON Zoltan CPUPPCState *env = &cpu->env; 64358b01325SBALATON Zoltan int ret; 64458b01325SBALATON Zoltan 64558b01325SBALATON Zoltan if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) { 64658b01325SBALATON Zoltan return true; 64758b01325SBALATON Zoltan } 64858b01325SBALATON Zoltan 64958b01325SBALATON Zoltan ret = mmu40x_get_physical_address(env, raddrp, protp, eaddr, access_type); 65058b01325SBALATON Zoltan if (ret == 0) { 65158b01325SBALATON Zoltan *psizep = TARGET_PAGE_BITS; 65258b01325SBALATON Zoltan return true; 65358b01325SBALATON Zoltan } else if (!guest_visible) { 65458b01325SBALATON Zoltan return false; 65558b01325SBALATON Zoltan } 65658b01325SBALATON Zoltan 65758b01325SBALATON Zoltan log_cpu_state_mask(CPU_LOG_MMU, cs, 0); 65858b01325SBALATON Zoltan if (access_type == MMU_INST_FETCH) { 65958b01325SBALATON Zoltan switch (ret) { 66058b01325SBALATON Zoltan case -1: 66158b01325SBALATON Zoltan /* No matches in page tables or TLB */ 66258b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_ITLB; 66358b01325SBALATON Zoltan env->error_code = 0; 66458b01325SBALATON Zoltan env->spr[SPR_40x_DEAR] = eaddr; 66558b01325SBALATON Zoltan env->spr[SPR_40x_ESR] = 0x00000000; 66658b01325SBALATON Zoltan break; 66758b01325SBALATON Zoltan case -2: 66858b01325SBALATON Zoltan /* Access rights violation */ 66958b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_ISI; 67058b01325SBALATON Zoltan env->error_code = 0x08000000; 67158b01325SBALATON Zoltan break; 67258b01325SBALATON Zoltan default: 67358b01325SBALATON Zoltan g_assert_not_reached(); 67458b01325SBALATON Zoltan } 67558b01325SBALATON Zoltan } else { 67658b01325SBALATON Zoltan switch (ret) { 67758b01325SBALATON Zoltan case -1: 67858b01325SBALATON Zoltan /* No matches in page tables or TLB */ 67958b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_DTLB; 68058b01325SBALATON Zoltan env->error_code = 0; 68158b01325SBALATON Zoltan env->spr[SPR_40x_DEAR] = eaddr; 68258b01325SBALATON Zoltan if (access_type == MMU_DATA_STORE) { 68358b01325SBALATON Zoltan env->spr[SPR_40x_ESR] = 0x00800000; 68458b01325SBALATON Zoltan } else { 68558b01325SBALATON Zoltan env->spr[SPR_40x_ESR] = 0x00000000; 68658b01325SBALATON Zoltan } 68758b01325SBALATON Zoltan break; 68858b01325SBALATON Zoltan case -2: 68958b01325SBALATON Zoltan /* Access rights violation */ 69058b01325SBALATON Zoltan cs->exception_index = POWERPC_EXCP_DSI; 69158b01325SBALATON Zoltan env->error_code = 0; 69258b01325SBALATON Zoltan env->spr[SPR_40x_DEAR] = eaddr; 69358b01325SBALATON Zoltan if (access_type == MMU_DATA_STORE) { 69458b01325SBALATON Zoltan env->spr[SPR_40x_ESR] |= 0x00800000; 69558b01325SBALATON Zoltan } 69658b01325SBALATON Zoltan break; 69758b01325SBALATON Zoltan default: 69858b01325SBALATON Zoltan g_assert_not_reached(); 69958b01325SBALATON Zoltan } 70058b01325SBALATON Zoltan } 70158b01325SBALATON Zoltan return false; 70258b01325SBALATON Zoltan } 70358b01325SBALATON Zoltan 7046b9ea7f3SBALATON Zoltan static bool ppc_6xx_xlate(PowerPCCPU *cpu, vaddr eaddr, 7055118ebe8SLucas Mateus Castro (alqotel) MMUAccessType access_type, 7065118ebe8SLucas Mateus Castro (alqotel) hwaddr *raddrp, int *psizep, int *protp, 7075118ebe8SLucas Mateus Castro (alqotel) int mmu_idx, bool guest_visible) 7085118ebe8SLucas Mateus Castro (alqotel) { 7095118ebe8SLucas Mateus Castro (alqotel) CPUState *cs = CPU(cpu); 7105118ebe8SLucas Mateus Castro (alqotel) CPUPPCState *env = &cpu->env; 7115118ebe8SLucas Mateus Castro (alqotel) mmu_ctx_t ctx; 712f6f8838bSBALATON Zoltan hwaddr hash = 0; /* init to 0 to avoid used uninit warning */ 713f6f8838bSBALATON Zoltan int type, ret; 7145118ebe8SLucas Mateus Castro (alqotel) 715c29f808aSBALATON Zoltan if (ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, protp)) { 716c29f808aSBALATON Zoltan return true; 717c29f808aSBALATON Zoltan } 718c29f808aSBALATON Zoltan 7195118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_INST_FETCH) { 7205118ebe8SLucas Mateus Castro (alqotel) /* code access */ 7215118ebe8SLucas Mateus Castro (alqotel) type = ACCESS_CODE; 7225118ebe8SLucas Mateus Castro (alqotel) } else if (guest_visible) { 7235118ebe8SLucas Mateus Castro (alqotel) /* data access */ 7245118ebe8SLucas Mateus Castro (alqotel) type = env->access_type; 7255118ebe8SLucas Mateus Castro (alqotel) } else { 7265118ebe8SLucas Mateus Castro (alqotel) type = ACCESS_INT; 7275118ebe8SLucas Mateus Castro (alqotel) } 7285118ebe8SLucas Mateus Castro (alqotel) 7296b9ea7f3SBALATON Zoltan ctx.prot = 0; 730f6f8838bSBALATON Zoltan ret = mmu6xx_get_physical_address(env, &ctx, eaddr, &hash, 731f6f8838bSBALATON Zoltan access_type, type); 7325118ebe8SLucas Mateus Castro (alqotel) if (ret == 0) { 7335118ebe8SLucas Mateus Castro (alqotel) *raddrp = ctx.raddr; 7345118ebe8SLucas Mateus Castro (alqotel) *protp = ctx.prot; 7355118ebe8SLucas Mateus Castro (alqotel) *psizep = TARGET_PAGE_BITS; 7365118ebe8SLucas Mateus Castro (alqotel) return true; 7379e9ca54cSBALATON Zoltan } else if (!guest_visible) { 7389e9ca54cSBALATON Zoltan return false; 7395118ebe8SLucas Mateus Castro (alqotel) } 7405118ebe8SLucas Mateus Castro (alqotel) 74156964585SCédric Le Goater log_cpu_state_mask(CPU_LOG_MMU, cs, 0); 7425118ebe8SLucas Mateus Castro (alqotel) if (type == ACCESS_CODE) { 7435118ebe8SLucas Mateus Castro (alqotel) switch (ret) { 7445118ebe8SLucas Mateus Castro (alqotel) case -1: 7455118ebe8SLucas Mateus Castro (alqotel) /* No matches in page tables or TLB */ 7465118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_IFTLB; 7475118ebe8SLucas Mateus Castro (alqotel) env->error_code = 1 << 18; 7485118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_IMISS] = eaddr; 749*cab21e2eSBALATON Zoltan env->spr[SPR_ICMP] |= 0x80000000; 7505118ebe8SLucas Mateus Castro (alqotel) goto tlb_miss; 7515118ebe8SLucas Mateus Castro (alqotel) case -2: 7525118ebe8SLucas Mateus Castro (alqotel) /* Access rights violation */ 7535118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ISI; 7545118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0x08000000; 7555118ebe8SLucas Mateus Castro (alqotel) break; 7565118ebe8SLucas Mateus Castro (alqotel) case -3: 7575118ebe8SLucas Mateus Castro (alqotel) /* No execute protection violation */ 7585118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ISI; 759ba91e5d0SBALATON Zoltan env->error_code = 0x10000000; 7605118ebe8SLucas Mateus Castro (alqotel) break; 7615118ebe8SLucas Mateus Castro (alqotel) case -4: 7625118ebe8SLucas Mateus Castro (alqotel) /* Direct store exception */ 7635118ebe8SLucas Mateus Castro (alqotel) /* No code fetch is allowed in direct-store areas */ 7645118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ISI; 7655118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0x10000000; 7665118ebe8SLucas Mateus Castro (alqotel) break; 7675118ebe8SLucas Mateus Castro (alqotel) } 7685118ebe8SLucas Mateus Castro (alqotel) } else { 7695118ebe8SLucas Mateus Castro (alqotel) switch (ret) { 7705118ebe8SLucas Mateus Castro (alqotel) case -1: 7715118ebe8SLucas Mateus Castro (alqotel) /* No matches in page tables or TLB */ 7725118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 7735118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSTLB; 7745118ebe8SLucas Mateus Castro (alqotel) env->error_code = 1 << 16; 7755118ebe8SLucas Mateus Castro (alqotel) } else { 7765118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DLTLB; 7775118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 7785118ebe8SLucas Mateus Castro (alqotel) } 7795118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DMISS] = eaddr; 780*cab21e2eSBALATON Zoltan env->spr[SPR_DCMP] |= 0x80000000; 7815118ebe8SLucas Mateus Castro (alqotel) tlb_miss: 7825118ebe8SLucas Mateus Castro (alqotel) env->error_code |= ctx.key << 19; 7835118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) + 784f6f8838bSBALATON Zoltan get_pteg_offset32(cpu, hash); 7855118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) + 786f6f8838bSBALATON Zoltan get_pteg_offset32(cpu, ~hash); 7875118ebe8SLucas Mateus Castro (alqotel) break; 7885118ebe8SLucas Mateus Castro (alqotel) case -2: 7895118ebe8SLucas Mateus Castro (alqotel) /* Access rights violation */ 7905118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSI; 7915118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 7925118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 7935118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 7945118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x0A000000; 7955118ebe8SLucas Mateus Castro (alqotel) } else { 7965118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x08000000; 7975118ebe8SLucas Mateus Castro (alqotel) } 7985118ebe8SLucas Mateus Castro (alqotel) break; 7995118ebe8SLucas Mateus Castro (alqotel) case -4: 8005118ebe8SLucas Mateus Castro (alqotel) /* Direct store exception */ 8015118ebe8SLucas Mateus Castro (alqotel) switch (type) { 8025118ebe8SLucas Mateus Castro (alqotel) case ACCESS_FLOAT: 8035118ebe8SLucas Mateus Castro (alqotel) /* Floating point load/store */ 8045118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_ALIGN; 8055118ebe8SLucas Mateus Castro (alqotel) env->error_code = POWERPC_EXCP_ALIGN_FP; 8065118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8075118ebe8SLucas Mateus Castro (alqotel) break; 8085118ebe8SLucas Mateus Castro (alqotel) case ACCESS_RES: 8095118ebe8SLucas Mateus Castro (alqotel) /* lwarx, ldarx or stwcx. */ 8105118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSI; 8115118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 8125118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8135118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 8145118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x06000000; 8155118ebe8SLucas Mateus Castro (alqotel) } else { 8165118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x04000000; 8175118ebe8SLucas Mateus Castro (alqotel) } 8185118ebe8SLucas Mateus Castro (alqotel) break; 8195118ebe8SLucas Mateus Castro (alqotel) case ACCESS_EXT: 8205118ebe8SLucas Mateus Castro (alqotel) /* eciwx or ecowx */ 8215118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_DSI; 8225118ebe8SLucas Mateus Castro (alqotel) env->error_code = 0; 8235118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8245118ebe8SLucas Mateus Castro (alqotel) if (access_type == MMU_DATA_STORE) { 8255118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x06100000; 8265118ebe8SLucas Mateus Castro (alqotel) } else { 8275118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DSISR] = 0x04100000; 8285118ebe8SLucas Mateus Castro (alqotel) } 8295118ebe8SLucas Mateus Castro (alqotel) break; 8305118ebe8SLucas Mateus Castro (alqotel) default: 8315118ebe8SLucas Mateus Castro (alqotel) printf("DSI: invalid exception (%d)\n", ret); 8325118ebe8SLucas Mateus Castro (alqotel) cs->exception_index = POWERPC_EXCP_PROGRAM; 8339e9ca54cSBALATON Zoltan env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; 8345118ebe8SLucas Mateus Castro (alqotel) env->spr[SPR_DAR] = eaddr; 8355118ebe8SLucas Mateus Castro (alqotel) break; 8365118ebe8SLucas Mateus Castro (alqotel) } 8375118ebe8SLucas Mateus Castro (alqotel) break; 8385118ebe8SLucas Mateus Castro (alqotel) } 8395118ebe8SLucas Mateus Castro (alqotel) } 8405118ebe8SLucas Mateus Castro (alqotel) return false; 8415118ebe8SLucas Mateus Castro (alqotel) } 8425118ebe8SLucas Mateus Castro (alqotel) 8435118ebe8SLucas Mateus Castro (alqotel) /*****************************************************************************/ 8445118ebe8SLucas Mateus Castro (alqotel) 8455118ebe8SLucas Mateus Castro (alqotel) bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, 8465118ebe8SLucas Mateus Castro (alqotel) hwaddr *raddrp, int *psizep, int *protp, 8475118ebe8SLucas Mateus Castro (alqotel) int mmu_idx, bool guest_visible) 8485118ebe8SLucas Mateus Castro (alqotel) { 8495118ebe8SLucas Mateus Castro (alqotel) switch (cpu->env.mmu_model) { 8505118ebe8SLucas Mateus Castro (alqotel) #if defined(TARGET_PPC64) 8515118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_3_00: 8525118ebe8SLucas Mateus Castro (alqotel) if (ppc64_v3_radix(cpu)) { 8535118ebe8SLucas Mateus Castro (alqotel) return ppc_radix64_xlate(cpu, eaddr, access_type, raddrp, 8545118ebe8SLucas Mateus Castro (alqotel) psizep, protp, mmu_idx, guest_visible); 8555118ebe8SLucas Mateus Castro (alqotel) } 8565118ebe8SLucas Mateus Castro (alqotel) /* fall through */ 8575118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_64B: 8585118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_03: 8595118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_06: 8605118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_2_07: 8615118ebe8SLucas Mateus Castro (alqotel) return ppc_hash64_xlate(cpu, eaddr, access_type, 8625118ebe8SLucas Mateus Castro (alqotel) raddrp, psizep, protp, mmu_idx, guest_visible); 8635118ebe8SLucas Mateus Castro (alqotel) #endif 8645118ebe8SLucas Mateus Castro (alqotel) 8655118ebe8SLucas Mateus Castro (alqotel) case POWERPC_MMU_32B: 8665118ebe8SLucas Mateus Castro (alqotel) return ppc_hash32_xlate(cpu, eaddr, access_type, raddrp, 8675118ebe8SLucas Mateus Castro (alqotel) psizep, protp, mmu_idx, guest_visible); 868ba91e5d0SBALATON Zoltan case POWERPC_MMU_BOOKE: 869ba91e5d0SBALATON Zoltan case POWERPC_MMU_BOOKE206: 870ba91e5d0SBALATON Zoltan return ppc_booke_xlate(cpu, eaddr, access_type, raddrp, 871ba91e5d0SBALATON Zoltan psizep, protp, mmu_idx, guest_visible); 87258b01325SBALATON Zoltan case POWERPC_MMU_SOFT_4xx: 87358b01325SBALATON Zoltan return ppc_40x_xlate(cpu, eaddr, access_type, raddrp, 87458b01325SBALATON Zoltan psizep, protp, mmu_idx, guest_visible); 8756b9ea7f3SBALATON Zoltan case POWERPC_MMU_SOFT_6xx: 8766b9ea7f3SBALATON Zoltan return ppc_6xx_xlate(cpu, eaddr, access_type, raddrp, 8776b9ea7f3SBALATON Zoltan psizep, protp, mmu_idx, guest_visible); 878c29f808aSBALATON Zoltan case POWERPC_MMU_REAL: 879c29f808aSBALATON Zoltan return ppc_real_mode_xlate(cpu, eaddr, access_type, raddrp, psizep, 880c29f808aSBALATON Zoltan protp); 881cfd5c128SBALATON Zoltan case POWERPC_MMU_MPC8xx: 882cfd5c128SBALATON Zoltan cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n"); 8835118ebe8SLucas Mateus Castro (alqotel) default: 8846b9ea7f3SBALATON Zoltan cpu_abort(CPU(cpu), "Unknown or invalid MMU model\n"); 8855118ebe8SLucas Mateus Castro (alqotel) } 8865118ebe8SLucas Mateus Castro (alqotel) } 8875118ebe8SLucas Mateus Castro (alqotel) 8885118ebe8SLucas Mateus Castro (alqotel) hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 8895118ebe8SLucas Mateus Castro (alqotel) { 8905118ebe8SLucas Mateus Castro (alqotel) PowerPCCPU *cpu = POWERPC_CPU(cs); 8915118ebe8SLucas Mateus Castro (alqotel) hwaddr raddr; 8925118ebe8SLucas Mateus Castro (alqotel) int s, p; 8935118ebe8SLucas Mateus Castro (alqotel) 8945118ebe8SLucas Mateus Castro (alqotel) /* 8955118ebe8SLucas Mateus Castro (alqotel) * Some MMUs have separate TLBs for code and data. If we only 8965118ebe8SLucas Mateus Castro (alqotel) * try an MMU_DATA_LOAD, we may not be able to read instructions 8975118ebe8SLucas Mateus Castro (alqotel) * mapped by code TLBs, so we also try a MMU_INST_FETCH. 8985118ebe8SLucas Mateus Castro (alqotel) */ 8995118ebe8SLucas Mateus Castro (alqotel) if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 900fb00f730SRichard Henderson ppc_env_mmu_index(&cpu->env, false), false) || 9015118ebe8SLucas Mateus Castro (alqotel) ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 902fb00f730SRichard Henderson ppc_env_mmu_index(&cpu->env, true), false)) { 9035118ebe8SLucas Mateus Castro (alqotel) return raddr & TARGET_PAGE_MASK; 9045118ebe8SLucas Mateus Castro (alqotel) } 9055118ebe8SLucas Mateus Castro (alqotel) return -1; 9065118ebe8SLucas Mateus Castro (alqotel) } 907